Accesul atomic la variabile, avr, programare

Când depanem aplicațiile încorporate, este mai greu să prinzi erori care nu sunt întotdeauna permanente, dar numai din când în când. Unul dintre motivele acestor erori: variabile care sunt accesate în mod asincron. Astfel de variabile trebuie să fie bine definite și să aibă o protecție adecvată.







Definiția trebuie să includă cuvântul cheie volatil. Aceasta informează compilatorul că o variabilă poate fi modificată nu numai din codul executabil curent, dar și din alte locuri. Apoi compilatorul va evita anumite optimizări ale acestei variabile.

Pentru a proteja o variabilă comună, fiecare operație de acces trebuie să fie atomică. Adică, nu ar trebui întrerupt până la sfârșit. De exemplu, accesul la o variabilă pe 32 de biți sau 16 biți pe o arhitectură pe 8 biți nu este atomică, deoarece operațiile de citire sau scriere necesită mai mult de o instrucțiune.

Luați în considerare un exemplu tipic al unei variabile publice - un cronometru de program. În dispozitivul de tratare a întreruperii, valoarea sa este modificată, iar în codul principal este citită. În cazul în care un manipulator de alte întreruperi sunt dezactivate, de exemplu, în mod implicit făcut în microcontrolere AVR, funcționarea variabila este atomică și nu există stocuri nu se va întâmpla.

Pe de altă parte, în bucla principală, programele de întrerupere sunt cel mai adesea rezolvate, iar versiunea codului nesigur ar putea arăta astfel:

Acest cod este nesigur, deoarece funcționarea citirii variabilei system_timer nu este atomică. În timp ce citim un octet al variabilei system_timer, poate să apară o întrerupere TIMER0_COMP și manipularea va schimba valoarea sa. Apoi, la revenirea la programul principal, vom citi restul variabilei deja de la noua sa valoare. În unele cazuri, amestecul de la valorile vechi și noi nu va cauza eșecuri, dar în altele poate afecta foarte mult comportamentul programului. Ei bine, de exemplu, dacă valoarea veche a system_timer a fost 0x00ffffff, iar cea nouă este 0x01000000.







Pentru a proteja accesul la variabila sistem_timer, puteți utiliza funcția de monitorizare, pentru a face acest lucru, cuvântul cheie _monitor este specificat înainte de numele funcției.

Funcția de monitorizare este o funcție care salvează registrul SREG la intrare, dezactivează întreruperi pe durata executării și restaurează conținutul SREG înainte de ieșire.

Dacă doriți ca întreruperile să fie dezactivate într-o anumită zonă a codului, puteți utiliza funcții intrinseci.

Instrumentele C ++ vă permit să integrați această logică în clasă.

Când creați obiectul m, constructorul va stoca registrul SREG și va dezactiva întreruperile. La sfârșitul blocului, distrugătorul va restabili conținutul SREG. Frumoasă, nu?

În general, principiul de scriere a codului cu operațiuni atomice este peste tot unul și există multe opțiuni de implementare. De exemplu, când accesați o variabilă, nu puteți interzice toate întreruperile, ci doar cele care utilizează această variabilă.

Problema este posibilă cu o variabilă pe 8 biți. Funcționare ca system_timer - = 100 compilează mai multe instrucțiuni de asamblare și în codul principal poate fi, de asemenea, întrerupt între system_timer de citire și se înregistrează rezultatele. Există un alt mod de a citi multi-byte contoare asincrone (fără a dezactiva întrerupe) - citește o variabilă de două ori și a compara toate bytes, cu excepția cei mai tineri. În cazul în care octeți în copiile sunt - vom lua ultima valoare de citire în cazul în care nu este egal - citește până în ultimele două valori de citire ale octeți sunt egale. Contor scăzut octet între citirile pot varia în timp, fără transport, deci nu este implicat în verificarea.

După cum puteți vedea din exemple, codul este dat pentru compilatorul IAR. În WinAVR, o problemă similară este rezolvată prin includerea fișierului atomic.h, în care sunt definite macrocomenzile pentru implementarea accesului atomic. De exemplu:

1. Accesul atomic la site-ul variabilelor: chipenable.ru - articolul original.







Articole similare

Trimiteți-le prietenilor: