MPASM, detektera sidbyten (PIC mikrokontroller)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

Satt och fibblade med battmeterns kod och plötsligt dog den, det var litet kul, för det hände i MPSIM med, dvs direkt då jag körde så hoppade den tillbaka till reset. Notera att koden kompilerade OK, utan varningar om sidbyten, men den är mycket nära PICens maxstorlek.

Efter att jag fixad det genom att minska med koden litet så hittade jag ett ställe där den hoppade ut i det okända:

Kod: Markera allt

check_minute
	banksel	mincounter
	decfsz	mincounter,f		; Has one minute elapsed?
	goto	check_minute1		; no, not yet
	movlw	MINCOUNT			; yes, prime counter		
	movwf	mincounter			; and jump to routine
	; fcall goes here!
	fcall	poll
Ändrade goto till lgoto, så spelade det igen, men frågan kvarstår: Hur kunde jag ha ett hopp över sida utan att få en varning? JAg har ej undertryckt dem.

Edit: Äh.. lgoto spelar inte så bra med decfsz....
Senast redigerad av AndersG 24 augusti 2010, 20:55:24, redigerad totalt 2 gånger.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av sodjan »

Alla "hopp" i själva koden är alltid inom samma page (som processorn ser det)
Om man ska till en annan page så måste det sättas upp först genom att sätta
de bitar i PCLATH som aderas till adresen i själva instruktionen innan GOTO
eller CALL görs.

Och det är ju just det som LGOTO och LCALL gör. Alltså samma sak som att
använda en kombination av PAGESEL och CALL/GOTO.

Detta problem blir mindre när man kör med relocatable code, eftersom en
code-section" aldrig spänner över flera pages. Så så länge man gör CALL/GOTO
inom en speciell del av programmet så är allt OK. Sedan kan man göra PAGESEL
innan man hoppar utanför det lokala blocket.

När man kör absolute mode/code så är det lite trickigare eftersom MPASM bara
smetar ut all kod över hela minnet oberoende av page-gränser.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

Och om man kör relokerbar kod så skall man ha flera typ:

MAIN_PROG CODE
...

BLABLA1 CODE

Etc?

Dessutom minnas att LCALL LGOTO etc är multibytesfunktioner och således inte funkar så bra med decfzs etc.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

Nu var det ett tag sedan jag skrev koden, men jag har inga ORGs och inga absoluta minnesdefinitioner, utan

Kod: Markera allt

RESET_VECTOR    CODE    0x0000       ; processor reset vector
	goto    start                ; go to beginning of program

INT_VECTOR      CODE    0x0004       ; interrupt vector location
;**********************************************************************************************************
; ISR
;**********************************************************************************************************
INTERRUPT
; Keep the actual ISR as short as possible.
;
; Arrive here on any interrupt - first save the world...
; 
	movwf   w_temp 			; save off current W register contents
	swapf
Och

Kod: Markera allt

group1		UDATA	0x20	; Note! Some work could be done here to conserve variables. Currently do some routines
							; blagged from various sources use their own temp variables, so they could be conbined into fewer.

cnt			res		1		; Used by bcd2a and b2bcd
pto			res		1
pti			res		1

.
.
INT_VAR     UDATA_SHR    
w_temp      RES     1       ; variable used for context saving 
status_temp RES     1       ; variable used for context saving
pclath_temp RES     1       ; variable used for context saving
fsr_temp	res		1
Men resten av koden är en enda CODE sektion. Du menar således att man skulle bryta ut den i separata CODE-sektioner, utan att för denskull ha multipla filer?
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

och således om en "sida" är 2k på 16f690:

Kod: Markera allt

MPLINK 4.34, Linker
Linker Map File - Created Tue Aug 24 22:43:41 2010

                                 Section Info
                  Section       Type    Address   Location Size(Bytes)
                ---------  ---------  ---------  ---------  ---------
             RESET_VECTOR       code   0x000000    program   0x000002
                   .cinit    romdata   0x000001    program   0x000004
               INT_VECTOR       code   0x000004    program   0x000030
                MAIN_PROG       code   0x00001c    program   0x000f92
                    MAINT       code   0x000800    program   0x000472
                 LCD_CODE       code   0x000a39    program   0x0002a0
                LCD_TEXTS       code   0x000b89    program   0x00022a
            HDQ_CALIBRATE       code   0x000c9e    program   0x000200
                 HDQ_SUBS       code   0x000d9e    program   0x00016a
                 DLY_CODE       code   0x000e53    program   0x000058
  .config_2007_COUNTER2.O       code   0x002007    program   0x000002
                       EE       code   0x002100    program   0x000010
                   GROUP1      udata   0x000020       data   0x000049
                 LCD_VARS      udata   0x000070       data   0x000008
                  INT_VAR      udata   0x000078       data   0x000005
                  DLY_VAR      udata   0x00007d       data   0x000003
Så dyker problemen upp i MAIN_PROG som är 0x000f92 bytes? Således borde den brytas upp ytterligare, eller är jag så trött att jag inte kan tänka? ;)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av sodjan »

> Och om man kör relokerbar kod så skall man ha flera typ CODE segment/block ?

Ja, man kan ha i princip hur många som helst. Varje CODE segment hanteras
av länkaren (MPLINK) som en enhet när den ska allokera koden till programminnet.
Ett CODE segment måste alltid får rum inom samma page, men för övrigt så kan
det hamna i vilken tillgänglig page som helst (men normalt fylls allt på "nerifrån").

> Dessutom minnas att LCALL LGOTO etc är multibytesfunktioner och således inte funkar så bra med decfzs etc.

LCALL, LGOTO och ett antal andra liknande beskrivs i MPASM manueln under
"A.6 12-BIT/14-BIT INSTRUCTION WIDTH PSEUDO-INSTRUCTIONS".
Och visst, precis som med egen definierade "vanliga" macron, så kan det
bli lite konstigt direkt efter en skip-instruktion...

De är inte multibyteinstruktioner, utan mer som macron som via inbyggda funktioner
i MPASM genererar ett antal vanliga instruktiner (t.ex en eller två BCF/BSF för att
sätta rätt page i PCLATH och sedan en GOTO eller CALL). D.v.s att *processorn*
i sig inte har en aning om vad LCALL/LGOTO är för något.

MAIN_PROG code 0x00001c program 0x000f92

Alltså börjar din MAIN_PROG på adres 1C och är F92 stor, med andra ord
slutar den på FAE. Alltså FFF-FAE = 51 (81 decimalt) kvar av page0 efter
att länkaren har placerat in MAIN_PROG.

Och eftersom ingen annat CODE-segment är mindre än x'58' (DLY_CODE) så
kommer alla andra segment att hamna i page1 istället.

Alla CALL/GOTO mellan MAIN_CODE och någon av de andra segmenten kommer
att krascha om man inte hanterar PCLATH korrekt (via PAGESEL eller LCALL/LGOTO).

Exakt vad man ska göra kan inte besvaras generellt. Antingen är inget tidskritiskt
och då kan man köra med PAGESEL (eller LGOTO/LCALL). Eller låt oss säga att t.ex
DLY_CODE anropas väldigt mycket, då skulle man kunna fixa så att de rutinerna
t.ex ligger i MAIN_CODE eller något liknande.

Är det enbart "ren" kod i MAIN_CODE ? Inga lookup-tabeller eller liknande ?
Dessa bryts lämpligen upp och tvingas upp i page1 för att frigöra utrymme
för vanlig exekverbar kod i page0. Normalt behöver man i alla fall ha kod vid
anrop av lookup-tabeller (d.v.s RETLW-tabeller) för att hantera PCLATH, så
det blir inget extra overhead. Samma sak om man läser tabeller via EExxx registren,
det blir ingen extra overhead för att kod i page0 läser en tabell i page1, EEADR/EEADRH
adresserar direkt hela minnet.

Ett helt annan "lösning" är att köra med PIC18 när man får kod > 2Kord... :-)
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

De är inte multibyteinstruktioner, utan mer som macron som via inbyggda funktioner
i MPASM genererar ett antal vanliga instruktiner (t.ex en eller två BCF/BSF för att
sätta rätt page i PCLATH och sedan en GOTO eller CALL). D.v.s att *processorn*
i sig inte har en aning om vad LCALL/LGOTO är för något.
Sorry, jo, jag uttryckte mig fel, vad jag menade var att macrot genererar flera instruktioner och då kommer ju en btfsc tex att "hamna mitt i"
Alltså börjar din MAIN_PROG på adres 1C och är F92 stor, med andra ord
slutar den på FAE. Alltså FFF-FAE = 51 (81 decimalt) kvar av page0 efter
att länkaren har placerat in MAIN_PROG.
Ah.. Tänkte fel, hade fått för mig att 16F690 bara hade 2k, men den har ju 4k....
Är det enbart "ren" kod i MAIN_CODE ? Inga lookup-tabeller eller liknande ?
Tyvärr, jo. Har flera lookuptabeller, men de är kodade "page safe", men visst kanske man kunde bryta ut dem.

Skrev ju denhär koden för 2 år sedan och den har snurrat snällt i båten, men nu skulle jag göra litet justeringar och det är fascinerande vad man glömmer på två år :)

Håller med om att koden är på gränsen för en 16f690, men jag orkar inte göra ett nytt kort...

Tack igen förresten!
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9126
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: MPASM, detektera sidbyten (PIC mikrokontroller)

Inlägg av AndersG »

Och om man är helt blind så kan man ju se vad PICKIT2 säger:

Kod: Markera allt

Programming Program Memory (0x0 - 0x7F3)
Programming Program Memory (0x800 - 0xE77)

Kod: Markera allt

                  Section       Type    Address   Location Size(Bytes)
                ---------  ---------  ---------  ---------  ---------
             RESET_VECTOR       code   0x000000    program   0x000002
                   .cinit    romdata   0x000001    program   0x000004
               INT_VECTOR       code   0x000004    program   0x000030
                MAIN_PROG       code   0x00001c    program   0x0009d4
                    MAINT       code   0x000506    program   0x000472
                 HDQ_SUBS       code   0x00073f    program   0x00016a
               MATH_STUFF       code   0x000800    program   0x0002ce
             BQ2018_STUFF       code   0x000967    program   0x000274
                LCD_TEXTS       code   0x000aa1    program   0x00022a
                 LCD_CODE       code   0x000bb6    program   0x00021e
            HDQ_CALIBRATE       code   0x000cc5    program   0x000204
             STRING_STUFF       code   0x000dc7    program   0x000104
                 DLY_CODE       code   0x000e49    program   0x000058
Då ser jag ju faktiskt i vilken "page", vilken rutin hamnar.

Tror inte jag läst MAP-filer så noga sedan jag programmerade i M80 :)
Skriv svar