Sida 1 av 2
PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 02:40:20
av JimmyAndersson
Det gäller inte specifikt delayrutiner, men jag brukar få felet där.
Jag får följande meddelande:
"MPLINK 4.11, Linker
Copyright (c) 2007 Microchip Technology Inc.
Error - file 'G:\PIC\ASM\PIC18LF1320\UV-box\uvbox.o', section 'DLY_CODE', Symbol '_DLY_CODE_0036' is not word-aligned.
It can not be used as the target of a call or goto instruction.
Errors : 1"
En titt på delay-koden:
Kod: Markera allt
;Delay-rutiner
DLY_VARS UDATA_ACS
d1 RES 1
d2 RES 1
d3 RES 1
DLY_CODE CODE
;Delay 1 sek.
Delay_1s
movlw 0x5A
movwf d1
movlw 0xCD
movwf d2
movlw 0x16
movwf d3
Delay_1s_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_1s_0
nop
return
; Delay 5 ms.
Delay_5ms
movlw 0x0E
movwf d1
movlw 0x28
movwf d2
Delay_5ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_5ms_0
goto $+1
nop
return
; Delay 1 us.
Delay_1us
movlw 0xC6
movwf d1
movlw 0x01
movwf d2
Delay_1us_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_1us_0
goto $+1
nop
return
(Tabbarna blev lite skeva när jag klistrade in koden..)
Jag har testat att byta "goto" till "bra". Har även testat att allokera variablerna till olika delar av minnet, men inget av det har löst problemet.
Men på
den här sajten så hittade jag detta:
"For PIC18, this delay routine will need a little modification to work properly.. the goto $+1 within the delay loops that sometimes appears needs to be changed to goto $+6, since each program word is 2 bytes, and goto is a 4 byte instruction. Also, at the end sometimes goto $+1 is used as a 2 cycle delay, need to use goto $+4 to skip over the whole goto."
Jag får inte ihop matten där riktigt, varför $+1 ska ändras till $+6 och $+1 ska ändras till $+4.
Det fungerar när jag ändrar, men känns just nu lite för osäkert att bara ändra utan att till 100% hänga med på varför just $+6 och $+4 fungerar.
Någon som kan räta ut min rynkade panna?
edit: Hoppsan.. 02:40.. Skulle ha lagt mig för tre timmar sedan, men det är lätt att fastna när man har kul.

Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 03:52:52
av bearing
Varje instruktion är minst 1 word / 2 bytes stor vilket gör att programhopp måste ske i steg av 2. Antagligen kan programräknaren i PIC18 adressera minnet på byte-nivå, vilket gör att goto $+1 (om möjligt) flyttar programpekaren till "mitt i" GOTO-instruktionen. Om det skulle fungera kommer nästa instruktion bli det som ligger i mitten av GOTO-blocket, vilket antagligen är skräp (blir NOP?), men skulle kunna vara en tillåten instruktion.
GOTO-instruktionen är 2 words / 4 bytes, vilket gör att adressen för nästa instruktion ligger 4 bytes bort. Jag förstår dock inte varför $+1 ska ersättas med $+6, så jag gissar att det är en felskrivning; $+4 ska det vara. $+2 ska sannolikt ersättas med $+6 dock (om instruktionen efter GOTO är 2-bytes stor).
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 06:38:45
av Swech
Är det inte bättre att använda riktiga labels istället för massa $+x?
Då blir det inte beroende på processormodell low-mid range osv,
Det blir lättare att läsa programmet också
P.s. sen bör man snart ta fram en lag inom EU att mjukvarufördröjningar förbjuds

Allvarligt, sluta lära ut detta som en metod att få processorer att vänta en stund,
Det är ok upp till ett par ms men inte mer. Vid längre tider bör (läs SKA) de inbyggda timers användas
Swech
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 09:43:17
av vfr
Det är ok upp till ett par ms men inte mer. Vid längre tider bör (läs SKA) de inbyggda timers användas
Absolut!
Helt klart också att dessa $+x är en styggelse. Tyvärr drar man på sig massor av problem med såna lösningar. Lablar är en mycket renare lösning som funkar i alla lägen.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 09:56:59
av sodjan
En PIC16 (som koden var generad till) adresserar flash i 14-bitars "bitar".
D.v.s att $+1 stegar fram 14-bitar (eller ett "word"). Det finns inget
sett att direkt adressera delar av ett word.
En PIC18 har en programräknare som räknar *BYTES*. Normalt hålls
alltid bit0 = "0" så att adresseringen sker i hela words. Däremot t.ex
indexregister och adressregister för direkt flash-läsning kan adressera
bytes, vilket gör flash-tabeller effektivare (kompaktare) på en PIC18
(alla 16-bitar används) än på en PIC16 (8 bitar av 14 används). Det
gör också att man behöver $+2 för att stega ett word framåt.
En anledning till att använda $+n i delay rutinerna är att man kan
automatgenerera två (eller flera) och använda dom direkt utan att få
"multiple defined label"...

Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 10:13:41
av vfr
Jag är helt med på användningen i t.ex makron och liknande. Dom flesta verktyg brukar ha något sätt att lösa även detta. T.ex någon form av temporära lablar. Nu har jag inte kollat vad just MPAsm klarar av, men jag tycker det vore konstigt om den inte kan lösa det. Det är en rätt vanlig funktion i en modern assembler. Och, som sagt, så ger det en massa fördelar att slippa dessa PC-relativa destinationer.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 10:29:07
av sodjan
Nu så var detta inte macron, men i macron kan man ha "local" symboler så
att samma symbol kan användas i flera expansioner av macrot (och en
gång utanför macrot).
Se "4.44 local - DECLARE LOCAL MACRO VARIABLE" i MPASM manualen.
Utanför/utan macron kan man få samma effekt genom att placera koden
i olika moduler (ASM filer) vilka alla har ett eget lokalt name-space (förrutom
de symboler som hanteras via global/extern direktiven).
Man måste komma ihåg att dessa delay rutiner (automatgenererade av en
lite gammal rutin på piclist.com) är väldigt enkla och använder inte alla
finesser i MPASM (vilka kanske inte ens fanns då rutinen konstruerades).
Så döm inte dagens MPASM efter hur dessa delayrutiner är gjorda...

Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 10:35:12
av vfr
Vad syftade du på för automatgenerering av kod? Som får problemet med lika labelnamn. Det mest uppenbara är väl makron, så därför tog jag det som exempel. Och det är ju bra att den varianten verkar stödjas.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 12:06:49
av sodjan
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 13:13:48
av JimmyAndersson
Tack! Nu förstår jag precis.
Just den här kodgeneratorn är som sagt lite gammal, men jag tycker ändå att den är väldigt användbar.
Timers är kanske lite mer "säkert", men i många projekt räcker det att låta PIC-kretsen snurra runt och
räkna en stund för att få en lagom fördröjning.
Swech:
"P.s. sen bör man snart ta fram en lag inom EU att mjukvarufördröjningar förbjuds"
Är dem inte trevliga? Små räknerutiner som gör att gamla DOS-spel går galet fort på moderna datorer..

"FOR t=1 to 1000;next t" gav ungefär en sekunds fördröjning på en Vic20. Samma kod skulle ge en nästan omärkbar
fördröjning i en modern PC, eller för den delen en modern PIC. Utvecklingen går framåt.

Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 13:19:58
av vfr
http://www.piclist.com/techref/piclist/ ... /delay.htm
Ok. Alltså något som ligger helt utanför verktygen i MPLab. Då är jag med.
Å andra sidan så genererar ju den typen av externt verktyg kod som är avsedd att sedan stoppa in i egen källkod. Då lär man ju knappast kunna påverka hur hoppen sker i vilket fall i verktyget. Fast det är ju heller inte speciellt svårt att byta ut mot lablar när man stoppar in det i egen kod. Har man koden framför sig, så ger det sig ganska fort vart den borde hoppa och var man skall stoppa in hopplablarna för att få en mer generisk kod. Det är ju dessutom ganska enkelt att testa att den verkligen genererar samma kod när man stoppat dit lablar istället.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 13:23:37
av jesse
om man absolut vill använda $+n så börja först att skriva dit lablar (swengelska, vad säger man? labels, etiketter, läjblar?) och skriva goto labelnamn, sedan kompilera (assemblera) och kolla i den färdiga koden vilket nummer du fått fram efter goto, om det finns en disassembler som skriver ut koden får du det i klartext goto $+6 eller vad det nu blir. skriv dit siffran i originalkoden och gör om lablarna till kommentarer så vet du vart du hoppar.
men jag skulle nog rekommendera att man undviker $+n helt och hållet och ska en kod upprepas så finns det ju nåt som heter macro.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 13:27:12
av v-g
Hur man än gör så står ju PICen på nåt ställe och snurrar
En del fördelar med att köra i interupt är att man kan göra lite annat medan man väntar på en sak. Man kan även köra SLEEP om strömförbrukning är viktigt, håller dock med om att för det mesta är det krångligare än att bara skriva
CALL XX_ms_Delay.
I nåt projekt minns jag att jag saktade ner PIC:en till lägsta INTOSC under delayen för att spara mesta möjliga och det fungerade faktist. För fast ansluta prylar struntar jag i SLEEP och strömspar det ger ju ändå liksom inget i sammanhanget
Jag har själv en rutin där jag bara skickar in WREG och kan på det sättet justera delayen för massor av olika tillfällen, själva "literalen" som jag skickar in mäter jag upp med MPSIM och sparar i min includefil.
Kod: Markera allt
Delay20uSecs EQU 0x3
Delay40uSecs EQU 0x6
Delay100uSecs EQU 0xE
Sen i koden:
Kod: Markera allt
MOVLW Delay40uSecs ;Wait a while to get pin HIGH or LOW
CALL Delay_Short
Hoppas det tillför något.
Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 15:23:30
av JimmyAndersson
Det var ju ingen dum idé! Enkelt och bra.
Jag testade att ändra $+x till labels:
Kod: Markera allt
Delay_5msb
movlw 0x0E
movwf d1
movlw 0x28
movwf d2
Delay_5msb_0
decfsz d1, f
goto Delay_5msb_1
Delay_5msb_1
decfsz d2, f
goto Delay_5msb_0
goto Delay_5msb_2
nop
Delay_5msb_2
return
I MPSIM tar den koden 24,8µs att köra, och inte 5ms som jag förväntade mig. Men:
Den genererade orginalkoden tar precis lika lång tid, så det verkar fungera att göra såhär.
(5msb = 5ms, version b

)
edit: Hm.. går inte den första och sista goto'n byta mot nop? Måste prova.
edit 2:
Kod: Markera allt
Delay_5msb
movlw 0x0E
movwf d1
movlw 0x28
movwf d2
Delay_5msb_0
decfsz d1, f
nop
nop
decfsz d2, f
goto Delay_5msb_0
nop
nop
return
Gick fint. Mycket renare och snyggare dessutom.

Re: PIC, ASM. Frågetecken kring delayrutiner
Postat: 27 maj 2009, 15:49:31
av sodjan
Notera att "goto $+1" är det samma (tidsmässigt) som "nop, nop",
men tar bara en instruktion istället för två. En smart men kanske
inte så uppenbar optimering. Så "goto $+1, nop" ska bytas till
"nop, nop, nop" för att det ska bli samma exekveringstid.