Sunteți pe pagina 1din 5

ASC2 – Lucrări de laborator 1/5 Lucrarea nr.

Întreruperea

1. Scopul lucrării

Scopul acestei lucrări îl constituie prezentarea întreruperii (în engleză – interrupt) ca fiind
o metodă mai eficientă decât interogarea în ce privește comunicarea între procesor și periferice.

2. Mersul lucrării

Întreruperea este o metodă alternativă pentru interogare. În lucrarea precedentă s-a


prezentat principiul care stă la baza interogării – testarea periodică a perifericelor. Interogarea este o
metodă ineficientă deoarece procesorul pierde timp să verifice dacă există date de recepționat chiar
și când perifericele nu au nimic de transmis. Întreruperea, însă, oferă o soluție mai bună: dacă
perifericul are ceva date de transmis (sau dorește să recepționeze date), generează o întrerupere a
procesorului; procesorul suspendă execuția programului curent, realizează transferul datelor cu
perifericul, apoi reia programul suspendat din punctul în care l-a lăsat. În acest mod sunt eliminați
timpii morți, pentru că procesorul este oprit din activitatea curentă doar dacă e necesară
comunicarea cu perifericul, execută rutina de tratare a întreruperii și apoi revine la execuția
programului principal.
Ca și în cazul interogării, fiecare periferic trebuie să aibă asociat un nivel de prioritate. Dacă
două periferice doresc să genereze o întrerupere în același timp, vor fi servite de către procesor în
ordinea priorității lor.

În această lucrare se va prezenta modul în care se pot genera întreruperi cu ajutorul


butoanelor KEY[3..1].
Așa cum s-a precizat și în lucrarea nr. 2, un port paralel poate avea următoarea configurație:

De această dată, nu vor fi folosite numai primele două cuvinte, ci și al treilea, cel care se
referă la mascarea biților. Mascarea biților înseamnă selectarea acelor biți din registrul de date
(locația cu adresa de bază) care să poată genera întreruperi. Doar cei pentru care se stabilește
Daniel FILIPAȘ 1/5 dfilipas@uoradea.ro
ASC2 – Lucrări de laborator 2/5 Lucrarea nr. 5

valoarea „1” vor putea genera întreruperi.


De exemplu, dacă adresa de bază a portului asociat butoanelor este declarată ca int * butoane
(adică pe 32 biți), mascarea celor 3 biți se realizează astfel:
*(butoane + 2) = 0x7;

2.1 Crearea proiectului și elaborarea sistemului

Se creează un nou proiect în Quartus II Web Edition (după modelul din Anexa A).

Apoi se construiește sistemul (după modelul din Anexa C). Acesta trebuie să cuprindă:
 un procesor NIOS II (varianta economică Nios II/e)
 un modul de memorie (se va alege un modul de 16 KB de memorie on-chip de tip RAM)
 un port de intrare (PIO) de 10 biți (corespunzător comutatoarelor SW)
 un port de intrare (PIO) de 3 biți (corespunzător butoanelor KEY[3..1])
 un port de ieșire (PIO) de 8 biți (corespunzător LED-urilor verzi LEDG)
 un port de ieșire (PIO) de 10 biți (corespunzător LED-urilor roșii LEDR)
 un port de ieșire (PIO) de 7 biți (corespunzător afișorului HEX0[6..0])
 un modul JTAG UART

Pentru a putea genera întreruperi cu ajutorul unui port (doar porturile de intrare și cele
bidirecționale pot genera întreruperi), e necesar să fie selectate opțiunile din figura de mai jos:

De asemenea, trebuie asociat un număr fiecărui port care poate genera întreruperi.
Indicele asociat portului se referă la poziția ocupată în registrul întreruperilor: pornind de la
dreapta spre stânga, „0” înseamnă primul bit, „1” înseamnă a doilea bit, „2” al treilea bit etc.

În figura următoare sunt trei porturi care pot genera întreruperi.

Daniel FILIPAȘ 2/5 dfilipas@uoradea.ro


ASC2 – Lucrări de laborator 3/5 Lucrarea nr. 5

După creare, instanțiere și compilare, sistemul trebuie descărcat pe placa Altera DE1.
Etapele care trebuie parcurse pentru acest lucru sunt prezentate în Anexa D.

E important să fie notate adresele alocate componentelor, întrucât ele trebuie accesate
din programele care vor fi lansate în execuție.

2.2 Compilarea și încărcarea unui program

Se consideră următorul program (scris în limbajul C):

int main(void)
{

volatile int * butoane = (int *) 0x9000; //adresa portului pentru butoane


volatile int * LEDverzi = (int *) 0x9030; //adresa LED-urilor verzi

*(butoane + 2) = 0x7; // masca pentru bitii KEY[3..1]

__builtin_wrctl(3, 2); // seteaza generarea de intreruperi de la butoane

__builtin_wrctl(0, 1); // permite procesorului sa accepte intreruperi

volatile int x, suma = 0;

while(1) //programul principal


{
*LEDverzi= suma;
for(x=500000;x>0;x--);
suma++;
}

return 0;
}

Execuția programului are ca efect afișarea pe LED-urile verzi a valorilor pe care le ia suma
(cu o întârziere de aproximativ o jumătate de secundă între două valori).

Daniel FILIPAȘ 3/5 dfilipas@uoradea.ro


ASC2 – Lucrări de laborator 4/5 Lucrarea nr. 5

Cu ajutorul butoanelor KEY[3..1] se vor genera întreruperi. În momentul în care apare o


întrerupere, procesorul suspendă programul care este în execuție, salvează starea curentă (adică
adresa următoarei instrucțiuni și conținutul registrelor), apoi execută rutina de tratare a întreruperii.
După execuția rutinei, restaurează starea programului întrerupt și continuă execuția acestuia din
punctul în care a rămas.
Codul următor prezintă cedarea controlului către rutina de tratare a întreruperii (codul
complet se află în fișierul salvare_st_curenta.c):

void interrupt_handler(void)
{
int intrerup;
intrerup = __builtin_rdctl(4); // starea registrului de intreruperi

if ( intrerup & 0x2 ) // butoanele au asociat numarul 1


{ // (al doilea bit din registrul de intreruperi)
rutina_trat_intr( );
}

return; // revine la programul principal


}

Rutina de tratare a întreruperii este următoarea:

void rutina_trat_intr( void )


{
volatile int * butoane = (int *) 0x9000; //adresa portului pentru butoane
volatile int * comutatoare = (int *) 0x9010; //adresa comutatoarelor
volatile int * LEDrosii= (int *) 0x9020; //adresa LED-urilor rosii
volatile int apasat;

apasat = *(butoane + 3); // citeste registrul de intreruperi al butoanelor


*(butoane + 3) = 0; // sterge intreruperea

if (apasat & 0x4) // daca a fost apasat KEY[3]


*LEDrosii = 0x3C0; // aprinde LED-urile [9..6]
else if (apasat & 0x2) // daca a fost apasat KEY[2]
*LEDrosii = 0xF; // aprinde LED-urile [3..0]
else // daca a fost apasat KEY[1]
*LEDrosii = *comutatoare; // afiseaza starea comutatoarelor pe LED-urile rosii

return; // iesire din subrutina


}

Efectul întreruperii constă în aprinderea unor LED-uri roșii, în funcție de butonul care a fost
apăsat.
Pentru a putea lansa în execuție programele, e necesar ca acestea să fie incluse într-un
proiect. Pentru crearea proiectului se utilizează Altera Monitor Program.
Etapele care trebuie parcurse pentru acest lucru sunt prezentate în Anexa MP.
Observație: Dacă există mai multe fișiere sursă care trebuie compilate (ca în cazul de mai
sus), primul fișier din listă trebuie să fie cel care conține programul principal (funcția main).
În plus, e foarte important următorul aspect: deoarece există o rutină de tratare a
întreruperii (care începe la o adresă de forma Baza + 0x20 și ocupă mai multe locații), pentru a nu
fi suprascrisă de programul principal, e necesar să fie stabilit un decalaj (offset) între programul

Daniel FILIPAȘ 4/5 dfilipas@uoradea.ro


ASC2 – Lucrări de laborator 5/5 Lucrarea nr. 5

principal și rutina de tratare a întreruperii. Pentru exemplul dat, valoarea 200 este suficientă, așa
cum se vede în figura următoare:

2.3 Aplicații în cadrul ședinței de laborator

a. Să se verifice funcționarea programelor date și să se observe utilitatea întreruperii.

b. Să se modifice rutina de tratare a întreruperii în așa fel încât la apăsarea butoanelor să se


tipărească, în fereastra Terminal, caracterele A, B sau C.

c. Să se completeze programele în așa fel încât pe afișorul HEX0 să apară valoarea unui
contor intern (inițializat cu valoarea 5), iar cu ajutorul butoanelor să fie modificată această valoare:
apăsarea lui KEY[3] să incrementeze valoarea, apăsarea lui KEY[2] să o decrementeze, iar apăsarea
lui KEY[1] să o aducă la 0. Indiciu: variabilele globale declarate în programul principal pot fi
accesate din rutina de întrerupere cu directiva extern (de exemplu: extern volatile int x; sau
extern x;)

d. Să se realizeze modificările necesare (în arhitectura sistemului și/sau în programele date)


astfel încât întreruperile să fie generate de comutatoare în loc de butoane.

Bibliografie:

http://www.altera.com/education/univ/materials/comp_org/labs/unv-labs.html

Daniel FILIPAȘ 5/5 dfilipas@uoradea.ro