Both sides previous revisionPrevious revisionNext revision | Previous revision |
en:avr:interrupts [2010/02/28 14:32] – mikk.leini | en:avr:interrupts [2020/07/20 09:00] (current) – external edit 127.0.0.1 |
---|
====== Interrupts ====== | ====== Interrupts ====== |
| |
Katkestuse (inglise keeles //interrupt//) saavad AVR-il tekitada loendurid, andmesideliidesed, analoog-digitaalmuundur, komparaator, spetsiaalsed sisend-väljundviigud ja mitmed muud funktsioonid, olenevalt kontrollerist. Igat katkestust saab lubada või keelata seda genereerivas üksuses. Olenemata katkestuse lubamisest või mitte, on iga katkestuse jaoks vastavas kontrolleriüksuses 1-bitine andmeväli (lipuke, inglise keeles //interrupt flag//), mis märgitakse katkestust põhjustava sündmuse toimumisel tõeseks. Kui toimub nimetatud andmevälja muutumine ja katkestus on lubatud, hakkab kontroller täitma koodi, mis oli katkestuse toimumisel ette nähtud. | Interrupts in AVR can be caused by counters, communication interfaces, analog-to-digital converters, comparators, special input-output pins and several other functions, depending on the controller. Any interrupt can be allowed or disallowed by the unit that generates it. Regardless of the interrupt being allowed or disallowed, there is a 1-bit field (interrupt flag) in the corresponding unit of the controller, which is marked as true when the interrupt condition is fulfilled. If the interrupt flag is changed to true and the interrupt is allowed, the controller starts to execute the code specified for this interrupt. |
| |
AVR mikrokontrolleris on iga katkestus seotud kindla sündmusega. Igal sündmusel on olekuregistris lipubitt, mis tähistab sündmuse juhtumist. Lisaks on sündmustega seotud katkestuste maskeerimise registrid ja vastavad bitid. Kui sündmuse katkestuse bitt on maskeerimata ja tekib sündmus, jätab protsessor mõne(kümne) töötakti jooksul käimasoleva programmi täitmise pooleli ning alustab katkestuse programmi täitmist. Pärast katkestuse programmi täitmist jätkab protsessor poolelijäänud programmi täitmist. | Every interrupt in the AVR microcontroller is tied to a specific event. Each event has a flag bit in the status register, which marks the occurring of the event. Events are also tied to interrupt mask registers and the corresponding bits. If the event's interrupt bit is left unmasked and an event occurs, the processor halts executing the current program for a few duty-cycles and begins executing the interrupt program. After the interrupt program has been executed, the processor resumes executing the paused main program. |
| |
<box 100% round #EEEEEE|Näide> | <box 100% round #EEEEEE|Example> |
| |
Katkestuste kasutamiseks AVR LibC teegiga tuleb kasutusele võtta //interrupt.h// fail. Katkestusel täitmisele minev programmikood lisatakse pärast "ISR"-i nimelist võtmesõna. "ISR" järele sulgudesse kirjutatakse katkestuse nimi. C-keele koodinäide: | To use interrupts with the AVR LibC library, it is necessary to include //interrupt.h//. The code that gets executed upon interrupt is written after the "ISR" keyword. The text between the brackets after "ISR" is the name of the interrupt. The following is a C language example: |
| |
<code c> | <code c> |
ISR(XXX_vect) | ISR(XXX_vect) |
{ | { |
// Tee midagi | // Do something |
} | } |
</code> | </code> |
</box> | </box> |
| |
Globaalne, kõigi katkestuste toimumise lubamine, määratakse ära juht- ja olekuregistris SREG. Võimaluse kõiki katkestusi keelata või lubada tingib andmete kaitse vajadus. Kuna katkestused katkestavad käimasoleva programmi täitmise, võivad nad segada või rikkuda andmeid, mida põhiprogramm katkestamise hetkel kasutas. Sellist olukorda saab vältida kõikide katkestuste keelamisega enne tundlike andmetega tegelemist. Globaalne katkestuste keelamine on lihtne, kui seda saab teha ühe registri (SREG) muutmisega. Pärast kriitilise programmiosa lõppu saab katkestused uuesti lubada ja kõik katkestused, mille lipuke vahepeal ära märgiti, lähevad täitmisele. | Global allowing of all interrupts is configured from the control and status register SREG. The option to allow or disallow all interrupts at once is there to help protect data. Since interrupts disrupt the execution of the main program, some data used by the main program may be disturbed or corrupted in the process. Situations like this can be avoided by simply disallowing all interrupts before processing such delicate data. Disallowing interrupts globally is easy, if it can be done by changing only one register (SREG). After the critical part of the program has been executed, the interrupts can easily be allowed again and all the interrupts that would have fired in the meantime are executed. |
| |
~~PB~~ | <pagebreak> |
| |
<box 100% round #EEEEEE|Näide> | <box 100% round #EEEEEE|Example> |
| |
Oletame, et programmis on kasutusel 16-bitine muutuja, mille väärtust muudab nii põhiprogramm kui ka katkestuse programmilõik, ja selle muutuja väärtus omistatakse hiljem teisele muutujale: | Let's suppose there is a 16-bit variable in use in the program, which is changed by both the main program and the interrupt program and the value of this variable is later given to another variable: |
| |
<code c> | <code c> |
#include <avr/interrupt.h> | #include <avr/interrupt.h> |
| |
// Globaalsed 16-bitised muutujad x ja y | // Global 16-bit variables x and y |
unsigned short x, y; | unsigned short x, y; |
| |
// Suvaline katkestus, mis muudab x väärtuse | // A random interrupt that changes the value of x |
ISR(XXX_vect) | ISR(XXX_vect) |
{ | { |
int main() | int main() |
{ | { |
// Muutujale x väärtuse omistamine | // Give a value to x |
x = 0x1111; | x = 0x1111; |
| |
// Globaalne katkestuste lubamine | // Allow interrupts globally |
sei(); | sei(); |
| |
// x väärtuse muutujasse y laadimine | // Give the value of x to y |
y = x; | y = x; |
} | } |
</code> | </code> |
| |
Programm on väga lihtne - algul omistatakse muutujale x väärtus 0x1111 ja hiljem selle väärtus omakorda muutujale y. Kui vahepeal tekib katkestus, saab x-i väärtuseks 0x3333. Loogikareeglite järgi saab muutujal y programmi lõpus olla kaks võimalikku väärtust, kuid 8-bitise AVR peal on ka kolmas võimalus. Nimelt, 8-bitise arhitektuuriga toimub 16-bitiste andmete liigutamine 2 takti jooksul ja vahepeal tekkiv katkestus võib andmete ühtsust rikkuda. Niisiis võib peale 0x1111 ja 0x3333 tekkida ka väärtus 0x3311. Et sellist asja ei juhtuks, tuleks katkestused enne operatsioone, mis toimuvad pikemalt kui 1 takti jooksul, ajutiselt keelata. | The program itself is very simple - first, variable x is given a value of 0x1111 and later, its value is given to variable y. If an interrupt occurs between those two operations, x gets a value of 0x3333. By logic, variable y can have two possible values by the end of the program, but on an 8-bit AVR there is also a third option. This is because 8-bit architecture needs 2 cycles to move 16-bit data and therefore a badly-timed interrupt can corrupt the integrity of the data. Consequently, y can have a value of 0x1111 or 0x3333, but it can also have a value of 0x3311 at the end of the program. To avoid getting the third, unwanted value, all interrupts should be temporarily disallowed before performing operations that take more than 1 cycle. |
| |
Toodud näites muutujale y muutuja x väärtuse omistamine ohutul meetodil: | In the following example, the value of x is given to y using a safe method: |
| |
<code c> | <code c> |
// Globaalne katkestuste keelamine | // Disallow interrupts globally |
cli(); | cli(); |
| |
// Laadimine | // Give the value of x to y |
y = x; | y = x; |
| |
// Globaalne katkestuste uuesti lubamine | // Re-allow all interrupts again |
sei(); | sei(); |
</code> | </code> |
| |
</box> | </box> |