interrupt med roliga fel

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Markus
Inlägg: 105
Blev medlem: 4 november 2005, 02:35:06
Kontakt:

ok, tack så mycket men

Inlägg av Markus »

Det jag skulle vilja ha hjälp med i först hand är Hur etiketter sitter i hopp med varandra i koden som sodjan har skrivit.
tex varför jag skriver ISR_code code tillexempel. kan man inte ta bort etiketten varför måste jag ha den där när den ändåse inte har någon funktion i koden. Hur tänker jag när jag skapar etiketterna.sedan tex så fattar jag inte varför jag måste ha ettiketten ISR_code med kodraden code när programmet anropar etikketten isr_start. Det är själv programmeringen som är problemet.
hur jag lägger upp själva strukturen. detta vill jag vet om jag vill tex ha en avbrotts rutin till.

Vet ni någonstans man kan läsa om denna typ av programmering relocatable code. Jag vill lära mig att förstå och kunna bygga med hjälp av
relocatable code.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

"ISR_code code" betyder:
"ISR_code" är ett namn/label, det kunne likaväl ha stådd "Hugo" eller "KarlBertil" eller annat beskrivande. Nu råkar det vara "standart" att kalla en Interrupt Service Rutine för "ISR" och det är inte data med kod så det är ett väl vald namn som tydligt beskrivar vad det har med att göra.

"code" betyder att det ska ligga i kod-segmentet....nånstans. Det är alltså intte en uppslagstabell eller annan konstant men det är kod = code på utrikisk.

Alltså anger den statement att "ISR_code" är en programsnudd. That's it.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Kaggen har helt rätt om att återanvända kod, bara med den lilla
kommentaren att man inte ofta delar koden via OBJ filerna så
som Kaggen beskriver det. Problemet med det är att man tappar all
möjlighet till "assembly time calculations", d.v.s t.ex att om man har en
USART rutin, så vill man kanske i sin huvudrutin tala om t.ex vilken
baud rate man skall köra med (via en SET av en assembler symbol).
Sedan kan man med kod i USART rutinen beräkna vilka värden det
blir för baudrate registren i PIC'en. Detta går inte om man har
förassemblerar kod, vilket gör att det knappast är något som gör så.

Man har sitt "kod-bibliotek" i form av assembler källkod som sedan
assembleras tillsammans med varje applikation.

En annan viktig fördel med reloc-code, är att allokeringen av RAM
variabler sker av länkaren. D.v.s att det t.ex i den gemensamma
USART rutinen inte finns några fasta RAM adresser, utan dessa
allokeras vid assembleringen tillsammans med varje applikation,
och kan naturligtsvis bli olika adresser från app till app beroende på
vilka andra RAM variabler som varje applikation använder. Utan denna
möjlighet blir det snabbt en riktig röra att hålla reda på vilka
adresser som olika gemensamma rutiner använder.

Se även : http://www.jescab.se/Rellocmode.html

Sen när det gäller CODE...

Visst, för att göra det tydligt hade jag kanske med fler CODE
än vad som (i detta fall) var nödvändigt, men det var bara för
att visa på principen, och för att MAP filen skulle bli lite mer "intressant".

Varje CODE talar om för länkaren (MPLINK) att "här kommer en ny
kodsnutt som du (länkaren) kan placera som du vill i programminnet".

> Det är själv programmeringen som är problemet.
> hur jag lägger upp själva strukturen.

Du fick ju en "mall" av mig. Inte perfekt, men duger att bygga vidare på.

> detta vill jag vet om jag vill tex ha en avbrotts rutin till.

Här är det lite begreppsförvirring, i princip finns det bara en (1) avbrottsrutin.
I denna får man sedan kolla (via xxIE/xxIF flaggorna) vilken källa
(ADC/USART/Timer o.s.v) som triggade avbrottet och anropa
(GOTO eller CALL beroende på hur man vill ha det) olika rutiner
som "tar hand om" avbrottet från respektive källa.

Men kanske viktigast, sätt igång någongång !! :-)
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

Markus: Jag tror vi talar om lite olika saker.

Jag tror vi blandar ihop labels för kodsegment (code) och labels för funktioner och funktionsanrop. Funktioner och funktionsanrop har i sig inget att göra med code segment.

I ett "code" segment kan du ha flera funktioner åtskiljda med labels, i princip hur många som helst.

Om man bara har en källkodsfil, alltså en .asm fil, i sitt projekt så finns det ingen anledning (vad jag kan se) att köra relocatable kod. Någon får gärna rätta mig om jag har fel.

Relocatable kod har man mest nytta av om man har flera källkodsfiler och vill sätta ihop dem till en slutgiltig binär objektfil. Du har då ett eller flera code-segment i varje källkodsfil. Detta för att linkern, det program som skall para ihop alla kodsegment till ett stort program, skall kunna pussla ihop segmenten utan att dom går in i varandra och för att korsreferenser mellan olika funktioner och variabler i olika filer skall funka.

Du behöver förresten bara labels för code segmenten om du skall ha mer än ett. Tänk på att "code" inte får stå längst till vänster på en rad utan måste vara en tab in.

Det kanske är bättre att du skippar relocatable kod tills det du verkligen behöver det, när dina projekt blir så stora att du vill splitta dem i flera källkodsfiler.


Hur du kollar flera interrupt är ju relativt enkelt i en funktion (generell psuedo kod):

Kod: Markera allt

IRQ_handle

 ; Spara undan register kod här!

 btfsc   INTCONX,IRF1  ; Är Interrupt 1 satt?
 call    HANDLE_IRQ1  ; Hantera IRQ 1 isåfall

 btfsc   INTCONX,IRF2  ; Är Interrupt 2 satt?
 call    HANDLE_IRQ2  ; Hantera IRQ 2 isåfall

 btfsc   INTCONX,IRF3  ; Är Interrupt 3 satt?
 call    HANDLE_IRQ3  ; Hantera IRQ 3 isåfall

 btfsc   INTCONX,IRF4  ; Är Interrupt 4 satt?
 call    HANDLE_IRQ4  ; Hantera IRQ 4 isåfall

 btfsc   INTCONX,IRF5  ; Är Interrupt 5 satt?
 call    HANDLE_IRQ5  ; Hantera IRQ 5 isåfall

; o.s.v. o.s.v.
; Återställ register kod här

 reti 
Där INTCONX är interrupt registret för din processor och IRF1-IRF5 är interruptflaggorna du är intresserad av. Du får kolla i databladet för din processor vad de skall ha för riktiga namn beroende på vad du vill göra.

mvh Mats
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> I ett "code" segment kan du ha flera funktioner åtskiljda med labels, i princip hur många som helst.

Nja, en label används bara som en "target" för en GOTO eller CALL.
Att man som programmerare väljer att kalla en kodsnutt för en funktion
(eller subrutin eller whatever) är inget som MPASM vet något om. Det är
helt upp till hur man "ser" på sin kod som programmerare.

Det är i princip ingen skillnad på en label som används som "entry point"
till din subrutin, och en som används *inom* subrutinen. En subrutin/funktion
kan även (inte ovanligt) ha flera "entry points", d.v.s att man gör CALL till
lite olika ställen och får lite olika "funktion" från funktionen.

> Om man bara har en källkodsfil, alltså en .asm fil, i sitt projekt så
> finns det ingen anledning (vad jag kan se) att köra relocatable kod.
> Någon får gärna rätta mig om jag har fel.

Gärna ! :-)

I Absolute Mode finns det en gräns för "path" till sitt projektbibliotek på 62 tecken.
Det finns inte i Relocatable Mode.
Et problem om t.ex vill ha sina filer under "My documents"...

All utveckling från Microchip sker på reloc delen. Abs mode delen kommer sannlikt att försvinna med tiden.
För PIC24/PIC30/PIC33 (16-bitars serierna) finns det ingen Abs Mode alls...

Det är inte *svårare* att skriva kod i Reloc Mode. Bara lite annorlunda...

Det är lättare att "växa" i projektet, när koden behöver delas upp o.s.v.

Det är lättare att dela gemensamma funktioner mellan projekt.

Om man delar upp koden i flera moduler (= filer) så kan man ha samma
label (t.ex "loop" eller liknande) på flera ställen (i varje modul).

Det blir generellt "snyggare" kod (vad nu det är :-) )

> Du behöver förresten bara labels för code segmenten om du skall ha mer än ett.

(Per kodmodul alltså. (En modul = en ASM fil))

Korrekt, men MAP filen blir jäkligt tråkig att läsa... :-)
Min rekomendation är att man alltid sätter ett *eget* namn på varje segment så att de blir enkla att hitta i MAP filen.

> Det kanske är bättre att du skippar relocatable kod tills det du verkligen
> behöver det, när dina projekt blir så stora att du vill splitta dem i flera
> källkodsfiler.

Det kanske är tydligt att jag inte håller med... :-)

Angående ditt kod exempel så har jag bara ett par mindre kommenterar...

> ; Spara undan register kod här!
> ; Återställ register kod här

Behövs inte på PIC18 när man kör med 1 interrupt prioritet (vilket är normalt).
En av anledningarna att interrupt går snabbare på PIC18 än på PIC16...

> btfsc INTCONX,IRF1 ; Är Interrupt 1 satt?
> call HANDLE_IRQ1 ; Hantera IRQ 1 isåfall
>
> btfsc INTCONX,IRF2 ; Är Interrupt 2 satt?
> call HANDLE_IRQ2 ; Hantera IRQ 2 isåfall

Bör vara något i stil med :

> btfss INTCONX,IRE1 ; Är Interrupt 1 enablat ?
> goto check_int2 ; Nej, kolla INT2
> btfsc INTCONX,IRF1 ; Är Interrupt 1 triggat ?
> call HANDLE_IRQ1 ; Hantera IRQ 1 isåfall
>
>check_int_2
>
> btfss INTCONX,IRE2 ; Är Interrupt 1 enablat ?
> goto check_int3 ; Nej, kolla INT3.
> btfsc INTCONX,IRF2 ; Är Interrupt 1 triggat ?
> call HANDLE_IRQ2 ; Hantera IRQ 1 isåfall
>

o.s.v.

D.v.s att man även måste kolla "E" flaggan, inte bara "F" flaggan.
Ibland vill man t.ex fördröja ett visst interrupt, och då clearar men
resp "E" flagga, säg IRE1. Med din kod kan man få ett "falsk" interrupt,
genom att t.ex INT2 triggar, men koden kommer att "fasta" på INT1,
p.g.a av att "E" flaggan inte kollas. Senare när man vill att INT1 skall
trigga igen, sätter man "E" flaggan igen...

> reti

Bör vara "RETFIE FAST" för att få återladdning av WREG/STATUS/BSR från shadow registren.
Kaggen
Inlägg: 432
Blev medlem: 29 januari 2005, 03:06:02

Inlägg av Kaggen »

sodjan:

Jo, du har rätt. Det är bättre att lära sig rätt från början.

Just när det gäller relocateble och start + interrupt vektorer (0x000 - 0x004) så är dock linkerfilen lite olika för olika processorer. Somliga har en egen codepage för start och interruptvektor, vilket gör att du måste starta ett nytt kodsegment direkt efter irq-vektorn, annars får man felmeddelande från linkern.

Angående interrupt:

Aha! Jag visste inte att irq-flaggan sattes trots att just det irq:et inte var enableat (ursäkta svengelskan). Det skulle kunna kostat någon timmes felsökning. :roll:

Man lär sig något nytt var dag. :)

mvh Mats
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Aha! Jag visste inte att irq-flaggan sattes trots att just det irq:et inte var enableat

Precis !
Ibland har man kod där ett avbrott från ett interrupt inte "passar".
Antingen inga avbrott alls och då kan man stänga av med den globala
enable flaggan (GIE), eller så bara från en viss källa, och då kan man
stänga av med xxIE flaggan för just den källan.

Ibland kan man få konflikt mellan ISR'en som skriver i ett par
gemensamma variabler, och den main rutin som läser samma
variabler. Man kanske vill läsa alla 3-4 variabler utan att det har
skett någon ändring under tiden.

I båda fallen sätts dock alltid xxIF flaggan, och så snart men "slår på"
GIE eller xxIE igen (och det har "hånt något" under tiden den/de var
avtängd) så får man ett interrupt direkt. Om man inte vill ha det fördröjda
interruptet alls, så får man lägga dit en extra BCF xxIF innan BSF xxIE...

Det är också av denna anledning som man måste/bör kolla xxIE flaggan
i ISR'en, annars kan man köra en rutin av misstag som man trodde var
avstängd. :-)

Sen stämmer det att det finns lite olika uppfattning hurvida de LKR
filer som kommer med MPLAB är perfekta, just det du pekar på är
den vanligaste invändningen. Man måste alltså lägga en GOTO på
interrupt vektorn, fast det igentligen inte är något som hindrar att man
lägger hela ISR'en där direkt. Personligen tycker jag att man kan börja
med att skriva så att det passar LKR filerna som de ser ut, och sedan när
man har lärt sig hur de fungerar (och när det finns behov!) justera dom
efter egen "smak"...
Skriv svar