? i LST-fil

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

? i LST-fil

Inlägg av persika »

PIC16:
Jag tänkte prova på relocatable-mode.
(Tänkte sen också experimentera med pagesel.)
Har därför kört exemplet från Sodjans sida.
Det funkar...

..men varför blir det frågetecken i LST-filen ?

En lösryckt del från LST-filen:

Kod: Markera allt

                      00015 ;
                      00016 ;**********************************************
                      00017 ; Här början den igentligen koden...
                      00018 ; "STARTUP" är definierat i LNK filen till
                      00019 ; h'0000'. Genom att kalla kodsegmentet nedan
                      00020 ; för STARTUP, så läggs det automatisk rätt.
                      00021 ;
                      00022 STARTUP CODE
0000   2???           00023                 GOTO START
0001   0000           00024                 NOP
0002   0000           00025                 NOP
0003   0000           00026                 NOP
0004   2???           00027                 GOTO ISR_ROUTINE
                      00028 ; 
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9127
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Inlägg av AndersG »

relocatable
Var inte hela poängen med relokerbar kod att adresserna bestäms vid länkning? ;)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> ..men varför blir det frågetecken i LST-filen ?

Adresser och andra referenser som länkaren (MPLINK) kommer
att bestämma. Se MAP filen för slutresultatet.

MPASM har inte en aning om vilken adress som START och
ISR_ROUTINE kommer att hamna på.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Inlägg av persika »

Jag lade oxå in pagesel som experiment, där kom oxå frågetecknen.
Jag ville se vad pagesel genererar för kod.

Tänkte mig ha ett bibliotek på adress 0800h h_bib.
Anropar rutin h_mult från huvudprog, med pagesel och call.

LST-fil:

Kod: Markera allt

;*********************************************
; Enkelt blink-a-led, 16F688.
;
;**********************************************
; Files required: P16F688.INC
; 16F688.LKR 
;
;**********************************************
;
;
		list p=16f688
		#include <p16f688.inc>
; 
		__CONFIG _CPD_OFF & _CP_ON & _EC_OSC & _BOD_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_ON
;
;**********************************************
; Här början den igentligen koden...
; "STARTUP" är definierat i LNK filen till
; h'0000'. Genom att kalla kodsegmentet nedan
; för STARTUP, så läggs det automatisk rätt.
;
STARTUP CODE
		goto start
		nop
		nop
		nop
		goto isr_routine
; 
;
;
;**********************************************
; Några variabler.
; De används inte i koden men visar skillanden
; mellan abs och reloc mode. Varablerna läggs i
; "shared/unbanked memory" för att slippa
; banksel...
;
MY_VARS UDATA_SHR
Var1 RES 1
Var2 RES 1
Var3 RES 1
;
;
;**********************************************
; Huvudkoden
; Ingen adress angiven, länkaren lägger
; koden där det är "ledigt"...
;
MAIN CODE

start

		banksel CMCON0
		movlw 	h'07'
		movwf 	CMCON0 ; Stäng av ADC.
	
		banksel trisa
		clrf 	trisa
		clrf 	trisc ; Alla = utgångar.
	
		banksel t1con
		movlw 	b'00110001'
		movwf 	t1con ; Se datablad...
	 
		banksel pie1
		movlw 	b'00000001'
		movwf 	pie1 ; Avbrott från TMR1.
	
		banksel intcon 
		bsf 	intcon, peie
		bsf 	intcon, gie ; Abrott...

loop
		goto loop ; Vänta på avbrott...
 

		pagesel	h_mult
		call h_mult

		nop


;**********************************************
; Interruptkoden.
; Notera användningen av CODE !
;
ISR_ROUTINE CODE

isr_routine

		banksel porta
		comf 	porta, f ; Blinka !!
	
		banksel pir1
		bcf 	pir1, tmr1if
	
		retfie

;*********************************************


;*********************************************
h_bib code	0800h


h_mult
		nop
		nop
		nop
		nop
		nop
		
		return


;*********************************************


		end
 

Så här ser MAP-filen ut:


Kod: Markera allt

MPLINK 4.11, Linker
Linker Map File - Created Fri Nov 21 18:28:50 2008

                                 Section Info
                  Section       Type    Address   Location Size(Bytes)
                ---------  ---------  ---------  ---------  ---------
                  STARTUP       code   0x000000    program   0x00000a
                    H_BIB       code   0x000800    program   0x00000c
                   .cinit    romdata   0x000806    program   0x000004
                     MAIN       code   0x000808    program   0x000030
              ISR_ROUTINE       code   0x000820    program   0x00000e
                  .config       code   0x002007    program   0x000002
                  MY_VARS      udata   0x000070       data   0x000003



                              Program Memory Usage 
                               Start         End      
                           ---------   ---------      
                            0x000000    0x000004      
                            0x000800    0x000826      
                            0x002007    0x002007      
            45 out of 4361 program addresses used, program memory utilization is 1%



                              Symbols - Sorted by Name
                     Name    Address   Location    Storage File                     
                ---------  ---------  ---------  --------- ---------                
                   H_MULT   0x000800    program     static E:\TestPage\TestPage.ASM 
              ISR_ROUTINE   0x000820    program     static E:\TestPage\TestPage.ASM 
                     LOOP   0x00081c    program     static E:\TestPage\TestPage.ASM 
                    START   0x000808    program     static E:\TestPage\TestPage.ASM 
                     VAR1   0x000070       data     static E:\TestPage\TestPage.ASM 
                     VAR2   0x000071       data     static E:\TestPage\TestPage.ASM 
                     VAR3   0x000072       data     static E:\TestPage\TestPage.ASM 



                              Symbols - Sorted by Address
                     Name    Address   Location    Storage File                     
                ---------  ---------  ---------  --------- ---------                
                   H_MULT   0x000800    program     static E:\TestPage\TestPage.ASM 
                    START   0x000808    program     static E:\TestPage\TestPage.ASM 
                     LOOP   0x00081c    program     static E:\TestPage\TestPage.ASM 
              ISR_ROUTINE   0x000820    program     static E:\TestPage\TestPage.ASM 
                     VAR1   0x000070       data     static E:\TestPage\TestPage.ASM 
                     VAR2   0x000071       data     static E:\TestPage\TestPage.ASM 
                     VAR3   0x000072       data     static E:\TestPage\TestPage.ASM 


Man kan inte se vad pagesel generat för kod, men nåt har nog ändå genererats eftersom det skapades en hex-fil
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag ville se vad pagesel genererar för kod.

Varför inte posta just den delen som LST filen som du
undrar över istället för *hela* källkoden (inte så intressant...) ?

> Tänkte mig ha ett bibliotek på adress 0800h h_bib.

Vad menar du med "bibliotek" ?
Och varför just där ? Spelar det någon roll var det ligger ?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Om du vill ha generella rutiner som kan användas från olika applikationer
(d.v.s om det är det som du menar med "bibloiotek") så är det bara att
lägga dom i en separat ASM fil. Den behöver inte heller ligga tillsammans
med varje aktuellt projekt, det är bara att länka in den i projekt-rutan som
en "source code/file".

Naturligstvis ska den inte ha några hårdkodade adresser, utan låt bara
länkaren pussla ihop det hela med resten av applikationen.

Det är dock helt rätt att använda PAGESEL innan CALL till rutinerna så
att det fungerar oavsett var den ligger. Enklast är att fixa en extra liten
fil med olika makron som du gör #INCLUDE på i applikationen med färdiga
makron för att anropa varje bibliotektsruin. Makrot skulle kunna e ut så här:

Kod: Markera allt

call_bibl    macro     bibl_rutin
             pagesel   bibl_rutin
             call      bibl_rutin
             pagesel   $
             endm
Anropet sker sedan med :

Kod: Markera allt

             call_bibl  h_mult
Sedan får du komplettera med GLOBAL i bibl filen och EXTERN i applikationen.
(EXTERN läggs lämpligen i INCLUDE filen...)
Alltså "GLOBAL h_mult" i biblioteksfilen och "EXTERN h_mult" i INCLUDE filen...
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Inlägg av persika »

Nu har jag kollat lite till på detta.
Har sett i rutan view/program-memory i MPLAB att för raderna med frågetecken (med pagesel o call) har det generats kod. Så frid o fröjd med det.

Tack för svar sodjan, macrot du visar är nåt liknande jag tänkt att man behöver för anrop över page-gränserna.

Hur vet man att hela biblioteket hamnar i en page ?
Så att interna call i biblioteket inte behöver använda pagesel.

Min tanke var att man har huvudprogrammet i page 0 och biblioteket i page 1
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> macrot du visar är nåt liknande jag tänkt att man behöver...

Behöver och behöver. Man kan göra exakt samma sak utan macro,
men macron är ett sätt att göra det lite bekvämare och säkrare. Det
blir även bara ett ställe att felsöka om det blir fel med anropen.

> Hur vet man att hela biblioteket hamnar i en page ?

Länkaren (MPLINK) kan inte lägga ett CODE segment så att det splittas
över flera "pages". Så, så länge som du håller din inom samma CODE
segment, så ligger allt inom samma 2 K-ord page i programminnet.
*Vilken* page spelar dock mindre roll. Om du däremot delar upp ditt
bibliotek med flera CODE så kan de hamna i olika pages, men då får
man dela upp det så att det inte blir speciellt många CALL's över gränserna,
så att säga.

> Min tanke var att man har huvudprogrammet i page 0 och biblioteket i page 1

En lite onödig tanke. :-) Låt MPLINK lägga prylarna där den vill.
Dessutom funegrar det ju inte på en single-page (2 Kord eller mindre) modell.
Det är bättre att koda utan förutfattade meningar om hur processorn ser ut.
Förr, då man skrev i "absolut mode" och inte hade tillgång till automatiken
i MPLINK, så fanns det större anledning att manuellt allokera koden i olika
pages, idag spelar det ingen större roll längre...
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Inlägg av persika »

Jag har testat med att lägga in massor av NOP på olika ställen och då kunnat se hur de olika code-segmenten flyttats runt och hamnat på olika page.

Alltså, för att göra helt rätt så ska CALL och GOTO mellan code-segment justera PCLATH före och efter anrop. ex.vis med hjälpa av macro och pagesel. Måste vara så för "goto isr_routine" i exemplet oxå ?


Sen, jag undrar vilket som är bäst...
att länka in biblioteks rutiner eller klipp o klistra in och ha allt i samma asm-fil ?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Måste vara så för "goto isr_routine" i exemplet oxå

Det där är igentligen lite trixigt...
Just när ett interrupt inträffar så vet man ju faktiskt inte
på vilken page man befinner sig, och alltså inte heller hur PCLATH
är inställt. Så igentligen så kan man inte bara sätta ett "goto isr_routine"
direkt vid interrupt vektorn utamn att komplettera med ett
"pagesel isr_routine" också. Dessutom så kan man inte bara sätta om
PCLATH hur som helst utan att spara undan det gamla PCLATH (som användes
i den rutin som blev avbruten av interruptet) först. D.v.s den vanliga koden
för att spara unden W, STATUS och PCLATH, det brukar vara dokumenterat
i kapitlet kring interrupt i varje datablad.

Jag har nog fuskat lite med detta i mina exempel eftersom det ändå
var så lite kod och allt hamnade i page0...

Ett sätt att helt slippa ifrån denna page-hantering är att köra med PIC18
istället, men det är ju lite fusk... :-)


> ...att länka in biblioteks rutiner eller klipp o klistra in och ha allt i samma asm-fil ?

Fördelen med att behålla det i olika delar är att varje fil är sitt
eget "name-space". D.v.a att man kan ha labels som "loop" eller
liknande i varje fil utan att de "krockar". Men kan dessutom ha variabler
som tmp, count eller så i varje fil. Om man lägger ihop allt i
samma fil (antingen genom att klippa ihop filerna eller med #INCLUDE)
så blir allt ett enda name-spece och alla symboler och labels måste vara
unika.

Notera också att man kan styra vilken page ett visst code segement ska
hamna på genom att ge det samma namn som ett "SECTION" i LKR filen.
Man kan lägga dit egna SECTIONS's som i detta exempel (från en
kod för en 16F886):

Kod: Markera allt

// Sample linker command file for 16F886

LIBPATH  .

CODEPAGE   NAME=page0    START=0x0      END=0x7FF
CODEPAGE   NAME=page1    START=0x800    END=0xFFF
CODEPAGE   NAME=page2    START=0x1000   END=0x17FF
CODEPAGE   NAME=page3    START=0x1800   END=0x1FFF
CODEPAGE   NAME=.idlocs  START=0x2000   END=0x2003   PROTECTED
CODEPAGE   NAME=.config  START=0x2007   END=0x2008   PROTECTED
CODEPAGE   NAME=eedata   START=0x2100   END=0x21FF   PROTECTED

DATABANK   NAME=sfr0     START=0x0      END=0x1F     PROTECTED
DATABANK   NAME=sfr1     START=0x80     END=0x9F     PROTECTED
DATABANK   NAME=sfr2     START=0x100    END=0x10F    PROTECTED
DATABANK   NAME=sfr3     START=0x180    END=0x18F    PROTECTED

DATABANK   NAME=gpr0     START=0x20     END=0x6F
DATABANK   NAME=gpr1     START=0xA0     END=0xEF
DATABANK   NAME=gpr2     START=0x110    END=0x16F
DATABANK   NAME=gpr3     START=0x190    END=0x1EF

SHAREBANK  NAME=gprnobnk START=0x70     END=0x7F
SHAREBANK  NAME=gprnobnk START=0xF0     END=0xFF     PROTECTED
SHAREBANK  NAME=gprnobnk START=0x170    END=0x17F    PROTECTED
SHAREBANK  NAME=gprnobnk START=0x1F0    END=0x1FF    PROTECTED

SECTION    NAME=PROG1    ROM=page0      // ROM code space - page0
SECTION    NAME=PROG2    ROM=page1      // ROM code space - page1
SECTION    NAME=PROG3    ROM=page2      // ROM code space - page2
SECTION    NAME=LCDSECT  ROM=page2      // ROM code space - page2
SECTION    NAME=PROG4    ROM=page3      // ROM code space - page3
SECTION    NAME=IDLOCS   ROM=.idlocs    // ID locations
SECTION    NAME=DEEPROM  ROM=eedata     // Data EEPROM
Notera redan med "LCDSECT" 4 rader från slutet.
Sedan kan man ge ett CODE segment detta namn:

Kod: Markera allt

;**********************************************************************
; Subs för HD44780
;
; Nägra temp variabler som används av LCD rutinerna.
; Lägger dom i "shared memory" så slipper vi banksel...
;
LCD_VARS        UDATA_SHR
LCD_TMP1        RES 1
LCD_TMP2        RES 1
;
; Slut på variabler, här kommer koden flr LCD rutinerna.
; Hamnar i SECTION = "LCDSEG"...
;
LCDSECT        CODE
;
lcd_init_hd44780
...
...
Detta gör att LCD-rutinerna styrs till PAGE2...

Så man kan ha en generell/gemensam fil med LCD rutinerna som
styrs mot en SECTION som heter LCDSECT. Sedan får man göra en
lokal kopia av LKR filen för det aktuella projektet och lägga till en
LCDSECT section där man vill ha den. Fördelen är naturligstvis att man
inte behöver ändra den gemensama ASM filen för at flytta koden, bara
den projekt-specifika LKR filen. Före större projekt är det nog vanligt
att man har en speciell variant av LKR filen i alla fall. Man vill kanske
styra lite var man lägger lookup-tabeller och text-strängar o.s.v...

Ja ja, det är en liten vetanskap detta om man börjar gräva i det... :-)
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Inlägg av persika »

Intressant svar! (jag ska spara det.)
För mig som hobby-programmerare känns det just nu som att det är lite överkurs att joxa med linker-script och sections osv.. men det är ju så klart bra att veta om att det går. För mig är det bra bara att kunna använda mer än 2K-word minne i picen, allstå då att anropa subrutiner över page-gränserna. och så klart även då att kunna använda interupt till det oxå.

Är det lätt att flytta program från PIC16 till PIC18 ? eller måste man börja om på ruta 1...
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Det är rätt lätt! Visst behöver du läsa på om en del saker i dokumentationen som är annorlunda, men egentligen är PIC18-miljön som sådan trevligare att jobba i.

Säger han som aldrig egentligen använt PIC18. :) Jag har däremot läst tillräckligt om den för att förstå dom fundamentala skillnaderna och tycker att den verkar trevligare på flera sätt!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

PIC18 har en arkitektur som är lite mer lättarbetad.
Hela minnet är åtkommligt för GOTO och CALL utan paging t.ex.

> För mig är det bra bara att kunna använda mer än 2K-word minne i picen,

Enklast är att bara låta koden hamn var den vill och alltid använda
ett macro som justerar PCLATH wid alla CALL. Visst, det blir ett par extra
och onödiga instruktioner då och då, men ide flesta fall spelar det inge roll.

Att börja anpassa LKR filen är nog överkurs och behövs normalt inte.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Inlägg av persika »

Jag har experimentarat vidare här.
Har gjort ett enkelt makro som automatiskt ska välja rätt anropssätt
för subrutiner, beroende på om anropad rutin ligger på samma page
eller på annan page i förhållande till anropsstället.

Så här:

Kod: Markera allt

;*********************************************
; Macro som automatiskt anropar subrutin på rätt sätt.
; Väljer om PCLATH ska ändras eller ej, beroende på om 
; anropad rutin finns på annan page eller på samma som anropstället.
ACall	MACRO	SubrutinNamn

			IF ($ & 1800h) == ( SubrutinNamn & 1800h ) 
				CALL SubrutinNamn
			ELSE
				pagesel SubrutinNamn
				CALL SubrutinNamn
				pagesel $
			ENDIF
		ENDM
;*********************************************
I absolut-mod funkar det som tänkt, men i relokerbar-mod funkar det inte, får felmeddelandet:

Kod: Markera allt

Error[151]   E:\TESTPAGE\TESTPAGEREL.ASM 41 : Operand contains unresolvable labels or is too complex
Vad göra ? eller det kanske inte går helt enkelt.?

(Rättat skrivfel)
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9127
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Inlägg av AndersG »

I absolut-mod funkar det som tänkt, men i relokerbar-mod funkar det inte,
Tror inte att ett makro fixar det. Makrot expanderas av assemblern. I relokerbar mod så ges adresserna av länkaren. Dvs makrot har ingen aning..
Skriv svar