|
Прерывания в Cortex-M3 |
|
|
|
Nov 24 2011, 02:31
|
Участник

Группа: Участник
Сообщений: 36
Регистрация: 5-12-10
Пользователь №: 61 414

|
Добрый день! Возникла следующая интересная проблема. По ходу выполнения прошивки в какой то момент происходит зацикливание программы на прерывании от USART1. То есть выполняется запуск обработчика прерываний с частотой примерно 100 кГц. Основная программа успевает сделать несколько инструкций после чего снова происходит прерывание. При этом если остановить обработку прерывания отладчиком и походить по инструкциям нормальный ход программы восстанавливается. Прерывания разрешены только на прием, флаг готовых данных не взведен. В регистре NVIC->ICSR указывается что активное прерывание от usart1. С чем может быть связанно такое поведение? Осциллографом контролировал линию - стабильная единица на обоих линиях. Стабильно повторяется. Прерывания по приему не запрещается и разрешено постоянно. Код void USART1_IRQHandler (void) { VD3R_ON; VD3G_ON;
if (USART_GetITStatus(USART1,USART_IT_TXE)) { // USART_ClearITPendingBit(USART1,USART_IT_TXE);
} if (USART_GetITStatus(USART1,USART_IT_RXNE)) { // USART_ClearITPendingBit(USART1,USART_IT_RXNE);
unsigned char receive_char=USART_ReceiveData(USART1);
if (!modemmode) {
}
VD3R_OFF; VD3G_OFF; }
|
|
|
|
|
 |
Ответов
|
Nov 24 2011, 05:31
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 15-11-07
Пользователь №: 32 363

|
Цитата(1kvi1 @ Nov 24 2011, 05:31)  Добрый день!
Возникла следующая интересная проблема.
По ходу выполнения прошивки в какой то момент происходит зацикливание программы на прерывании от USART1.
То есть выполняется запуск обработчика прерываний с частотой примерно 100 кГц.
Основная программа успевает сделать несколько инструкций после чего снова происходит прерывание. ... не любит STM чтобы использовали код не так, как в их примерах)). Заметил тоже самое с другими прерываниями. Например с таймером, вот такой код работает нормально: Код void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерывания
} } а теперь для теста добавим пару переменных Код void TIM4_IRQHandler(void) { CountTest1++; if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерывания CountTest2++; } } В этом случае все рассыпается, переменная CountTest1 будет постоянно быстрее накапливаться, чем переменная CountTest2. Это говорит о том, что void TIM4_IRQHandler(void) вызывается намного чаще, чем планировалось. Но вот такой код: Код void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерывания CountTest2++; } CountTest1++; } работает нормально и CountTest1 всегда равна CountTest2. Получается, что вставка кода до строки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) все ломает. Это одинаково проявляется на STM32F207 и STM32F407. Для эксперимента пробовал добавить GPIOC->ODR ^= GPIO_Pin_13; и посмотреть осциллографом длительность на GPIO_Pin_13. Получается полный хаос. 150 мс прерывания работают как положено раз в 1 мс (таймер настроен на 1 мс), потом на 150 мс висит 0 на GPIO_Pin_13. Может зависнуть на 150 мс и с 1 на выходе GPIO_Pin_13. Код void TIM4_IRQHandler(void) { GPIOC->ODR ^= GPIO_Pin_13; //индицируем прерывание для отладки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерывания CountTest2++; }
} опять же, если GPIOC->ODR ^= GPIO_Pin_13, добавить после строки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET), то все оживает и работает как положено.
Сообщение отредактировал vptr - Nov 24 2011, 05:32
|
|
|
|
|
Nov 24 2011, 05:58
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 15-11-07
Пользователь №: 32 363

|
да и обработка прерывания завершается TIM_ClearITPendingBit(TIM4, TIM_IT_Update) все как в примерах Код void TIM4_IRQHandler(void) { GPIOC->ODR ^= GPIO_Pin_13; //индицируем прерывание для отладки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерыания CountTest2++; TIM_ClearITPendingBit(TIM4, TIM_IT_Update); } }
Сообщение отредактировал vptr - Nov 24 2011, 06:02
|
|
|
|
|
Nov 24 2011, 08:37
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(vptr @ Nov 24 2011, 07:58)  да и обработка прерывания завершается TIM_ClearITPendingBit(TIM4, TIM_IT_Update) все как в примерах Код void TIM4_IRQHandler(void) { GPIOC->ODR ^= GPIO_Pin_13; //индицируем прерывание для отладки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { //здесь обработчик прерыания CountTest2++; TIM_ClearITPendingBit(TIM4, TIM_IT_Update); } } В форуме здесь, а также на форуме ST, было упомянуто вообще-то для всех Кортексов (поищите сами), что при сбросе флагов прерываний непосредственно перед выходом из ISR, возможен повторный вызов ISR по причине конвейера и особенностей доступа по внутренним шинам. Поэтому перенесите TIM_ClearITPendingBit(TIM4, TIM_IT_Update); в начало ветви обработки, то есть поместив рабочие инструкции между сбросом флага и выходом из ISR.
|
|
|
|
|
Nov 24 2011, 09:52
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 15-11-07
Пользователь №: 32 363

|
Цитата(KnightIgor @ Nov 24 2011, 11:37)  В форуме здесь, а также на форуме ST, было упомянуто вообще-то для всех Кортексов (поищите сами), что при сбросе флагов прерываний непосредственно перед выходом из ISR, возможен повторный вызов ISR по причине конвейера и особенностей доступа по внутренним шинам. Поэтому перенесите TIM_ClearITPendingBit(TIM4, TIM_IT_Update); в начало ветви обработки, то есть поместив рабочие инструкции между сбросом флага и выходом из ISR. спасибо, судя по всему в этом и есть причина вот этот код рабочий Код void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update);// если вызывать позже, то возможен хаос //здесь обработчик прерыания CountTest2++; ... }
} Если TIM_ClearITPendingBit(TIM4, TIM_IT_Update) вызывать позже в обработчике прерывания (причем не сразу, а так через несколько команд), то наступает описанный выше хаос. В общем сам виноват, в примерах от STM так и сделано, сперва if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET), потом TIM_ClearITPendingBit(TIM4, TIM_IT_Update) и только после этого код обработки прерывания причем даже код ниже становится рабочим, но понятно что так делать нельзя, т.к. любые действия до TIM_ClearITPendingBit(TIM4, TIM_IT_Update); не есть хорошо Код void TIM4_IRQHandler(void) { GPIOC->ODR ^= GPIO_Pin_13; //индицируем прерывание для отладки if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update);// если вызывать позже, то возможен хаос //здесь обработчик прерывания CountTest2++; }
}
Сообщение отредактировал vptr - Nov 24 2011, 09:53
|
|
|
|
Сообщений в этой теме
1kvi1 Прерывания в Cortex-M3 Nov 24 2011, 02:31 demiurg_spb Думаю что это связано с тем что запросы на прерыва... Nov 24 2011, 04:44 1kvi1 ТО что флаги автоматически сбрасываются - это мне ... Nov 24 2011, 05:15 demiurg_spb Цитата(vptr @ Nov 24 2011, 09:31) не люби... Nov 24 2011, 05:36  AHTOXA Возможно, это то, что называется "spurious in... Nov 24 2011, 06:08   demiurg_spb Цитата(KnightIgor @ Nov 24 2011, 12:37) В... Nov 24 2011, 08:50    KnightIgor Цитата(demiurg_spb @ Nov 24 2011, 10:50) ... Nov 24 2011, 09:34    demiurg_spb Цитата(vptr @ Nov 24 2011, 13:52) и тольк... Nov 25 2011, 04:37     dxp Цитата(demiurg_spb @ Nov 25 2011, 11:37) ... Nov 25 2011, 06:34      demiurg_spb Цитата(dxp @ Nov 25 2011, 10:34) А не пом... Nov 25 2011, 06:58       dxp Цитата(demiurg_spb @ Nov 25 2011, 13:58) ... Nov 25 2011, 15:21 andrewlekar А по-моему никто ничего не рушит, а просто прерыва... Nov 24 2011, 05:42 1kvi1 "spurious interrupt" - да был такой опыт... Nov 24 2011, 08:53 ViKo А чего-й-то у меня прерывание работает простенько?... Nov 25 2011, 12:04 demiurg_spb Цитата(ViKo @ Nov 25 2011, 16:04) А чего-... Nov 28 2011, 08:01  ViKo Цитата(demiurg_spb @ Nov 28 2011, 11:01) ... Nov 28 2011, 08:50 1kvi1 К сожалению, описанные выше ситуации, когда флаг з... Nov 27 2011, 15:33 dxp Цитата(1kvi1 @ Nov 27 2011, 22:33) Интере... Nov 27 2011, 16:24 V_M_Luck ЦитатаПоэтому, имхо, грамотный подход - это исполь... Dec 8 2011, 10:13 1kvi1 Внимательное чтение документации помогло определит... Dec 9 2011, 09:54
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|