Страница 1 из 1

Запрет прерывания

Добавлено: Вт фев 19, 2013 21:28:03
Frensis
Вот код с CodeVisioonAVR по обработке прерывания прихода символа в USART:

Код: Выделить всё

interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index]=data;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
};
};
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif

так вот в курсе 123авр фрагмент
#asm("cli")
--rx_counter;
#asm("sei")

описан, но я его в корне не пойму....зачем и смысл останавлиать прерывания потом его заново запускать....непойму...


так тут написано что прерывания блокируются из за того что...
Так как мы считали символ из буфера нужно уменьшить число символов в нем подлежащих считыванию.

#asm("cli") // запретить прерывания глобально
--rx_counter; // вычесть 1 из rx_counter
#asm("sei") // разрешить прерывания глобально

Обратите внимание что перед декрементом мы запрещаем прерывания, а после прерывания включаем опять.

Зачем ? Вот фо ??? воскликнул бы англоязычный читатель ...

А затем, что в обработчике прерывания есть инкремент rx_counter - и если на декременте возникнет прерывание мы можем зациклится в этом месте программы и получить ошибку в числе символов в буфере.
....получается, что они останавливают прерывания только для того чтоб не помешать декременту....но а смысл если когда произойдет прерывание то по его окончанию все равно декремент выполнится, ведь прерывание не портит функции --rx_counter если выполняется в тот же момент

Re: Запрет прерывания

Добавлено: Вт фев 19, 2013 23:56:58
nirq
2. Очень внимательно приглядываемся к rx_counter, понимаем: что оно есть на самом деле и какие конкретно действия прячутся в надписи "--rx_counter".
1. В интернете читаем про слово "атомарность".

Ассемблер "учить" не обязательно, но желательно в общих чертах иметь представление о... о том, как буквы, нарисованные на экране компьютера, работают внутри микросхемы.
Накрайняк в том же интернете глянуть по-быстрому.

Простыню не читал, потому что не нужно.



Факультативно:
СпойлерКак выбираешь источники информации, на пользование которыми имеет смысл тратить своё время (вместо каких других)?

а). по знакомству дали ссылку;
б). в интернете первая или вторая ссылка по запросу;
в). чтобы русскими буквами и понятно (то есть попроще как-нибудь, "для идио чайников"... с яркими иллюстрациями и без многабукф);
г). чтобы без ошибок и правильно (а кто гарантирует);
д). чтобы было популярным, я в интернете самый умный особенный чтоле или как все обычный (~ вариант б);
е). официальные документы ищу одним или несколькими из перечисленных способов;
ё). официальные документы беру с сайта производителя;
ж). пишу на форумах;
з). читаю на форумах;
и). сначала пишу, потом читаю;
й). сначала читаю, потом пишу;
к). ...

Re: Запрет прерывания

Добавлено: Ср фев 20, 2013 08:43:08
Frensis
вопрос остается открытым

Re: Запрет прерывания

Добавлено: Ср фев 20, 2013 08:48:53
ploop
Frensis, вам предельно ясно написали, что "--rx_counter"это не одна команда, а как минимум две. И таки да, ассемблер знать очень желательно, благо на AVR он прост, как валенок.
Так вот, если между этими двумя командами ворвётся прерывание, вы словите нехилый такой глюк, который ни повторить, ни отловить не удастся, т.к. при повторении прерывание может и не быть в этом месте. А по закону подлоти глюк этот будет в уже работающей железке, а не во время отладки.

Re: Запрет прерывания

Добавлено: Ср фев 20, 2013 08:57:31
korsaj
А можно ссылку на первоисточник.

Re: Запрет прерывания

Добавлено: Ср фев 20, 2013 10:35:18
Kavka
Frensis, переменная rx_counter используется из двух мест - из основного кода и из прерывания. Поэтому переменная должна быть размещена в ОЗУ (volitile), а не в регистрах, как компиляторы Си, обычно, делают при оптимизации.
Как вы думаете сколько машинных команд надо для "--rx_counter". Да же если rx_counter однобайтовая, то команд будет 3. И предполагается, что во время выполнения этой последовательности команд содержимое ячейки памяти будет изменено только этой же самой последовательностью команд (а не из прерывания). А если переменная двухбайтовая, то прерывание может ещё и между операциями с байтами вклиниться. Понятно?

korsaj, http://www.123avr.com/

Re: Запрет прерывания

Добавлено: Ср фев 20, 2013 12:27:48
Frensis
ploop писал(а):Frensisесли между этими двумя командами ворвётся прерывание, вы словите нехилый такой глюк, который ни повторить, ни отловить не удастся, т.к. при повторении прерывание может и не быть в этом месте
Kavka писал(а):Frensis, переменная rx_counter используется из двух мест - из основного кода и из прерывания. Поэтому.......
......Понятно?
Да, спасибо, все ясно...