Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывание EXTI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
juvf
st32f401. Поподаю в прерывание EXTI3_IRQHandler(). Флаги прерывания нулю равны, но прерывание срабатывает. Не могу понять почему. Вот обработчик дебажный
Цитата
extern "C" void EXTI3_IRQHandler()
{
static uint32_t a;
a = EXTI->PR;
EXTI_ClearFlag(EXTI_Line3);
}
EXTI->PR равно нулю. а всегда равна нулю. Почему попадаю в прерывание. Как это отловить?
scifi
Остановиться в обработчике прерывания, посмотреть регистры NVIC.
adnega
Цитата(juvf @ Nov 5 2016, 13:30) *
Почему попадаю в прерывание. Как это отловить?

Видимо, вы его разрешили и сконфигурировали - вот и попадаете.
Вопрос не понятный: вас смущает, что вообще прерывание возникает? или что оно и должно возникать, но PR при этом нулевой?

Есть у Cortex такая штука как повторный вход в прерывание по уму обработчик должен проверять условие.
Например,
Код
void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
  {
    /* Toggle LED3 */
    STM_EVAL_LEDToggle(LED3);
    
    /* Clear the EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line0);
  }
}
juvf
Цитата(scifi @ Nov 5 2016, 16:39) *
Остановиться в обработчике прерывания, посмотреть регистры NVIC.

А какие регистры?

Цитата
Вопрос не понятный: вас смущает, что вообще прерывание возникает? или что оно и должно возникать, но PR при этом нулевой?
Смущяет то, то оно не должно возникать, PR равен нулю, как и положенно, а вызов обработчика есть.


Суть в следующем: я настраиваю прерывание EXTI3 как переход из "1" в "0" на ноге РА3 и ухожу в стоп режим (PWR_STOPEntry_WFI). на ноге РА3 стоит "1"... ни каких дерганий и помаргиваний.... процессор выходит из стоп режима. Почему? Единственное разрешенное прерывание для выхода из стопа это переход на ноге РА3 из 1 в 0. Может вовсе не по EXTI3 выхожу из стопа.... поставил ловушку в обработчике прерывания EXTI3_IRQHandler(). Попадаю после стопа сразу в этот обработчик..... значит просыпаюсь по ексти3 всётаки.....
далее... сразу после пробуждения, ещё до входа в прерывание читаю EXTI->PR, там ноль. после настройки HSE разрешаю прерывания и тут же попадаю в обработчик EXTI3_IRQHandler(). Опять проверяю EXTI->PR. Там НОЛЬ!!! черт с ним, со стопом... потом разберусь.... вопрос в следующем - почему я попадаю в обработчик прерывания, когда флаг прерывания равен нулю? Если EXTI->PR == 0, то не было событий ни каких в эксти. Раз не было событий, какого лешего идет вызов обработчика?
scifi
Цитата(juvf @ Nov 6 2016, 11:57) *
А какие регистры?

Очевидно же: те, которые могут представлять интерес. Можно все. Не стесняйтесь, открывайте мануал и читайте про то, что такое NVIC, зачём он нужен, и как он работает.
juvf
Цитата(scifi @ Nov 6 2016, 14:18) *
Очевидно же: те, которые могут представлять интерес. Можно все. Не стесняйтесь, открывайте мануал и читайте про то, что такое NVIC, зачём он нужен, и как он работает.
...ять.... знал бы прикуп, жилбы в рио как решить проблему и какие регистры помогут, сюда бы не обращался. Какой конкретно регистр в NVIC может сказать чем было вызвано прерывание? Их там не так много.
Interrupt set-enable registers (NVIC_ISERx) - этот? наврятли.
может это Interrupt clear-enable registers (NVIC_ICERx)? Из названия видно что не этот.
может быть вот этот "The IABR0-IABR2 registers indicate which interrupts are active.".... 512 в нем. это вроде как 9-ый бит в "1", т.е. 9-ое прерывание активно. 9-е прерывание это как раз EXTI Line3 interrupt. Но ПОЧЕМУ оно активно? В каком NVIC регистре конкретно посмотреть ПОЧЕМУ ПРЕРЫВАНИЕ СРАБОТАЛО?
adnega
Цитата(juvf @ Nov 6 2016, 13:06) *
ПОЧЕМУ ПРЕРЫВАНИЕ СРАБОТАЛО?

Похоже на чудеса. Попробуйте запретить прерывание для EXTI3 (точнее не разрешайте его в NVIC).
Может, у вас где-то в другом месте бага и управление как-то попадает в функцию EXTI3_IRQHandler().
scifi
Цитата(juvf @ Nov 6 2016, 13:06) *
может быть вот этот "The IABR0-IABR2 registers indicate which interrupts are active.".... 512 в нем. это вроде как 9-ый бит в "1", т.е. 9-ое прерывание активно. 9-е прерывание это как раз EXTI Line3 interrupt. Но ПОЧЕМУ оно активно? В каком NVIC регистре конкретно посмотреть ПОЧЕМУ ПРЕРЫВАНИЕ СРАБОТАЛО?

На самом деле я имел в виду исключить вариант, когда другое прерывание вызывает этот обработчик (кривая таблица векторов, например). Исключили.
Про EXTI и выход из Stop mode, увы, ничего не могу сказать, ибо не доводилось использовать. В мануале оно всё как-то хитровывернуто описано, разбираться лень.
juvf
Цитата(adnega @ Nov 6 2016, 15:37) *
Попробуйте запретить прерывание для EXTI3 (точнее не разрешайте его в NVIC).
Может, у вас где-то в другом месте бага и управление как-то попадает в функцию EXTI3_IRQHandler().

Да я тоже думал что где-то НЕ из-за эксти падает в EXTI3_IRQHandler(). Но NVIC всётаки говорит что активное прерывание EXTI3 (спс scifi wink.gif ). Есть ещё мысль, что к EXTI3 подключено какоенить другое событие не только порт РА3? например RTC или какая нить другая периферия.... лан... буду разбираться...

Цитата
Похоже на чудеса.
Согласен.... хоть проц перепаивай...
adnega
Цитата(juvf @ Nov 6 2016, 13:51) *
Согласен.... хоть проц перепаивай...

Может, оптимизация как-то мудрит и выкидывает переменную "a".
Как вы установили, что PR == 0 ?
juvf
Цитата(adnega @ Nov 6 2016, 16:56) *
Как вы установили, что PR == 0 ?

в статическую переменную записал EXTI->PR после выхода из стопа и после входа в прерывание.

ПОБЕДИЛ ЧУДО!!! Заработало!!! В 2-х словах - обработчик может быть вызван без флага прерывания, или это можно назвать отложенное прерывание. Если интересно... распишу...
adnega
Цитата(juvf @ Nov 6 2016, 15:00) *
ПОБЕДИЛ ЧУДО!!! Заработало!!! В 2-х словах - обработчик может быть вызван без флага прерывания, или это можно назвать отложенное прерывание. Если интересно... распишу...

Как правило есть два бита: периферийный и NVIC-овский.
Когда периферийный срабатывает, он устанавливает NVIC-овский.
Когда дело доходит до обработчика, NVIC-овский аппаратно сбрасывается (при выходе?),
а в обработчике нужно сбросить периферийный. Если делать это в самом конце, то
будет повторное вхождение в обработчик, но уже со сброшенным периферийным битом.
Поэтому всегда нужно проверять установку периферийного бита. И сбрасывать его как можно раньше,
а если сбрасываешь в конце обработчика, то перед выходом добавить NOP, а еще правильнее барьер (DSB?).

juvf
2adnega, это всё известно и периферийный сбрасывается сразу же при входе в прерывание. подвох в другом месте был. в NVIC. вобщем при входе в стоп готовлю эксти3 для пробуждения, разрешаю прерывание от ексти3 и ухожу в стоп. после пробуждения сбрасываю флаг эксти3 и запрещаю прерывания от эксти3. Вот тут и грабля....

после выхода из стопа всего лиш запрещал прерывания, т.е. думал что строчки NVIC_DisableIRQ(EXTI3_IRQn); для запрета прерывания достаточно. Так то да, NVIC больше не вызывал обработчик, но нога РА3 дергалась и EXTI3_IRQn срабатывало и взводило флаг прерывания в EXTI, и флаг NVIC-овский, так называемый IRQn pending.

перед очередным стопом я сбрасывал флаг в EXTI (PR) и разрешал NVIC-ку прерывание. А у NVIC взведён и ждет IRQn pending. Он принудительно вызывал обработчик прерывания, не смотря на то, что у EXTI прерывания нет.

ps а сбросить IRQn pending в NVIC не получилось. Вроде NVIC_ClearPendingIRQ(EXTI3_IRQn) должен сбросить.... но он не сбрасывает. только вызов обработчика сбрасывает этот пендинг.
adnega
Цитата(juvf @ Nov 6 2016, 15:50) *
после пробуждения сбрасываю флаг эксти3 и запрещаю прерывания от эксти3. Вот тут и грабля....

Может, NVIC-регистры не трогать, а запрет обработки делать на уровне EXTI ?

Цитата(juvf @ Nov 6 2016, 15:50) *
ps а сбросить IRQn pending в NVIC не получилось. Вроде NVIC_ClearPendingIRQ(EXTI3_IRQn) должен сбросить.... но он не сбрасывает. только вызов обработчика сбрасывает этот пендинг.

Я обычно делаю так: настраиваю периферию, но не разрешаю прерывание; настраиваю и разрешаю NVIC предварительно сбросив флаг от периферии;
разрешаю прерывание в периферии.

Запрещаю прерывания только на уровне периферии (например, при передаче по UART).
Запрещать/разрешать в NVIC давным-давно решил для себя считать источником потенциальных проблем (приоритеты, многопоточность,
правильные последовательности разрешения/запрещения).
juvf
Цитата(adnega @ Nov 6 2016, 18:59) *
Может, NVIC-регистры не трогать, а запрет обработки делать на уровне EXTI ?
да кстати.... может вы правы... я тоже делаю все запреты/разрешения прерывания на уровне перефирии, например

Код
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_TC, DISABLE);
Но с EXTI первый раз свезался, нужен был стоп режим.... почему-то на уровень NVIC ушел. Спс за совет.
esaulenka
Цитата(adnega @ Nov 6 2016, 15:27) *
Как правило есть два бита: периферийный и NVIC-овский. Когда периферийный срабатывает, он устанавливает NVIC-овский.
Когда дело доходит до обработчика, NVIC-овский аппаратно сбрасывается (при выходе?),
а в обработчике нужно сбросить периферийный. Если делать это в самом конце, то будет повторное вхождение в обработчик, но уже со сброшенным периферийным битом.
Поэтому всегда нужно проверять установку периферийного бита. И сбрасывать его как можно раньше, а если сбрасываешь в конце обработчика, то перед выходом добавить NOP, а еще правильнее барьер (DSB?).

Повторный вход в обработчик подтверждаю, есть такое.
Правда, я лечил просто переносом сброса наверх - дополнительная проверка не нужна.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.