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

 
 
> STM32L151 + SDIO + FreeRTOS, BusFault после выхода из прерывания SDIO
MiklPolikov
сообщение Feb 26 2015, 15:55
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Коллеги, добрый день.
Подскажите что-нибудь !

После выхода из обработчика прерывания SDIO программа оказывается в BusFault_Handler. Глюк происходит изредка и нерегулярно.
В окне Callstuck картина каждый раз одинаковая, глюк где-то в коде ядра ОС
Если установку эвентов в прерывании заменить на глобальную переменную, а ожидание эвентов на проверку этой переменной в цикле while , то глюка не происходит.

Приоритет прерывания 12.

FreeRTOS настроена так :
Код
#define configKERNEL_INTERRUPT_PRIORITY         255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;; ); }  /*проходит не ругается  */


Обработчик прерывания
Код
void SDIO_IRQHandler(void)
{
       static portBASE_TYPE xHigherPriorityTaskWoken;
       static unsigned int  SDIO_STA_MASK;

        xHigherPriorityTaskWoken = pdFALSE;
    
     SDIO_STA_MASK=SDIO->STA & 0x00ffffff; //т.к. в EventGroup можно передавать только 24 бита
    
     xEventGroupSetBitsFromISR(x_SDIO_Transmit_EventGroup, SDIO_STA_MASK ,&xHigherPriorityTaskWoken);

     portYIELD_FROM_ISR(xHigherPriorityTaskWoken == pdTRUE);

     SDIO->ICR= SDIO_STA_MASK; //сбрасываем флаги прерывания //

        xxxx=123; //Глобальная переменная для поиска места глюка
}

Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 25)
aaarrr
сообщение Feb 26 2015, 20:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Смотрите значения BFSR и BFAR.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 00:15
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



CFSR = 0x00008200 (во всех случаях)
То есть, стоят биты
15 BFARVALID BFAR holds a valid fault address.
9 PRECISERR Precise data bus error . A data bus error has occurred, and the PC value stacked for the exception return points to
the instruction that caused the fault.

BFAR=0xE000ED00 или 0xC0008830
Что по этим адресам, показано на картинках.

Мне не приходит в голову, что со всем этим делать.

Ещё, заметил, что глюк происходит не в одном месте, а в двух: а)во время ожидания эвента из прерывания(чаще) , и б) во время ожидания другого эвента просто из задачи. Т.е. вроде как и с прерыванием не связано, а связано только с эвентом. Множество других эвентов работают без проблем.
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 27 2015, 09:29
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Feb 27 2015, 03:15) *
Мне не приходит в голову, что со всем этим делать.

Надо найти инструкцию, вызвавшую исключение, затем посмотреть, откуда в ней мог взяться левый адрес и кто его мог испортить.
Для начала можно проверить простые варианты, вроде нехватки стека задачи или выхода за границы буфера при чтении карты.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 10:48
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вот такой массив их эвентов и такое обращение к нему причиной проблемы быть не может ?
Я что-то засомневался, ведь EventGroupHandle_t это указатель.
Получается объявление аналогичное
char *x[2];

Код
#define SD_CARDS_COUNT 2
#define SD1 0
#define SD2 1

EventGroupHandle_t xSD_State_EventGroup[SD_CARDS_COUNT];

...............

xSD_State_EventGroup[SD1]=xEventGroupCreate();
xSD_State_EventGroup[SD2]=xEventGroupCreate();

..............

char sd_n = SD2;
xEventGroupClearBits(xSD_State_EventGroup[sd_n], INIT_COMPLETE);


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 27 2015, 11:05
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MiklPolikov @ Feb 27 2015, 15:48) *
Код
#define SD_CARDS_COUNT

А где циферка-то? Чему равно SD_CARDS_COUNT?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 11:08
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ Feb 27 2015, 14:05) *
А где циферка-то? Чему равно SD_CARDS_COUNT?

Опечатка, в коде #define SD_CARDS_COUNT 2


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 27 2015, 19:43
Сообщение #8


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Feb 26 2015, 18:55) *
...Если установку эвентов в прерывании заменить...


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

муторно конечно же, но причину отроете обязательно в конце концов.

можно конечно же сделать "ход конём" и полностью сэмулировать взаимодейтвие прерывания от карточки, оси и потоков. если
рыба упадёт - то это уже гораздо меньше кода. если нет - идём уже от меньшего к большему - копируем околотемный функционал,
пытаясь проявить бяку. ну и т.д...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 20:12
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(kolobok0 @ Feb 27 2015, 22:43) *
тупо отключать куски кода методом комментирования


Уже двинулся по этому пути.
Но проблема в том, что глюк уж больно хитрый, то он есть, то нет, и если убираешь одно стабильно-глючное место, то стабильно-глючным становится другое.
Я-то надеялся, что мне сейчас скажут какую-нибудь хитрость про настройку FreeRTOS , которую я не знал, и проблема легко решится : )


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 21:45
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Другой вопрос:
Делаю xTimerResetFromISR , после этого программа попадает в функцию таймера, и в это время в окне Call Stack появляется prvTaskExitError . Откуда эта ошибка ? Она означает, что программа где-то вышла из бесконечного цикла внутри задачи, так ? Для чистоты эксперимента, никаких задачь нету. есть только функция таймера и прерывание (от кнопки).

Код
///функция таймера
void vTimerCallback_Buttons( TimerHandle_t  x_Timer)
{
   char result;
   result =1; // тут точка останова, на которой в Call Stack  уже появились   2шт  prvTaskExitError

}

//Прерывание от кнопки
void EXTI9_5_IRQHandler (void)
{
    
     static portBASE_TYPE xHigherPriorityTaskWoken;
    
     xHigherPriorityTaskWoken = pdFALSE;
    
    EXTI->PR|=(1<<7);
    EXTI->PR|=(1<<9);
    
    xTimerResetFromISR(x_Timer_Buttons, &xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken == pdTRUE);            
}

...................
//так создаётся таймер
x_Timer_Buttons=xTimerCreate("x_Timer_Buttons", 1000/portTICK_RATE_MS, pdFALSE , ( void * )1,       vTimerCallback_Buttons);

Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 27 2015, 22:18
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Приоритеты прерываний настроены?
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 27 2015, 23:24
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(aaarrr @ Feb 28 2015, 01:18) *
Приоритеты прерываний настроены?

Вроде бы да :
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0xb0
Т.к. в STM32 для определения приоритета используются биты 7-4 , то это приоритет 0xB или 11.
Стало быть, те прерывания, где есть функции API , должны иметь приоритеты ниже, т.е. 15-11 включительно. У меня так и сделано.
Всё верно ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 27 2015, 23:55
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Feb 28 2015, 02:24) *
Всё верно ?

Вроде так. А subpriority зарублены?
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 28 2015, 00:38
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(aaarrr @ Feb 28 2015, 02:55) *
Вроде так. А subpriority зарублены?


Не совсем понимаю вопроса. У меня у всех прерываний разные приоритеты. Вроде бы это означает, что о субприоритетах можно не думать.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 28 2015, 01:02
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Feb 28 2015, 03:38) *
Не совсем понимаю вопроса. У меня у всех прерываний разные приоритеты. Вроде бы это означает, что о субприоритетах можно не думать.

Можно не думать, только если Вы не пользуетесь NVIC_Init() или установлен режим без субприоритетов - NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ),
в противном случае приоритеты ОС (MAX_SYSCALL_INTERRUPT_PRIORITY) и прерываний, сконфигурированных вызовом NVIC_Init(),
окажутся в разных размерностях.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 28 2015, 14:36
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Картина проясняется.

Есть две задачи.
Есть два несвязанных друг с другом прерывания. Первое прерывание выдаёт симафор в первую задачу, второе эвенты во вторую.
И время от времени из-за какого-то наложения прерываний друг на друга возникает BusFault.
Бит 9 в CFSR говорит о том что : "PRECISERR Precise data bus error . A data bus error has occurred, and the PC value stacked for the exception return points to
the instruction that caused the fault" Т.е. речь как раз о проблеме при выходе из прерывания, из стека в PC загружается неправильное значение !!!!



В регистр SCB->AIRCR есть поле PRIGROUP , в котором задаётся, какие из 8и битов обозначают приоритет а какие субприоритет.
Раньше это поле было 0, хотя такого значения в документации нету, непонятно что это значит.
Сейчас пишу значение 3, т.е. 4 старших бита означают приоритет, субприоритетов нет.
Проверяю что записалось и что больше никогда не меняется.
Для конфигурации прерываний использую стандартные Кейловские NVIC_SetPriority и NVIC_EnableIRQ. Они пушут приоритет в старшие 4 бита, как и надо.
Вроде бы теперь настроил правильно, но глюк остался.
Вопрос: где в операционке настраивается то же самое ? Каким образом операционка понимает, в какие биты нужно писать её приоритеты ?




--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 28 2015, 15:01
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Feb 28 2015, 17:36) *
Бит 9 в CFSR говорит о том что : "PRECISERR Precise data bus error . A data bus error has occurred, and the PC value stacked for the exception return points to
the instruction that caused the fault" Т.е. речь как раз о проблеме при выходе из прерывания, из стека в PC загружается неправильное значение !!!!

Совсем не так. Случилась ошибка доступа к данным (скажем, обращение по несуществующему адресу), сохраненное значение PC содержит адрес инструкции, вызвавшей исключение.

Цитата(MiklPolikov @ Feb 28 2015, 17:36) *
Вроде бы теперь настроил правильно, но глюк остался.
Вопрос: где в операционке настраивается то же самое ? Каким образом операционка понимает, в какие биты нужно писать её приоритеты ?

Проверьте значения непосредственно в регистрах NVIC. В ОС нигде не настраивается, просто задается число для записи в регистр.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 28 2015, 15:27
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(aaarrr @ Feb 28 2015, 18:01) *
Проверьте значения непосредственно в регистрах NVIC. В ОС нигде не настраивается, просто задается число для записи в регистр.


А какие вообще прерывания использует ОС и зачем ? Помимо системного тика. Зачем ей прерывания приоритетом выше чем configMAX_SYSCALL_INTERRUPT_PRIORITY 0x60 (т.е. 6) , и почему это значение разрешается устанавливать самому ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 28 2015, 15:59
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



С приоритетом KERNEL_INTERRUPT_PRIORITY работают все прерывания ОС: SysTick, PendSV и SVCall.
Уровнем MAX_SYSCALL_INTERRUPT_PRIORITY задается максимальный приоритет, на котором может быть осуществлен системный вызов. Понятно, что в системе могут быть прерывания с более высоким приоритетом, которые не используют сервисы ОС. Для них и предусмотрено конфигурирование.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 28 2015, 17:13
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(aaarrr @ Feb 28 2015, 18:59) *
С приоритетом KERNEL_INTERRUPT_PRIORITY работают все прерывания ОС: SysTick, PendSV и SVCall.


SysTick, PendSV в SCB_SHPR ОС устанавливает самые низкие, 0xF0 . Приоритет SVCall самый высокий 0 , и я не вижу места, где бы он устанавливался.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 28 2015, 17:54
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Feb 28 2015, 20:13) *
Приоритет SVCall самый высокий 0 , и я не вижу места, где бы он устанавливался.

SVCall действительно не устанавливается, но он и используется однократно, так что все равно.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 28 2015, 21:32
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Поэкспериментировал ещё :

Оказывается, если заменить выдачу из прерывания эвента на симафор, то всё работает. Причём дело даже не в выдаче эвента из прерывания, а просто в том, что использование функции ожидания эвента каким-то неудачным образом накладывается на момент прерывания, и вот при этом происходит Bus Fault . Что-то не так именно с эвентами !


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 28 2015, 22:22
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Сломается точно так же и с семафорами в конце концов. Смысл экспериментов в чем?

Ключи все у Вас в руках:
1. Имеем Precise data bus error
2. Есть адрес инструкции, его вызвавшей
3. Известны ошибочные адреса (BFAR), по которым было обращение
Порой достаточно даже одного п.3: по характеру данных можно установить виновника.

Попробуйте своим прерываниям выставить минимальный приоритет (0xF0), посмотрите, будут ли воспроизводится проблемы.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 1 2015, 04:47
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Проблема решилась.
После перехода с версии FreeRTOS 8.0.0 на 8.2.0 её не стало.
Выходит , что 8.0.0 была с глюком.
В общей сложности потратил на ковыряние недели 2 чистого времени. Причём начал тратить ещё тогда, когда версия 8.2.0 ещё и не вышла.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 1 2015, 11:57
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MiklPolikov @ Mar 1 2015, 07:47) *
После перехода с версии FreeRTOS 8.0.0 на 8.2.0 её не стало.
Выходит , что 8.0.0 была с глюком.

Из первого, увы, никак не следует второе. В history ничего похожего нет.
Go to the top of the page
 
+Quote Post
kan35
сообщение Apr 8 2015, 17:30
Сообщение #26


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



у меня аналогичное случалось при банальном переполнении стека, по умолчанию в кейле, например не достаточно для такого примера
Go to the top of the page
 
+Quote Post

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

 


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


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