Katkestused

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.

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.

Näide

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:

#include <avr/interrupt.h>
 
ISR(XXX_vect)
{
	// Tee midagi
}

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.

Näide

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:

#include <avr/interrupt.h>
 
// Globaalsed 16-bitised muutujad x ja y
unsigned short x, y;
 
// Suvaline katkestus, mis muudab x väärtuse
ISR(XXX_vect)
{
	x = 0x3333;
}
 
// Põhiprogramm
int main(void)
{
	// Muutujale x väärtuse omistamine
	x = 0x1111;
 
	// Globaalne katkestuste lubamine
	sei();
 
	// x väärtuse muutujasse y laadimine
	y = x;	
}

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.

Toodud näites muutujale y muutuja x väärtuse omistamine ohutul meetodil:

	// Globaalne katkestuste keelamine
	cli();
 
	// Laadimine
	y = x;
 
	// Globaalne katkestuste uuesti lubamine
	sei();

Atmeli xmega seeria kontrolleritel on katkestused jaotatud kolme prioriteedi klassi:

  1. Madala prioriteediga katkestused
  2. Keskmise prioriteediga katkestused
  3. Kõrge prioriteediga katkestused

See tähendab, et kõrgema prioriteediga katkestus võib katkestada madalama prioriteediga katkestuse koodi. Seoses sellega tuleb katkestusi kasutades vastava prioriteediga katkestused ka kõigepealt lubada.

	//Luba madala prioriteediga katkestused
	PMIC.CTRL |= PMIC_LOLVLEN_bm;
	//Luba keskmise prioriteediga katkestused
	PMIC.CTRL |= PMIC_MEDLVLEN_bm;
	//Luba kõrge prioriteediga katkestused
	PMIC.CTRL |= PMIC_HILVLEN_bm;
 
	// Globaalne katkestuste lubamine
	sei();

Illustratsioonilt on näha, kuidas kõrgema tasemega katkestus peatab madalama tasemega katkestuse ning madalama tasemega katkestuse programm jätkab tööd pärast kõrgema tasemega katkestuse töö lõppu.

Erineva taseme katkestuste käivitamise järjekord

Kui järjest tuleb mitu samatasemelist katkestust, siis oodatakse eelneva katkestuse töö lõppu ning alles siis alustab samatasemeline katkestus tööd. Juhul, kui vahepeal tuleb mõni kõrgema tasemega katkestus lükkub edasi mõlema katkestuse programmi töö.

Sama taseme katkestuste käivitamise järjekord