|
Прерывания в 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; }
|
|
|
|
2 страниц
< 1 2
|
 |
Ответов
(15 - 23)
|
Nov 25 2011, 06:58
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 25 2011, 12:04
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
А чего-й-то у меня прерывание работает простенько? Правда, только по приему. (Передаю один байт, без прерываний.) Код void USART3_IRQHandler(void) // Прерывание от интерфейса с панелью { uint8_t temp = USART3->DR; // временное хранение принятого байта ... // здесь он кидается в нужное место буфера } // вот и всё! :) В настройке использую следующее (уже не знаю, что там, биты расшифровывать лень) Код USART3->BRR = (36000000 / 19200); USART3->CR1 = 0x202c; USART3->CR2 = 0x2000; USART3->CR3 = 0x0000; P.S. Из других прерываний - только SysTick_Handler.
|
|
|
|
|
Nov 25 2011, 15:21
|

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, у других процов с конвейером и нетривиальными путями данных через это дело тоже должны быть аналогичные средства. Поэтому, имхо, грамотный подход - это использовать представленные специально для этого средства и не заморачиваться на порядок выполнения выражений.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 27 2011, 15:33
|
Участник

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

|
К сожалению, описанные выше ситуации, когда флаг запроса на прерывания не успевает сбрасываться до выхода из прерывания не подходит для моего случая.
Так как в моем исходнике вставлены инструкции включения-выключения светодиодов, которые вносят необходиму задержку перед выходом из прерывания.
В документации PM0056 Programming manual с сайта st натолкнулся на следующий текст
пункт 4.3.10
Ensure software uses correctly aligned register accesses. The processor does not support unaligned accesses to NVIC registers. See the individual register descriptions for the supported access sizes. A interrupt can enter pending state even it is disabled. Before programming VTOR to relocate the vector table, ensure the vector table entries of the new vector table are setup for fault handlers, NMI and all enabled exception like interrupts. For more information see Section 4.4.4: Vector table offset register (SCB_VTOR) on page 134.
Интересует строка A interrupt can enter pending state even it is disabled.
Правильно ли я понял что прерывания могут произойти даже если они запрещены?
Сообщение отредактировал 1kvi1 - Nov 27 2011, 15:34
|
|
|
|
|
Nov 27 2011, 16:24
|

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

|
Цитата(1kvi1 @ Nov 27 2011, 22:33)  Интересует строка A interrupt can enter pending state even it is disabled.
Правильно ли я понял что прерывания могут произойти даже если они запрещены? pending - это прерывание не происходит, а висит в ожидании, т.е. событие-источник прерывания произошло и флаг прерывания встал, но управление к обработчику прерываний не передано по той или иной причине (прерывание запрещено или в данный момент выполняется другое, более приоритетное прерывание). Конкретно заинтересовавшая вас фраза буквально означает, что даже если прерывание запрещено, это не помешает логике обработки источника прерывания взвести флаг прерывания и подготовить всё для перехода к выполнению обработчика этого прерывания, когда это будет разрешено.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 28 2011, 08:01
|

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

|
Цитата(ViKo @ Nov 25 2011, 16:04)  А чего-й-то у меня прерывание работает простенько? Так и в чём вопрос-то? В случае с USART нет нуджы пендинги зачищать - они сами чистятся при чтении-записи DR. Поэтому наверное всё "простенько" и получается. Цитата(dxp @ Nov 25 2011, 19:21)  Поэтому, имхо, грамотный подход - это использовать представленные специально для этого средства и не заморачиваться на порядок выполнения выражений. +1.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 8 2011, 10:13
|
Участник

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

|
Цитата Поэтому, имхо, грамотный подход - это использовать представленные специально для этого средства и не заморачиваться на порядок выполнения выражений. А как грамотно в данном случае использовать DSB? Например, в случае с таймером: Код void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { ... TIM_ClearITPendingBit(TIM4, TIM_IT_Update); __DSB(); ... }
} Так верно?
|
|
|
|
|
Dec 9 2011, 09:54
|
Участник

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

|
Внимательное чтение документации помогло определить проблему.
Дело в том что флаг ошибки переполнения ORE при разрешенном прерывании RXNEIE также вызывает прерывание. Поэтому постоянно срабатывало прерывание и сбросить его можно только прочитав данные.
Всем спасибо, проблема решена - оказалась проще чем можно себе представить.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|