Jump to content

    

зацикливается freertos

Пробую freertos в действии. Простейшая задача - прерывание таймера (10 кГц) асинхронно периодически толкает процесс. stm32f205.

от 0.1 до 2-3 секунд работает, далее зацикливается в недрах RTOS на функции vListInsert (которой передается управления при вызове ulTaskNotifyTake), на этой строчке:

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. */

 

было подозрение на порчу памяти, но после перемещения памяти rtos в другие адреса эффект не изменился.

Не пойму, что за чудеса такие. Переполнение буферов? race condition? Копать глубже исходники rtos?

 

Функция ожидания, вызываемая процессом в цикле:

void wait_tick() {
  rmotion_go=2;// включение долбилки из ISR
wt=1;// для отслеживания входа в notifytake. при зацикливании равен единице.
  int id=ulTaskNotifyTake( pdTRUE, 2 );
wt=0;
  }

 

 

ISR (10 кГц):

  if (rmotion_go==2) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(Motion_task_handle, &xHigherPriorityTaskWoken );
//    xTaskNotifyFromISR( Motion_task_handle, 2, eNoAction/*eSetValueWithoutOverwrite*/, &xHigherPriorityTaskWoken );
//    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );// need realtime process
    }

соответственно, ISR долбит notify постоянно после того как процесс включит долбёжку (т.е. долбёжка не останавливается). Приоритет ISR таймера 7, приоритет супервизора 15 (судя по конфигу).

Замена vTaskNotifyGiveFromISR на xTaskNotifyFromISR с опцией eSetValueWithoutOverwrite ничего не меняет.

 

 

 

 

call stack:

vListInsert
prvAddCurrentTaskToDelayedList
ulTaskNotifyTake
wait_tick

 

Конфиг:

FreeRTOS Kernel V10.0.1

#define configUSE_PREEMPTION		1
#define configUSE_IDLE_HOOK			0
#define configUSE_TICK_HOOK			0
#define configCPU_CLOCK_HZ			( ( unsigned long ) 120000000 )	
#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES		( 5 )
#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 512 )
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 32 * 1024 ) )
#define configMAX_TASK_NAME_LEN		( 16 )
#define configUSE_TRACE_FACILITY	1
#define configUSE_16_BIT_TICKS		0
#define configIDLE_SHOULD_YIELD		1

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 		0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet		1
#define INCLUDE_uxTaskPriorityGet		1
#define INCLUDE_vTaskDelete				1
#define INCLUDE_vTaskCleanUpResources	0
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay				1
#define INCLUDE_xTaskGetCurrentTaskHandle 1

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 		255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY	15


#define xPortSysTickHandler SysTick_Handler
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler

Share this post


Link to post
Share on other sites
Пробую freertos в действии...
А с прерываниями в freertos на кортексе точно у вас всё в порядке?

 

В двух словах...

Для Cortex-M3-M4 в фрииртос есть засада: в конфиге указывается максимальный приоритет, в обработчике которого будут вызываться API фриртоса.

Вроде как #define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */

Т.е. у вас в конфиге указанно, что приоритет прерывания, в котором будут вызываться API не должен быть выше 11. У вас приоритет ISR таймера 7. Либо в конфиге укажите configMAX_SYSCALL_INTERRUPT_PRIORITY больше 7 (или "больше либо равно 7"), либо понижайте ISR таймера до 11.... Более точно про приоритеты сказать не могу... не помню уже... гуглите, .... тут поднималась эта тема и там расписано с точностью до запятой, что да как.

 

 

ps Может у вас не в этом проблема, но описанное поведение/зависание freertos именно такое, когда в прерывании выше configMAX_SYSCALL_INTERRUPT_PRIORITY дергают API.... ртос работает... и нормально работают все прерывания, но рано или позно ртос где-то в недрах зависает.

 

pps Это вызов АПИ с нарушением приоритета положит ось не всегда. Может раз 100-10000 нормально сработает, а потом ось ляжет. Как-то это асертом ловилось. Если не ошибаюсь в конфиге нужно ассерт определить. Он в целом тормозит ОС, но после того, как проверите правильность прерываний его можно/нужно отключить закоментировать. Вроде с ассертом при первом вызове из "неправильного" прерывания апи ось сразу встанет. И вроде это так делается

/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY    15

#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;; ); }

Share this post


Link to post
Share on other sites

- проверить что CPU реально работает на 120 МГц

- уменьшить частоту прерываний таймера (тот что 10000) до 100 Гц и проверить что это так.

- вместо кода во все задачи поставить "пустышки", и убедиться что планировщик переключает задачи.

(и вообще, что управление передается планировщику, есть прерывания тиков в #define xPortSysTickHandler SysTick_Handler ).

- далее - последовательно увеличивать частоту таймера для ISR до 10000 и подключать свой код.

- размер стека(ов) я бы увеличил. В конфиге есть configCHECK_FOR_STACK_OVERFLOW для его контроля.

может проблема и не так глубоко.

 

 

Share this post


Link to post
Share on other sites

Вы уверены что вызывать vTaskNotifyGiveFromISR 10000 раз в секунду это правильный подход?

Может вам стоит пересмотреть логику работы вашей программы.

Share this post


Link to post
Share on other sites

Про допустимый уровень приоритета для xxxFromISR выше уже написали. Поскольку IDLE_SHOULD_YIELD, вероятность прерывания инициированной IdleTask модификации списка задач другой, конкурирующей, модификацией, инициированной обработчиком прерывания, достаточно высока. Похоже, иногда это происходит в ломающем логику модификации списка месте. )

 

А так, пропускную способность 10к событий/с эта структура программы обеспечит с запасом. Только, присоединюсь к предыдущему оратору - зачем? )

Share this post


Link to post
Share on other sites

Да, слона то я и не приметил... Не думал что максимальный приоритет вызовов ограничен. Спасибо :) Похоже действительно switch_context прерывался, и я давал Notify в это время.

 

По поводу 10 кГц - это во-первых испытания на пригодность работы в жестком реалтайме, во-вторых задачи бывают разыне и иногда требуется большую и сложную state машину крутить в жестком реалтайме. Код существенно нагляднее получается когда написан в виде процесса, а не обработчика прерывания с кучей ветвей state машины.

Как альтернативу я как-то делал микро-запоминалку-востанавливалку контекста/стека в конкретном ISR для таких целей (т.е. в обработчике ISR я могу вызвать функцию "ждать следующего ISR", которое сохранит контекст и выйдет из прерывания, а следующее прерывание продолжит исполненеия обработчика с этого места), но это не практично т.к. контекст для экономии ресурсов обычно сохраняется-восстанавливается с ограничениями и другим людям в таких вещах зачастую сложно разобраться.

Share this post


Link to post
Share on other sites

Ну, мы занимаемся (одним конкретным из множества разнообразных видов) "жестким реалтаймом". ) Так для нас "жесткий реалтайм" - это когда еще при проектировании определенные гарантированные запасы времени на решение задач заложены. Если с самого начала ходить по пути "на весь цикл работы системы отводится всего около 10 тыс тактов машины" можно попасть в... неудобное положение.

 

"Для оценочного тестирования задействованных механизмов ОС" - я бы еще понял. )

Share this post


Link to post
Share on other sites
на весь цикл работы системы отводится всего около 10 тыс тактов машины" можно попасть в... неудобное положение.

Это я прекрасно понимаю, но в данной задаче таких проблем нет, и интересно посмотреть как поведет себя RTOS при таких нагрузках. Знать и правильно использовать пределы возможностей RTOS полезно.

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

Share this post


Link to post
Share on other sites

А. Ну, то есть, все-таки для оценки механизмов сигнализации/переключения. Кстати, этот джиттер, в абсолютных микро/наносекундах и есть ценный результат - он показывает границы неопределенности во времени, затрачиваемом на выполнение всех этих телодвижений ОС. ) По хорошему, к нему еще нужно среднее и максимальное время, затраченное на переключение. Методом подбора "ломающей систему частоты" это все равно неудобно делать )

Share this post


Link to post
Share on other sites
По поводу 10 кГц - это во-первых испытания на пригодность работы в жестком реалтайме,
Для реалтайма такой подоход не годится. Надо это делать подобные вещи мимо ОС. Через DMA, двойные буферы и прочее. Чтобы джиттер переключения контекста не оказывал никакого влияния.

Share this post


Link to post
Share on other sites
Для реалтайма такой подоход не годится. Надо это делать подобные вещи мимо ОС. Через DMA, двойные буферы и прочее. Чтобы джиттер переключения контекста не оказывал никакого влияния.

Для Cortex-M с тактовой >=100МГц переключение контекста RTOS с частотой 10кГц не должно быть проблемой. Загрузка CPU таким переключением должна быть не более пары процентов.

Но конечно лучше использовать частоты переключения как можно ниже.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now