|
продолжить прерывание, atmega128 winavr |
|
|
|
Feb 9 2011, 14:07
|

Частый гость
 
Группа: Участник
Сообщений: 82
Регистрация: 1-03-10
Пользователь №: 55 731

|
Добрый день есть некоторый код Код void funс(void){ cli(); ... sei(); } ISR(INT0_vect){ ...} ISR(USART1_RX_vect){ ...} ISR(USART1_TX_vect){ ... func(); ...} ISR(USART1_UDRE_vect){ ... } ... Функцию я вызываю из прерывания, во время её выполнения прерывания нужно запретить. Когда я их снова разрешу, то могут возникнуть любые прерывания, а не продолжалось USART1_TX, так ведь? Вопрос, как сделать так, что бы после разрешения прерываний разрешалось только USART1_TX Спасибо за помощь
|
|
|
|
|
Feb 9 2011, 14:48
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Mikron @ Feb 9 2011, 17:07)  Функцию я вызываю из прерывания, во время её выполнения прерывания нужно запретить. Когда я их снова разрешу, то могут возникнуть любые прерывания, а не продолжалось USART1_TX, так ведь? Вопрос, как сделать так, что бы после разрешения прерываний разрешалось только USART1_TX Ничего в функциях обработки прерываний запрещать и разрешать не надо, т.к. это происходит полностью автоматически. Т.е. при возникновении ситуации прерывания с последующим перескоком из произвольного места программы на процедуру его обработки, прерывания автоматически запрещаются. И никакой cli дополнительно тут не нужен. Точно так же, прерывания восстановятся сами после выхода из той процедуры по iret. А вот то, что в процедуре прерывания надо делать обязательно, то это сохранить содержимое регистра флагов (0x3F), а также исходные значения всех регистров, которые в той процедуре используете. Для этого и то, и другое, следует загнать в стек, а перед выходом восстановить из стека. Если это USART1_TX, то крайне нежелательно разрешать прерывание в процедуре его обработки, т.к. тогда может возникнуть новое прерывание того же типа тогда, когда вы не успели обработать предыдущее. В некоторых замыслах это бывает необходимо, но все-таки лучше так не рисковать.
|
|
|
|
|
Feb 9 2011, 16:15
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата Когда я их снова разрешу, то могут возникнуть любые прерывания, а не продолжалось USART1_TX, так ведь? Вопрос, как сделать так, что бы после разрешения прерываний разрешалось только USART1_TX А вы в обработчике USART1_TX - запретите , сделайте сброс разрешений прерываний в контрольном регисте USART1, тех что Вам не нужны. Вывалитесь из обработчика , у Вас останется только USART1_TX. Но Вам надо продумать , как потом включить их снова. Да и вот ещё , TX у Вас "младшее" по приоритету прерывание , смотря как написан код , Вы рискуете туда и не добраться
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Feb 10 2011, 14:09
|

Частый гость
 
Группа: Участник
Сообщений: 82
Регистрация: 1-03-10
Пользователь №: 55 731

|
Цитата(ILYAUL @ Feb 9 2011, 19:15)  Да и вот ещё , TX у Вас "младшее" по приоритету прерывание , смотря как написан код , Вы рискуете туда и не добраться Возник вопрос, почему могу туда не добраться Просто в документации на контроллер про прерывания написано There are basically two types of interrupts. The first type is triggered by an event that sets the interrupt flag. For these interrupts, the Program Counter is vectored to the actual interrupt vector in order to execute the interrupt handling routine, and hardware clears the corresponding interrupt flag. Interrupt flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the interrupt flag will be set and remembered until the interrupt is enabled, or the flag is cleared by software. Similarly, if one or more interrupt conditions occur while the global interrupt enable bit is cleared, the corresponding interrupt flag(s) will be set and remembered until the global interrupt enable bit is set, and will then be executed by order of priority. То есть произошел как бы запрос на прерывание, установился флаг, и рано или поздно оно все равно произойдет, а почему нет?
|
|
|
|
|
Feb 10 2011, 15:20
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(_Артём_ @ Feb 10 2011, 17:18)  Разве при переходе на вектор прерывания флаг I не сбрасывается? Тогда CLI(); - лишняя. Мной приведена функция, которую вызывают из обработчика прерывания (в этом случае - флаг I сброшен) и из другого места программы (например, из бесконечного цикла - флаг I установлен), т.е. примерно такая, как у автора вопроса. Код функции таков, что вся функция или её отдельный участок должен работать не прерываясь. Чтобы выполнение кода не прервалось, прерывания нужно запретить (конечно, если вызвана функция из прерывания - флаг I и так сброшен, и делать это не обязательно, но "лишний" раз - не повредит), но вот в конце функции (или её участка) разрешать прерывания нужно не всегда, а только в том случае, если при входе в функцию прерывания были разрешены. Imho, сделать это удобно сохраняя при входе в функцию регистр SREG (из него нам интересен флаг I), а в конце функции(участка кода) - восстановить SREG вместе с флагом I.
|
|
|
|
|
Feb 10 2011, 18:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(Mikron @ Feb 10 2011, 17:09)  Возник вопрос, почему могу туда не добраться Всё достаточно просто, TX1 имеет низший приоритет . А вот INT0_vect высший, затем идут USART1_RX_vect и USART1_UDRE_vect и только потом Ваш. Вам надо посчитать насколько часто будут появлятся эти три прерывания, успеете Вы в паузах между ними обработать TX, ведь надо успеть принять символ, загрузить символ и ещё обработать INT0 и на все три уходит время . Смотря как Вы напишете код , у Вас просто может не хватить времени обработать TX . Его "забьют" старшие. Надо бы сказать , что USART1_TX_vect это дублёр USART1_UDRE - этот имеет тенденцию забросил и забыл. Первый (USART1_TX_vect) передачу закончил. В зависимости от требуемых функций ( не путать с функциями Си) можно использовать или UDRE или TX. Так например при обработке DS18B20 лучше не использовать UDRE. Кстати , этот флаг имеет "неприятную" особенность он практически "всегда установлен". С момента сброса и до выключения питания. Увидеть его в ноль можно посылая сразу большой массив данных. И так как он старше TX.....
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Feb 11 2011, 05:07
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
 Ето винавр, проснитесь! Код #include <util/atomic.h> void func(void) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { <Function's body&soul> } } ЗЫ в опциях обязательно включить -std=gnu99 Цитата(ILYAUL @ Feb 10 2011, 21:39)  Так например при обработке DS18B20 лучше не использовать UDRE.  Стало быть, Вы не умеете его готовить в условиях многозадачности?
|
|
|
|
|
Feb 11 2011, 07:31
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(ILYAUL @ Feb 10 2011, 20:39)  Кстати , этот флаг имеет "неприятную" особенность он практически "всегда установлен". С момента сброса и до выключения питания. Увидеть его в ноль можно посылая сразу большой массив данных. И так как он старше TX..... Так это же отлично! И я этим радостно пользуюсь. Даже если другие прерывания задержат обработку UDRE и уже поднимется TXC, при освобождении процессора будет выполнен таки обработчик UDRE. Там я сброшу флаг TXC. И в самом же обрабочтике UDRE сниму его разрешение UDRIE при отправке последнего байта пакета. Таким образом, если до обработчика TXC вообще дошло, то это конец пакета. Постоянное взведение UDRE тоже очень удобно, не нужно никаких танцев с тем, что первый байт пакета надо вручную затолкать в UDR, а уже остальные по прерываниям. Сформировал пакет и поднял UDRIE - данные пошли единообразным способом.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 11 2011, 11:36
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(_Pasha @ Feb 11 2011, 08:07)   Стало быть, Вы не умеете его готовить в условиях многозадачности? Причём здесь мнонгозадачность и DS18B20. Если Вы возьмёте листок бумаги и посчитаете поведение USART при использовании UDRE в качестве прерывания для обмена с DS , то увидите что , если не изменяет память, на 9 байте начинает лезть ошибка приема ответа DS . Точне посмотрю дома в записях. Считали и не я один. А запрещать и разрешать его в таком случае смысла не имеет , если есть TX. Цитата ReAl Так это же отлично! ...... и т.д. При передачи сразу массива данных , нафинг он вообще нужен TXC ? Tолько что бы "красиво" в конце передачи массива узнать , что последний байт массива передали. Смысл? Всё равно же считаете переданные байты либо в ноль либо до какого-то значения. Цитата Кстати , этот флаг имеет "неприятную" особенность он практически "всегда установлен". А это я написал , так как топикстартер ещё не определился , что он вообще будет использовать и нигде не озвучивал свой замысел. А "неприятную" - как Вы видите я поставил в кавычках
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Feb 11 2011, 11:40
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(ILYAUL @ Feb 11 2011, 14:36)  При передачи сразу массива данных , нафинг он вообще нужен TXC ? Tолько что бы "красиво" в конце передачи массива узнать , что последний байт массива передали. Смысл? Чтобы максимально быстро перевести драйвер RS485 в на приём и освободить линию после завершения передачи последнего байта. UART используется и для симплексных каналов связи. Или чтобы отключить передатчик для экономии батарейки например...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|