реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Не срабатывает внешнее прерывание
Rash
сообщение Dec 2 2014, 19:46
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Всем привет.

Столкнулся с такой проблемой в STM32F407: Если сделать критическую секцию для внешнего прерывания, то если его отключить на время выполнения кода, а потом опять включить, но за время выполнения кода пришло внешнее прерывание, то при последующем включении внешнего прерывания, прерывание не сработает. Т.е. получается будет пропущенное прерывание на время его отключения. Как сделать чтобы при включении внешнего прерывания его сработавший флаг был активен?

Код инициализации
CODE
#define TEST_IRQ_PIN GPIO_Pin_14
#define TEST_IRQ_GPIO_PORT GPIOE
#define TEST_EXTI_Line EXTI_Line14
#define TEST_IRQChannel EXTI15_10_IRQn
#define TEST_EXTI_PortSource EXTI_PortSourceGPIOE
#define TEST_GPIO_PinSource GPIO_PinSource14


// отключение обработки внешнего прерывания
#define ENTER_NOIRQ_REGION() { ITStatus exti_status = EXTI_GetIRQStatus(TEST_EXTI_Line); \
EXTI_Disable_IRQ(TEST_EXTI_Line); \

// включение обработки прерывания
#define LEAVE_NOIRQ_REGION() if(exti_status != RESET) \
EXTI_Enable_IRQ(TEST_EXTI_Line); \
}


GPIO_InitStructure.GPIO_Pin = TEST_IRQ_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(TEST_IRQ_GPIO_PORT, &GPIO_InitStructure);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(TEST_EXTI_PortSource, TEST_GPIO_PinSource);

EXTI_InitStructure.EXTI_Line = TEST_EXTI_Line;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = TEST_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


Такой вид имеет код приложения
Код
ENTER_NOIRQ_REGION();
           ...
   Копирование данных
           ...
LEAVE_NOIRQ_REGION();


Сообщение отредактировал IgorKossak - Dec 2 2014, 19:55
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Dec 2 2014, 20:33
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



если флаг прерывания есть, то оно сработает, и пока флаг не снимите будет долбить. Потому если было внешнее прерывание и оно было замечено и был поставлен флаг, то после разрешения прерываний как оно может не сработать? Вы точно разрешая прерывания никакие флаги не сбрасываете на всякий случай?
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 2 2014, 20:47
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



да сам удивлён такой ситуации. Штрихуешь выключения/включение внешнего прерывания на время выполнения необходимого кода и всё работает как часы. Флаги ни какие больше не сбрасываю, в коде на момент отключения внешнего прерывания копирование из одного буфера в другой, ни какой работы с внешней периферией.
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 3 2014, 08:12
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Не нашел исходников EXTI_Disable_IRQ() и EXTI_Enable_IRQ().
Может там PendingBit сбрасывается (скорее всего при разрешении)?
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 3 2014, 08:31
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Код
static inline void EXTI_Enable_IRQ(uint32_t EXTI_Line)
{
  EXTI->IMR |= EXTI_Line;
}

static inline void EXTI_Disable_IRQ(uint32_t EXTI_Line)
{
  EXTI->IMR &= ~EXTI_Line;
}

static inline ITStatus EXTI_GetIRQStatus(uint32_t EXTI_Line)
{
  if ((EXTI->IMR & EXTI_Line) != (uint32_t)RESET)
    return SET;

  return RESET;
}
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Dec 3 2014, 08:46
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



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

может сделали такое гадство, что
EXTI->IMR |= EXTI_Line;
сбрасывает и флаг заодно?
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 3 2014, 08:57
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Я пробовал читать этот флаг перед EXTI->IMR |= EXTI_Line; и ставил даже __DSB() между чтением, потом проверял если флаг был установлен, вызвать прерываний программно, но флаг ни разу установленным не оказался.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Dec 3 2014, 09:15
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



погодите.
Так если флага нет, то и прерывания не будет.
То есть у вас происходит внешнее прерывание и флага не ставиться? Ну тогда его действительно не произойдет. Надо понять почему флаг не ставиться...
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 3 2014, 09:30
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



попытаюсь вкратце объяснить. По внешнему прерыванию опрашивается внешний приёмопередатчик, так вот он перестают опрашиваться если пропустил от него хоть одно прерывания (по которому высчитывается его статус). Если ручками при отладке установить бит нужного прерывания в EXTI_SWIER, то сработает обработчик и всё пойдёт как раньше, опять до критического совпадения.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Dec 3 2014, 09:53
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



вот сейчас мне вдруг подумалось
вы включение и маскирование прерывания не перепутали?

вы не выключаете реакцию, а выключаете маску, кажется...

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

или это я глупость сказал?
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 3 2014, 10:34
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Dec 2 2014, 22:46) *
Т.е. получается будет пропущенное прерывание на время его отключения.

Если взглянуть на блок-схему EXTI, то ровно так оно и должно работать: регистр маскирования не пропускает сигнал со входа в регистр Pending Request.

Цитата(Rash @ Dec 2 2014, 22:46) *
Как сделать чтобы при включении внешнего прерывания его сработавший флаг был активен?

Опять же, если взглянуть на блок схему, то напрашивается вывод, что прерывание надо маскировать на уровне NVIC. Другие способы не просматриваются.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 3 2014, 10:59
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(scifi @ Dec 3 2014, 14:34) *
прерывание надо маскировать на уровне NVIC. Другие способы не просматриваются.

+1
Так и никак иначе.
Запрещать и разрешать через NVIC->ICER и NVIC->ISER.
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 3 2014, 17:20
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Я понял, спасибо за разъяснение.
Но если работать через NVIC, то получается если запретить EXTI15_10_IRQn, то не работать будут сразу 5 прерываний объединённых в эту группу. Не критично конечно, но не приятно, нужно на будущее учесть. В STM с внешними прерываниями какая то урезанность, например: на два одинаковых бита различных портов нельзя сделать прерывания (PA2 и PB2).
Ещё такой вопрос если мне нужно определить включено ли сейчас прерывание, нужно читать регистр ISER или также можно ISPR?
т.е. мне нужно прочитать состояние прерывания, запомнить его, выполнить операцию и вернуть обратно статус.
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 3 2014, 18:11
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Dec 3 2014, 20:20) *
Но если работать через NVIC, то получается если запретить EXTI15_10_IRQn, то не работать будут сразу 5 прерываний объединённых в эту группу. Не критично конечно, но не приятно, нужно на будущее учесть.

Ну да, всегда будут какие-то ограничения.
Но никто не отменял творческий подход: если есть свободный таймер, к примеру, то можно его входы использовать для внешних прерываний.
Go to the top of the page
 
+Quote Post
Rash
сообщение Dec 3 2014, 21:12
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Объясните, пожалуйста, смысл регистров NVIC ISPR и ICPR?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:33
Рейтинг@Mail.ru


Страница сгенерированна за 0.06058 секунд с 7
ELECTRONIX ©2004-2016