LAB3: Obrada prekida prema prioritetu


Zadatak

Prilagoditi prekidni podsustav tako da se prekidi obrađuju prema prioritetu -- svakom prekidnom broju pridijeliti prioritet. Ako se za vrijeme obrade jednog prekida dogodi novi zahtjev većeg prioriteta, on će se prihvatiti i obraditi odmah, odnosno, ako je manjeg prioriteta označiti ga za obradu i obraditi kasnije. Koristan dio obrade simuliranih prekida (koje simulirati ispisom i odgodama, npr. ukupnog trajanja 10 s) izvoditi s dozvoljenim prekidanjem. Postojeće prekide (0-48) pozivati na uobičajeni način (mogu svi imati isti prioritet, veći od simuliranih).

Ograničiti rekurzivni prihvat prekida na najviše tri. Tj. da se najviše dva prekida mogu prekinuti prioritetnijim. Npr. prvo se pojavi P3, pa P5 (koji prekida P3 i započinje P5), pa P7 (koji prekida P5 i započitnje P7) koji, obzirom da je već u trećoj razini, ne omogućava da novi zahtjevi većeg prioriteta krenu s obradom prije nego li je P7 gotov. Takve zahtjeve zaprimiti, ali ne odmah i krenuti s njihovom obradom u takvim situacijama. Ugradbeni sustavi su limitirani memorijom, a ugnježđeni prihvati prekida na stog stavljaju dosta sadržaja koji mogu biti previše.

Koristiti sklopovske prekide da pored "svoje" operacije još simuliraju pojavu novih.

Moguća ideja

Postojećim prekidima dati velike prioritete da se uvijek prihvate i obrade - neka za njih ne vrijedi ograničenje rekurzije. Oni i kratko traju pa ne bi trebali smetati u simulaciji. Npr. prekidima od 0-48 (postojećim) dati prioritet 20, a novim simuliranim od 1-9. Koristiti serijsku vezu kao izvor prekida (ili tipkovnicu). Svaki put kad se pročita neki znak (stisnuti broj), njega u upravljačkom programu postaviti i u dodatnu varijablu (npr. u funkciji uart_read pročitani znak staviti i u varijablu irq_prio, pretpostaviti da je broj: irq_prio = up->inbuff[up->inl] - '0'). Na kraju obrade prekida prije povratka u prekinuto, pogledati je li u toj varijabli ima nešto. Ako ima onda iz toga generirati prioritet novog zahtjeva i obrisati tu varijablu.

Ideja prihvata prekida bi bila:

IRQ_NUM_SIM0 = 48
PRIO_SIM_MAX = 9
irq_prio = 0

dodaj_zahtjeve(irq_num) 
{
	za sve ihndlr registrirane za irq_num
		zahtjev = kmalloc...
		zahtjev.handler = ihndlr
		zahtjev.u_obradi = laž
		...
		dodaj 'zahtjev' u 'listu zahtjeva uređenu prema prioritetu (zahtjev.handler.prio)
}

funkcija za prihvat prekida(irq_num) 
{
	dodaj_zahtjeve(irq_num)

	prvi = prvi zahtjev iz 'liste zahtjeva'
	dok je prvi != NULL i prvi.u_obradi == laž i (dubina < 3 ili prvi.prio > PRIO_SIM_MAX)
	{
		dubina++
		aktivni_zahtjev = prvi
		aktivni_zahtjev.u_obradi = istina

		dozvoli prekidanje
		obradi aktivni_zahtjev (pozovi aktivni_zahtjev.handler.ihandler(...))
		zabrani prekidanje

		dubina--
		makni aktivni_zahtjev iz liste (on sad ne mora biti na prvom mjestu!)

		//simulacija novih zahtjeva nakon obrade prekida serije
		ako je irq_prio > 0 {
			dodaj_zahtjeve(IRQ_NUM_SIM0 + irq_prio)
			irq_prio = 0
		}
		prvi = prvi zahtjev iz liste zahtjeva
	}
}
Varijablu irq_prio se može deklarirati u interrupts.c a prije njenog korištenja iz uart.c u funkciji uart_read samo ju označiti da postoji s extern int irq_prio;

Dodatno

Postoji greška u korištenju UART-a. Trenutni kod krivo postavlja sklop te on ne izaziva/obrađuje prekide kad dođe novi znak. Popravak ove greške je opisan u uart-fix.patch.

Primjer programa koji ispituje rad prioritetnog prekidnog sustava je u datoteci interrupts.c.