ПредишенСледващото

Когато отстраняване на грешки вградени приложения, най-трудно да хванеш грешки, които се проявяват не постоянно, но само от време на време. Една от причините за такива грешки: променливите достъпни асинхронно. Тези променливи трябва да бъдат правилно идентифицирани и да имат подходяща защита.

Определението следва да включва волатилните ключова дума. Той информира, че компилаторът променлива може да се променя не само от сегашните изпълним код, но и от други места. След това компилаторът ще се избегнат някои оптимизации променлива.
За да се защити обща променлива, всяка операция за достъп трябва да бъде атомно. Това означава, че тя не трябва да се прекъсва преди неговото завършване. Например, за достъп до променлива 32 или 16 бита в 8-битова архитектура, а не атомен, тъй като четат или пишат операции изискват повече от една инструкция.
Помислете за един типичен пример за публично променлива - таймер софтуер. Оператора за прекъсване, променя стойността си, а в основен код - чете. Ако манипулатор други прекъсвания са с увреждания, например, по подразбиране прави в микроконтролери AVR, операцията на променливата е атомно и никакви запаси няма да се случи.

летливи неподписан дълго system_timer = 0;

#pragma вектор = TIMER0_COMP_vect
__interruptvoid Timer0CompVect (свободен)
system_timer ++;
>

От друга страна в основата на прекъсване на цикъла програма обикновено допуска и възможността за опасен код може да изглежда така:

ако (system_timer> = next_cycle)
next_cycle + = 100;
do_ нещо ();
>

Този код не е безопасно, защото действието на променлива system_timer на четене без атомна. Четем един байт променлива system_timer, може TIMER0_COMP прекъсне треньор, и промяна на стойността. След това, за да се върнете към основната програма, четем на останалата част от променливата вече на новата си стойност. В някои случаи е смесица от стари и нови ценности няма да доведе до прекъсване, но в други това може да се отрази значително на поведението на програмата. Ами, например, ако старата стойност е system_timer 0x00FFFFFF и новият 0x01000000.

За да се защити достъп до променлива system_timer, можете да използвате функцията за монитор, това име на функция, за да определите ключ slovo__monitor.


ако (get_system_timer ()> = next_cycle)
next_cycle + = 100;
do_ нещо ();
>

Функцията за монитор - функция, която е на входа поддържа регистър SREG, забранява прекъсва за периода на неговото изпълнение, както и преди публикуването на съдържанието на възстановяване SREG.

Ако искате да се прекъсне забранена в някоя конкретна област код, можете да използвате вътрешната функция.

...
неподписан дълго ПТУ;
неподписан овъгляване oldState;
oldState = __save_interrupt (); // освен регистрирате SREG
__disable_interrupt (); // деактивирането прекъсва
ТМР = system_timer; // прочете стойността на временно променлива system_timer __restore_interrupt (oldState); // възстанови SREG

Средства C ++ позволява да се изгради тази логика в един клас.

Mutex ()
__restore_interrupt (current_state);
>

неподписан дълго ПТУ;
Mutex m; // създаде обект от класа, сега е на разположение за атомна
ТМР = system_timer; // спаси system_timer променливи във времето
>

При създаване на обект конструктор м спаси регистрирате SREG и забрани прекъсването. В края на блока - деструктор ще възстанови SREG съдържание. Красива, а?

Общ принцип навсякъде един и реализирането на много опции. Можете, например, при достъп до променливата не забранява всички прекъсва, но само тези, които използват тази променлива.

Това е всичко. Всички успешното отстраняване на грешки.

Може би проблемът с осем променлива. Операция като system_timer - = 100 Кампильо няколко инструкции за монтаж и в основния код може също да бъде прекъснато между system_timer четене и запис на резултатите.
---------
Има и друг начин да се чете многобайтови асинхронни броячи (без да деактивирате прекъсвания) - четете променлива два пъти и сравни всички байтове с изключение на най-малките. Ако байта в копията са - ние приемаме последната стойност за четене, ако не е равно - чете, докато последните две прочетените стойности на байта са равни. Ниска байт брояч между показанията може да варира във времето, без носене, така че не е участвал в проверката.

Както се вижда от примерите, кодът дадени за съставител IAR. В WINAVR подобен проблем е решен чрез включване на файла. който определя макроси за изпълнение на атомната достъп.
по следния начин:
.
ATOMIC_BLOCK (ATOMIC_RESTORESTATE)
// блок от код със забранени прекъсвания
>
.

Свързани статии

Подкрепете проекта - споделете линка, благодаря!