|
Запрет/Разрешение прерываний в кольцевых буферах, Как правильно и оптимально? |
|
|
|
Jun 18 2008, 03:11
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 18-06-07
Пользователь №: 28 506

|
Пожалуйста, подскажите как правильно и оптимально Запрешать/Разрешать прерывания при работе с программыми буферами устройств. Попробовал несколько вариантов: 1) cpsr=DisableIRQ();
.... // работа с буфером
RestoreIRQ(cpsr); 2) VICIntEnClr = 1 << UART0_INT;
.... // работа с буфером VICIntEnable = 1 << UART0_INT; 3) cpsr=DisableIRQ(); U0IER &= ~UIER_ETBEI; RestoreIRQ(cpsr);
.... // работа с буфером
cpsr=DisableIRQ(); U0IER |= UIER_ETBEI; RestoreIRQ(cpsr);
Второй случай давал сбои и зависание на LPC2138, а вот на LPC2368 работаспособен..
Сообщение отредактировал Smallday - Jun 18 2008, 03:18
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 19)
|
Jun 18 2008, 05:29
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
запрет источника прерывания приводит к потере запроса прерывания, возникшего во время запрета. При глобальном запрещении прерываний запросы прерываний взводят флаги, и если они не сброшены до глобального разрешения прерываний, то после разрешения срабатывает логика контроллера прерваний и вызываются соответствующие обработчики в установленном этой логикой порядке (логика зависит от типа контроллера прерываний или конкретного решения конкретного микроконтроллера, а общий механизм един для процессорных систем). Так что второй вариант не годится. ИМХО, в русском техническом языке существуют как минимум такие понятия как источник прерывания, запрос прерывания, контроллер прерывания, обработчик прерывания, а вот само слово прерывание в разных контекстах обозначает разное сочетание этих понятий (к моему сожалению всё чаще русскоязычные словосочетания забываются и с английского переводится без учёта контекста). А глобальное разрешение прерываний грубо относится к "кнопке" управления контроллера прерываний со стороны процессора (ядра), которая в случае запрета на время как бы придерживает выдачу запроса прерывания от контроллера прерывания к ядру (в случае с ARM это, например, IRQ со своим запретом и FIQ со своим запретом). Что касается буферов, то они бывают разными и есть варианты построения и дисциплины работы, не требующие запрета прерываний. Что касается вариантов 1 и 3, то существуют разные подходы в части использования и способов входа/выхода в/из критических секций и это отдельный вопрос, по которому на форуме было достаточно много обсуждений.
--------------------
aka Vit
|
|
|
|
|
Jun 18 2008, 05:53
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(sensor_ua @ Jun 18 2008, 09:29)  запрет источника прерывания приводит к потере запроса прерывания, возникшего во время запрета. ...Вы уверены? Потеря запроса прерывания может произойти в том случае если имеется запрос на данный момент времени (по каким либо причинам не получивший обработку) и появился следующий запрос от этого же источника прерывания. Таким образом риск потери запроса прерывания возникает в том случае когда время обработки прерывания (и/или время реакции на прерывание) превышает минимально-возможное время между двумя запросами.
|
|
|
|
|
Jun 18 2008, 06:13
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата ...Вы уверены? Абсолютно. Толко я чуть ошибся с контекстом. Читать "запрет обработки запроса прерывания", хотя и при запрете источника будет так же не работать. Вопрос же скорости обработки запросов и их потерь при неуспевании, ИМХО, суть другой вопрос.
--------------------
aka Vit
|
|
|
|
|
Jun 18 2008, 06:19
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(sensor_ua @ Jun 18 2008, 10:13)  Читать "запрет обработки запроса прерывания", мне кажется сути это не меняет. А вы попробуйте запретить прервание по приему от UART и отправьте на него символ, а потом разрешите прерывание и посмотрите что получится
|
|
|
|
|
Jun 18 2008, 07:19
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Посмотрите хотя бы картинку Interrupt request logic в описании VIC'а. Смотрю документ http://infocenter.arm.com/help/topic/com.a...81e/DDI0181.pdf Figure 2-2 и триггеров не наблюдаю. Читаем до того на стр. 20 примечание The VIC does not handle interrupt sources with transient behavior. For example, an interrupt is asserted and then deasserted before software can clear the interrupt source. ... However, when a transient interrupt occurs, the priority logic of the VIC is not set ... Может я, конечно чего не понимаю, но в LPC2138, например, для источника прерывания по ExtInt проложен регистр (триггеры) ДО VIC (смотрю UM LPC2138 раздел 5-2 External Interrupt Flag register) и если выходы таких регистров служат запросами прерывания, то, естественно, если триггер не сбросишь, то запросы прерывания на соответствующих входах Interrupt Request Logic VIC будет активны.
--------------------
aka Vit
|
|
|
|
|
Jun 18 2008, 11:37
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(Rst7 @ Jun 18 2008, 13:56)  А можно примерчик такого? ...вот пример кольцевого буфера не требующего запрета прерываний struct { U8 in; U8 out; U8 data [256]; } buf;
void init_buf(void) { buf.in = buf.out; }
void isr_rx(void) { U8 c; ... if ((U8)(buf.in + 1) != buf.out) buf.data [buf.in++] = c; else return; }
void main(void) { U8 c; ...
if (buf.in != buf.out) c = buf.data[buf.out++];
... }
|
|
|
|
|
Jun 18 2008, 17:11
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Идея кольцевых буферов и код есть в avr-lib Да где ее только нет. Я и сам могу десяток реализаций разных сделать (и делал). Я к тому веду, что в общем случае, при работе с кольцевыми буферами необходима атомарная RMW-операция с памятью хотя-бы в одном месте. С учетом того, что на RISC-процах нет столь любимого на PDP11 INC и DEC прямо ячейки памяти, получается, что необходимо уметь запрещать/разрешать прерывания (или переключение задач в общем случае). Кстати, в ARM есть комманда SWP для управления семафорами (она как раз RMW), только я не могу пока придумать, как ее использовать для циклических буферов.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Jun 18 2008, 17:38
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(rezident @ Jun 18 2008, 20:21)  Для кольцевых буферов я лично использую два индекса - один индекс для чтения, другой для записи. Ну и счетчик еще. Я тоже так делаю :-) Но всё равно, изменение значения счётчика приходится выполнять при запрещённых прервыаниях, ибо операция не атомарная. Цитата(Rst7 @ Jun 18 2008, 23:11)  Я к тому веду, что в общем случае, при работе с кольцевыми буферами необходима атомарная RMW-операция с памятью хотя-бы в одном месте. С учетом того, что на RISC-процах нет столь любимого на PDP11 INC и DEC прямо ячейки памяти, получается, что необходимо уметь запрещать/разрешать прерывания (или переключение задач в общем случае). Во-во
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 18 2008, 21:16
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Rst7 @ Jun 18 2008, 15:02)  >> if ((U8)(buf.in + 1) != buf.out) buf.data [buf.in++] = c;
Да, такая конструкция работает. По причине атомарности добавления. А вот аналогиная передача - - работать не будет. Это еще почему?! Еще как будет работать. По причине того что in++ делается уже после того как байт добавлен в очередь. Предположим передатчик прервал фоновую задачу в любой момент выполнения if ((U8)(buf.in + 1) != buf.out) buf.data [buf.in++] = c; Если индекс "in" соответвует разрядности процессора, и будет записан в память одной командой ST тогда будем иметь только три возможные комбинации в обработчике прерывания: buf.in == buf.out нет новых данных (ничего не отправлено) buf.in == buf.out есть новые данные (ничего не отправлено, т.к. индексы говорят об отсутсвии данных) buf.in != buf.out есть новые данные (берем сколько можно пока out != in) Все комбинации безопасны. Ранее чем изменится индекс in, передатчик не сможет определить, что байт был добавлен в буфер, соответвенно ничего лишнего или частично положенного не вытянет. Для работоспособности этой конструкции необходимо - чтобы данные шли всегда из одного и того же источника (задачи) - забирались всегда одним и тем же адресатом (задачей) (источник и адресат - могут быть разными задачами) и достаточно атомарности обновления индекса (запись одной командой ST), т.е. индекс не может быть большей разрядности чем разрядность регистров процессора. Все остальное не важно.
|
|
|
|
|
Jun 19 2008, 05:20
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561

|
Цитата(Rst7 @ Jun 18 2008, 16:02)  Да, такая конструкция работает. По причине атомарности добавления. А вот аналогиная передача - работать не будет. ...и передача тоже будет работать и по причине атомарности в том числе
|
|
|
|
|
Jun 19 2008, 05:25
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Это еще почему?! Еще как будет работать. Да, согласен. Тут я погорячился, но... Цитата Для работоспособности этой конструкции необходимо - чтобы данные шли всегда из одного и того же источника (задачи) Просто в моих задачах обычно кольцевые буферы используются для складывания событий, и при этом добавление новой информации в буфер может происходить из разных задач. В таком случае надо обеспечивать атомарность увеличения указателя, иначе может случиться гуано. В общем случае я бы такую задачу формулировал и решал с точки зрения минимизации нахождения в состоянии с запрещенными прерываниями.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|