hi!

hebben jullie tips hoe je de programmacode die verdeelt is over een aantal paginas , best kunt programmeren?

zo heb ik miserie met tabellen .
ik programeer in asm in mplab

als ik een tabel aanroep via een CALL , kan het gebeuren dat de pcl wel correct is maar niet de pclatch

ik heb mijn tabel ( een subroutine) nu helemaal bovenaangezet , zodat het zowat in pagina nul komt te staan

maar vanzodra ik nieuwe subroutines bijzet , valt gans het programma in panne , (zelfs routines die niet gebruikt zijn in het hoofdprogramma)

dus ik vermoed dat de subroutine de boel , laat verschuiven in mijn paginas

iemand tips ?

Als je tabellen gebruikt moet je wel zorgen dat PCLATH goed staat voor het adres in de tabel dat je wilt lezen...
Zie AN556 voor uitgebreide info: http://ww1.microchip.com/downloads/en/AppNotes/00556e.pdf

Op 27 maart 2007 00:05:49 schreef Extragroot:
hi!

hebben jullie tips hoe je de programmacode die verdeelt is over een aantal paginas , best kunt programmeren?

zo heb ik miserie met tabellen .
ik programeer in asm in mplab

als ik een tabel aanroep via een CALL , kan het gebeuren dat de pcl wel correct is maar niet de pclatch

ik heb mijn tabel ( een subroutine) nu helemaal bovenaangezet , zodat het zowat in pagina nul komt te staan

maar vanzodra ik nieuwe subroutines bijzet , valt gans het programma in panne , (zelfs routines die niet gebruikt zijn in het hoofdprogramma)

dus ik vermoed dat de subroutine de boel , laat verschuiven in mijn paginas

iemand tips ?

Ik weet niet precies wat je bedoelt met 'een tabel aanroepen'.
Maar wat je in de gaten moet houden:
1. Als je iets gaat doen waarmee je PCL on the fly aanpast, met je eerst PCLATH goed vullen.
2. Als je een tabel oid gebruikt waar je 'in' springt (bijvoorbeeld voor GOTO's of RETLW's), mag die geen paginagrens overschrijven. De instructie waar je op uitkomt mag uiteraard wel weer buiten deze pagina liggen.
Dus controleer of het begin en einde van de sprongtabel binnen dezelfde pagina liggen.

Ik begin de sprong tabel gewoon standaard in pagina 2.
Pclath aanpassen en jumpen maar.
Zit je met je pagina over de grens dan moet je ff een stukkie code ertussen zetten dat eerst de sprong controleerd en indien nodig pclath aanpast.

je kan als ik me niet vergis alleen tabellen en andere indirecte adresseringen op het eerste blad hebben staan.

ik begin me tabellen meestal hier
org 000H

en me code pas hier
org 0100H

Op 27 maart 2007 19:57:14 schreef mts plus:
ik begin me tabellen meestal hier
org 000H

Heel knap, want daar zit de reset vector van de PIC. Dat zal dus wel een ander getal zijn.
Maar er zijn twee grenzen waar je rekening mee moet houden:
1) De 256 byte grens wanneer je "computed gotos" gebruikt. Dat is met de instructie addwf PCL,F. Zo'n tabel mag een 256 byte grens niet passeren en je moet PCH laden met de correcte waarde. Met MPASM kan je met macro's foutmeldingen genereren wanneer dit gebeurt. (Handig wanneer je wat code invoegt en de tabel daardoor verschuift)
2) de 2K grens. Hier heb je last van met call en goto instructies, ook hier weer geld: eerst PCLATH laden. Maar ik denk dat er weinig C.O.'ers zijn die zulke grote assembly programmas maken.

euhm je hebt gelijk.

zit te suffen

Op 27 maart 2007 20:27:25 schreef JoWi:
[...]2) de 2K grens. Hier heb je last van met call en goto instructies, ook hier weer geld: eerst PCLATH laden. Maar ik denk dat er weinig C.O.'ers zijn die zulke grote assembly programmas maken.

Yep, vooral macro's maken het leven makkelijk.
Volgens mij heb je géén last van de 2K grens. Waar je last van zou kunnen krijgen is de 4K grens.
Tot 4K kun je voor zover ik weet doen wat je wil met je calls en goto's (even zo uit het hoofd, meen dat ik zoiets had zien staan in de 16F648A datasheet...)

Nope, de grens is 2K.
Kijk in het datasheet. Je kan het ook uit de instructiedecodering halen: 11 bits in de opcode zijn gereserveerd voor het adres.

Er is vaak een misverstand over wat nu een geheugen 'page' is. Bij tabellen wordt soms een 256 byte geheugen blok als page gezien, wat eigenlijk niet juist is. Een page is 8k bytes oftewel 4k (14 bits)words.

Met tabellen en PCLATH is er een probleem als er in de tabel in de program counter een 'roll-over' plaats vindt van 0xFF naar 0x00 tussen de instructie aan het begin van de tabel, welke de program counter wijzigt (ADDWF PCL), en de eigenlijke return waarde in de tabbel.

In dat geval moet PCLATH worden aangepast, omdat anders de computed goto op een verkeerd adres uitkomt.

Bij overschrijden van een echte page (8/4k) komt er een extra probleem bij. Bij return van een goto/call moet dan de originele waarde van PCLATH worden hersteld, omdat anders problemen optreden bij volgende goto/calls in page 0
(In plaats van in page 0 zouden die dan in page 1 terecht komen...)

Op 27 maart 2007 23:08:47 schreef Arco:
Er is vaak een misverstand over wat nu een geheugen 'page' is. Bij tabellen wordt soms een 256 byte geheugen blok als page gezien, wat eigenlijk niet juist is. Een page is 8k bytes oftewel 4k (14 bits)words.

Met tabellen en PCLATH is er een probleem als er in de tabel een 'roll-over' plaats vindt van 0xFF naar 0x00 tussen de instructie aan het begin van de tabel, welke de program counter wijzigt (ADDWF PCL), en de eigenlijke return waarde in de tabbel.

In dat geval moet PCLATH worden aangepast.

Bij overschrijden van een echte page (8/4k) komt er een extra probleem bij. Bij return van een goto/call moet dan de originele waarde van PCLATH worden hersteld, omdat anders problemen optreden bij volgende goto/calls in page 0
(In plaats van in page 0 zouden die dan in page 1 terecht komen...)

Inderdaad.
Dus samengevat (ik herhaal wat ik eerder al zei):
- blijf je onder de 4K code, heb je sowieso geen problemen met je goto's of calls.
- als je sprongtabel een 256-grens overschrijdt heb je een probleem; dus altijd controleren (via compiler-instructies) of je een grens overschrijdt
- bij springen door aanpassing van PCL (ADDWF PCL) eerst PCLATH goed vullen

dus in principe moet je compileren
en daarna telkens eens kijken in
mplab <>>vieuw>>program memory

en dan u tabel zoeken , e
en dan eventueel uw routines verschuiven

en ook dus uw pcl en pclacht mischien best opslaan in een ramlokatie als buffer , en als je tabel-routine is afgelopen ,
dan je oude pcl en pclatch weer inladen ?

ter info mijn tabel (let niet op de inhoud)
_____________________________
tabel
banksel PCL
addwf PCL,1
retlw 'z'
retlw 'o'
retlw 't'
retlw 't'
retlw 'e'
retlw 'k'
retlw 'o'
retlw 't'
retlw 'z'
retlw 'o'
retlw 't'
retlw '#'
return
_______________________

Of je definieert een macro en gebruikt die, tezamen met de compiler om het voor je te laten uitrekenen:


CHECK_BOUNDARY MACRO FROM
	local TableEnd
TableEnd
	IF HIGH(FROM) != HIGH(TableEnd)
       ERROR   ">>> Table/jump " FROM " crosses page boundry in computed addressing/jump"
    ENDIF
	ENDM

...

tabel
	; banksel PCL -> niet nodig             
	; ... bewaar W ergens
	; bijv: movwf  TEMP_W
        ;
	movlw  HIGH(tabel)
	movwf  PCLATH
	; ... haal W weer op
	; bijv: movfw  TEMP_W
        ;
	addwf  PCL,1
	retlw  'z'
	retlw  'o'
	retlw  't'
	retlw  't'
	retlw  'e'
	retlw  'k'
	retlw  'o'
	retlw  't'
	retlw  'z'
	retlw  'o'
	retlw  't'
	retlw  '#'
	return
CHECK_BOUNDARY tabel

Is makkelijker dan compileren en handmatig alle tabellen checken :-)

dus in principe moet je compileren en daarna telkens eens kijken in mplab <>>vieuw>>program memory

Nee, dat hoeft niet. Als je de code in example 5 in AN556 gebruikt, wordt automatisch de PCLATH oogehoogd als er een 'page crossing' is...
(Je hebt er dan geen omkijken meer naar...)

Nog wel een waarschuwing:

- Uiteraard nooit tabellen op adres 0x000 omdat dat de reset vector is
- Ook niet op adres 0x004, dit is de interrupt vector. Zet hier altijd een retfie instructie, ook als je geen interrupts gebruikt. Dit voorkomt vervelende en moeilijk op te sporen fouten als je (misschien per ongeluk) een interrupt inschakelt...

Op 27 maart 2007 23:08:47 schreef Arco:
Er is vaak een misverstand over wat nu een geheugen 'page' is. Bij tabellen wordt soms een 256 byte geheugen blok als page gezien, wat eigenlijk niet juist is. Een page is 8k bytes oftewel 4k (14 bits)words.

Vooruit, laat ik het nog maar een keer proberen:

De grens is 2K woorden.

Over bytes kan je eigenlijk niet spreken want de breedte is 14 bit (en niet 16). Dit is een gevolg van de Harvard architectuur. Maar aangezien gewoon de verkeerde info gegeven wordt en het naslaan van datasheets teveel werk is hier wat stukkies uit het PIC16F648 datasheet:
http://www.uploadarchief.net/files/download/pclath.png
En ook bij de beschrijving van de goto staat het er nog een keer:
http://www.uploadarchief.net/files/download/pclath2.png
Met 11 bits kan je maar 2K adresseren!!!!!!

En als je nu de application note waar naar verwezen wordt (AN556) eens goed bestudeerd zie je daar het volgende:
http://www.uploadarchief.net/files/download/pclath3.png

Let met name op het stuk in het grijze kader |:(

Klopt, foutje... :o

8k/4k moet natuurlijk zijn: 4k/2k in bovenstaande...

Is eenvoudig te doen , was makkelijker dan ik dacht , en je moet logsiche nadenken

de fouten die ik had waren onoplettendheden
zoals : mijn label 'tabel' stond een lijntje voor de org0X320

en ook moet je erop letten dat je dan de bankselctie goed zet vd pclatch

THX voor de nuttige info

ps: http://support2.microchip.com/KBSearch/KB_Ticket.aspx?ID=Tt6UJ9A0004X9

ps2 : mijn werkende asm

___________
laad
BANKSEL PCLATH
movlw HIGH tabel ;STAAT OP ORG0Xà320?HIGHERODERBYTE IS 03
movwf PCLATH
BANKSEL PORTB
movf aanwijzer,w ; 0e element ophalen

call tabel

;;;;;;;;;;;
ORG 0x0320

tabel

banksel PCL
addwf PCL,1
retlw 'z'
retlw 'o'
retlw 't'
retlw 't'
retlw 'e'
retlw 'k'
retlw 'o'
retlw 't'
retlw 'z'
retlw 'o'
retlw 't'
retlw '#'
return
____________________________

[Bericht gewijzigd door Extragroot op ]

Wat betreft je 'werkende code':
Dit is alleen waar als je een vast adres gebruikt voor de tabel, en er geen 256 byte grens wordt overschreden.
(Als je bijvoorbeeld het tabel adres verandert in 0x1FF of 0x2FF, dan werkt het niet meer...)

Dit is meestal geen probleem als je nog genoeg ruimte vrij hebt in het programma geheugen. Als het wat voller wordt, dan wordt het vaak 'schuiven' met de tabel naar een vrij plaatsje. Hetzelfde geldt als de tabel langer wordt. Je moet dan uitkijken dat 'ie niet over de 256 byte grens heengaat...

Simpeler is het om zoals gezegd de code uit AN556 te gebruiken, zodat het niet uitmaakt waar de tabel ergens staat...


laad
        movlw   LOW tabel      ;Laad tabel low address byte
        addwf   aanwijzer,w    ;Add offset
        movlw   HIGH tabel     ;
        btfsc   status,c       ;Roll-over? (carry is set)
        addlw   1              ;Ja, increment hi address byte
        movwf   PCLATH         :Save hi byte in PCLATH 
        movf    aanwijzer,w

        call    tabel 
        
        .
        .
        .
        .

tabel
        addwf PCL,f
        retlw 'z'
        retlw 'o'
        retlw 't'
        retlw 't'
        retlw 'e'
        retlw 'k'
        retlw 'o'
        retlw 't'
        retlw 'z'
        retlw 'o'
        retlw 't'
        retlw '#'

De RETURN aan het eind van de tabel heeft geen nut, deze kan weg. Evenals de BANKSEL voor PCL of PCLATH, omdat die in alle banks zijn gemapt...

[Edit]
Je kunt de tabel trouwens eenvoudiger schrijven:


tabel
        addwf   PCL,f
        dt      "zottekotzot#"

(is alleen korter en overzichtelijker, maakt in asm code geen verschil...)
[/edit]