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

 
 
> Прерывания в Cortex-M3
1kvi1
сообщение Nov 24 2011, 02:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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;
}


Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
vptr
сообщение Nov 24 2011, 05:31
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
vptr
сообщение Nov 24 2011, 05:58
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Nov 24 2011, 08:37
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
vptr
сообщение Nov 24 2011, 09:52
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 25 2011, 04:37
Сообщение #6


неотягощённый злом
******

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



Цитата(vptr @ Nov 24 2011, 13:52) *
и только после этого код обработки прерывания причем даже код ниже становится рабочим, но понятно что так делать нельзя, т.к. любые действия до TIM_ClearITPendingBit(TIM4, TIM_IT_Update); не есть хорошо
Думаю что это уже не важно. Главное чтобы ClearITPendingBit физически успел выполниться до ret. Все остальные измышления ИМХО не имеют под собой основания.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 25 2011, 06:34
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(demiurg_spb @ Nov 25 2011, 11:37) *
Думаю что это уже не важно. Главное чтобы ClearITPendingBit физически успел выполниться до ret. Все остальные измышления ИМХО не имеют под собой основания.

А не поможет тут использование инструкций-барьеров, чтобы гарантировать выполнение? А так, вообще-то, да - грабли конкретные.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 25 2011, 06:58
Сообщение #8


неотягощённый злом
******

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



Цитата(dxp @ Nov 25 2011, 10:34) *
А не поможет тут использование инструкций-барьеров, чтобы гарантировать выполнение?

Код
__DSB();  // Ensure completion of memory access
Вы об этом?
По идее должно помочь. Вот что об этом в CM3_TRM пишут.
Цитата
To prevent bus wait cycles from stalling the processor during data stores, buffered stores
to the DCode and System buses go through a one-entry write buffer. If the write buffer is full, subsequent accesses to the bus stall until the write buffer has drained.
The write buffer is only used if the bus waits the data phase of the buffered store, otherwise the transaction completes on the bus.
DMB and DSB instructions wait for the write buffer to drain before completing. If an interrupt comes in while DMB/DSB is waiting for the write buffer to drain,
the opcode after the DMB/DSB is returned to on the completion of the interrupt. This is because interrupt processing is a memory barrier operation.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 25 2011, 15:21
Сообщение #9


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(demiurg_spb @ Nov 25 2011, 13:58) *
Код
__DSB();  // Ensure completion of memory access
Вы об этом?
По идее должно помочь.

Да, про это. Возможно, в данной ситуации больше подходит ISB, детально не разбирался. Но идея общая - на процах с конвейером типична ситуация, когда данные ходят не совсем так, как можно предположить, глядя в код. Поэтому там обычно (у грамотного производителя) предусмотрены средства для синхронизации потока данных и потока выполнения, что как правило требуется при работе с MMR и подобными ресурсами. У Cortex-M3 это инструкции DMB, DSB, ISB, у Blackfin'а - csync и ssync, у других процов с конвейером и нетривиальными путями данных через это дело тоже должны быть аналогичные средства.

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- 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
- - 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


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

 


RSS Текстовая версия Сейчас: 28th July 2025 - 06:40
Рейтинг@Mail.ru


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