ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 марта
657725
BaRaGoZ (03.03.2016 20:44, просмотров: 2032)
Пишу на STM32 под freeRTOS. Наткнулся на проблему с критическими секциями. Появилась задачка маршрутизации для радиомодуля, имеются датчики, мы их обрабатываем, далее(при определенных условиях) 1)формируем сообщение и добавляем его в очередь, 2)из этой очереди забираем сообщения и транслируем их в сеть. Также есть входящие сообщения, который мы либо обрабатываем, либо 3)ретранслируем - путем добавления в туже очередь. Казалось бы, все довольно просто с точки зрения потоков: xTaskCreate (GetRFRX, (const char * const)"Прием", configMINIMAL_STACK_SIZE * 3, (void*)this, tskIDLE_PRIORITY+2, &(xTaskGetRF)); //поток приема в эфире xTaskCreate (GetQueueItem, (const char * const)"Очередь", configMINIMAL_STACK_SIZE * 3, (void*)this, tskIDLE_PRIORITY+1, &(xTaskQueue));//поток обслуживания очереди xTaskCreate (HardwareTIM3, (const char * const)"Датчик", configMINIMAL_STACK_SIZE * 3, (void*)this, tskIDLE_PRIORITY+0, &(UsbTaskHandle)); //обработка датчиков Сразу скажу, что стек подбирал эмпирически, более того, кучу проверяю везде где можно. В функции переполнения не вылетает. Приоритеты ставил разные - от этого меняется лишь ситуация с deadlock`ми. Начал синхронизировать все "расшаренные" ресурсы, хотя их немного, но система периодически стала вылетать: 1) HardFault - все на память пока свалил 2) В дедлоки (я так думаю, дабы все вроде как работает только Idle после останова, но все же работает) 3) В текстах самой freeRTOS: /* *** NOTE *********************************************************** If you find your application is crashing here then likely causes are listed below. In addition see http://www.freertos.org/FAQHelp.html for more tips, and ensure configASSERT() is defined! http://www.freerto …0110.html#configASSERT 1) Stack overflow - see http://www.freerto …overflow-checking.html 2) Incorrect interrupt priority assignment, especially on Cortex-M parts where numerically high priority values denote low actual interrupt priorities, which can seem counter intuitive. See http://www.freerto …RTOS-Cortex-M3-M4.html and the definition of configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html 3) Calling an API function from within a critical section or when the scheduler is suspended, or calling an API function that does not end in "FromISR" from an interrupt. 4) Using a queue or semaphore before it has been initialised or before the scheduler has been started (are interrupts firing before vTaskStartScheduler() has been called?). **********************************************************************/ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ { __asm("nop"); /* There is nothing to do here, just iterating to the wanted insertion position. */ } Вываливается из мест , где идет какое либо обращение к объектам синхронизации, но чаще всего к очереди: xQueueReceive( A->RecQHandle, &w, portMAX_DELAY ); Причем частенько , сама RTOS часто в этих случаях(при работе с объектами синхр-ии) использует taskENTER_CRITICAL(),taskEXIT_CRITICAL() Первые две ошибки думаю решаемы, начал с третьей, дабы для меня она самая неясная, начал проверять работу критических секций, как мне показалось, что они не работают, написал простое приложение, которое запускает 2 потока для проверки критической секциии, и обалдел... : //создание 2х потоков xTaskCreate (tLED1, (const char * const)"Прием1", configMINIMAL_STACK_SIZE , NULL, tskIDLE_PRIORITY+0,0); xTaskCreate (tLED2, (const char * const)"Прием2", configMINIMAL_STACK_SIZE , NULL, tskIDLE_PRIORITY+0, 0); .............................. static void tLED1(void *pvParameter) { for(;;){ // taskENTER_CRITICAL(); vPortEnterCritical(); // Tooggllee(LED4,4000000000); qwassss = 0; for(int i =1;i<=1000000;i++){ qwassss= qwassss+1;// qwas = i*i*i*i*i*i/qwas/qwas/qwas; } Tooggllee(LED4,1);//мигнуть с задержкой *задержка циклом, без HAL_Delay или vTaskDelay // taskEXIT_CRITICAL(); vPortExitCritical(); taskYIELD(); } } static void tLED2(void *pvParameter) { for(;;){ //Tooggllee(LED4,5000); vPortEnterCritical(); for(int i =1;i<=100;i++){ qwassss= qwassss-1;// qwas = i*i*i*i*i*i/qwas/qwas/qwas; } Tooggllee(LED4,1); //мигнуть с задержкой *задержка циклом, без HAL_Delay или vTaskDelay vPortExitCritical(); taskYIELD(); } } В общем смысл проверки какой - есть 2 потока, один в цикле увеличивает переменную от 1 до 1000000, другой уменьшает ее в цикле на 100. если мы зашли в КС первого потока, то второй поток блокирован, и не уменьшит ее, перед выходом проверяем переменную и должны увидеть 1000000. Результаты мне вообще непонятны, если приоритет у потоков 0, то КС что есть, что нет ее. Если , например приоритеты 2,3,4 и до максимального, то все ок. Если же один более приоритетный поток vLED2(приоритет к примеру 3), то он спокойно себе прерывает поток vLED1(приоритет 2), который в данный момент считает переменную до 1000000, находясь в КС Про КС вроде помнил все, прочитал про КС в фриРТОСЕ, где черным по белому пишут, что до выхода из КС не переключаются контексты задач. Я вот думаю что то тут простое, что я не дочитал или пропустил, ведь если не работают КС, то у самой же РТОС будут проблемы, дабы она везде ими "засвечена". Подскажите, в чем может быть проблема? Заранее благодарен!