You are here

Возможности трассировки приложений

Перевод может содержать ошибки. Читайте первоисточник: Trace Hook Macros

Назад: [Более подробно...] Вверх: [Более подробно...] Вперёд: [Более подробно...]

 

Макросы отладочных ловушек

 

 

Описание

Макросы отладочных ловушек это очень мощная возможность собирать информацию о том, как ведёт себя встраиваемое приложение.

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

 

Примеры

Ниже приведены примеры некоторых вариантов использования этих макросов:

  • Установка цифрового выхода для индикации, какая задача сейчас запущена. Это позволяет использовать логический анализатор для просмотра и записи последовательности выполнения задач и их синхронизации.
  • Аналогично - установка напряжения на аналоговом выходе, которое показывает, какая из задач сейчас запущена. Это позволяет использовать аналоговый осцилллограф для просмотра и записи последовательности выполнения задач и их синхронизации.
  • Журналирование последовательности запуска, синхронизации задач, событий ядра ОС и вызовов функций API для последующего вдумчивого анализа.
  • Интеграция событий ядра ОС с отладчиками сторонних производителей.

 

Пример 1

Функционал метки задачи FreeRTOS предоставляет простой механизм для настройки журналирования через цифровые или аналоговые выходы. Например, значение метки может быть установлено на напряжение, которое будет уникальным для каждой задачи. Тогда макрос traceSWITCHED_IN() может быть определён так, чтобы просто выводить на аналоговый выход значение метки задачи, на которую было выполнено переключение. В исходных кодах это будет выглядеть так:

/*----------------------------------------------------------------------------*/
/* В первой задаче устанавливаем значение метки в 1. */
void vTask1( void *pvParameters )
{
    /* Эта задача будет представлена напряжением, соответствующим значению 1. */
    vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );

    for( ;; )
    {
        /* Здесь должен быть размещён код самой задачи. */
    }
}

/*----------------------------------------------------------------------------*/
/* Во второй задаче устанавливаем значение метки в 2. */
void vTask2( void *pvParameters )
{
    /* Эта задача будет представлена напряжением, соответствующим значению 2. */
    vTaskSetApplicationTaskTag( NULL, ( void * ) 2 );

    for( ;; )
    {
        /* Здесь должен быть размещён код самой задачи. */
    }
}

/*----------------------------------------------------------------------------*/
/* Определим макрос traceTASK_SWITCHED_IN() так, чтобы он вызывал функцию подачи
на аналоговый выход 0 напряжения, соответствущего значению метки задачи. */
#define traceTASK_SWITCHED_IN()         /
    vSetAnalogueOutput( 0, (int)pxCurrentTCB->pxTaskTag )

 

Пример 2

Журналирование вызовов функций API может использоваться для записи причин выполнения переключения контекста. Журналирование вызовов ядра ОС для записи последовательности, в которой запускаются задачи. Это можно реализовать так:

/*----------------------------------------------------------------------------*/
/* Макрос traceBLOCKING_ON_QUEUE_RECEIVE() это один из макросов, позволяющих
определить причину переключения контекста. */
#define traceBLOCKING_ON_QUEUE_RECEIVE(xQueue)  /
    ulSwitchReason = reasonBLOCKING_ON_QUEUE_READ;

/*----------------------------------------------------------------------------*/
/* Функция log_event() реализуется разработчиком приложения. В качестве
аргументов она получает собственно задачу, которая была заблокирована, и
причину, почему это произошло. */
#define traceTASK_SWITCHED_OUT()                /
    log_event( pxCurrentTCB, ulSwitchReason );

 

Описание макросов

Макросы, которые вызываются внутри обработчиков прерываний, особенно из прерывания тиков ОС, должны выполняться быстро и не использовать большого объёма ОЗУ в стеке. Установка значений переменных, запись в регистры трассировки или вывод в порты - это всё, что допустимо. А вызов, например, функции fprintf() с записью на медленный носитель работать не будет!

Макросы должны быть определены до включения в код файла FreeRTOS.h. Самое простое место для размещения макросов отладки - внизу файла FreeRTOSConfig.h, или в отдельном заголовочном файле, подключаемом внизу файла FreeRTOSConfig.h.

В таблице ниже описаны доступные макросы. Параметры макроса используются для указания того, какая задача, очередь, семафор или мьютекс были связаны с записываемым событием. Но на исходной странице список для версии где-то около 8.0.0, поэтому остальные взяты напрямую из FreeRTOS.h, и к ним пока нет пояснений.

Макросы трассировки ядра FreeRTOS

Макрос Описание
traceSTART() Используется для выполнения необходимой инициализации трассировки - например для открытия файла, в который будет осуществляться запись данных при трассировке.
traceEND() Используется для завершения трассировки - например для закрытия файла, в который велась запись данных при трассировке.
traceTASK_SWITCHED_IN() Вызывается после того, как будет выбрана задача для перехода в запущенное состояние. В момент вызова макроса глобальная переменная pxCurrentTCB содержит хэндл задачи, которая переходит в запущенное состояние.
traceINCREASE_TICK_COUNT( xTicksToJump ) Вызывается перед шагом счётчика тиков ОС после пробуждения из состояния простоя без тиков ОС. Вызывается из vTaskStepTick() в файле tasks.c, при условии, что configUSE_TICKLESS_IDLE не равен 0.
traceLOW_POWER_IDLE_BEGIN() Вызывается непосредственно перед тем, как перейти в состояние простоя без тиков ОС.
traceLOW_POWER_IDLE_END() Вызывается при возврате в задачу простоя после состояния простоя без тиков ОС.
traceTASK_SWITCHED_OUT() Вызывается перед выбором задачи для запуска. В момент вызова макроса глобальная переменная pxCurrentTCB содержит хэндл задачи (указатель на TaskControlBlock), которая выходит из запущенного состояния.
traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) Вызывается, когда задача пытается получить мьютекс, который уже взят задачей с более низким приоритетом. pxTCBOfMutexHolder указывает на TCB задачи, удерживающей мьютекс. uxInheritedPriority является приоритетом, который наследует держатель мьютекса (приоритет задачи, которая пытается получить мьютекс).
traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) Вызывается, когда задача освобождает мьютекс, в результате удержания которого она унаследовала приоритет задачи с более высоким приоритетом. pxTCBOfMutexHolder содержит указатель на TCB задачи, которая освобождает мьютекс. uxOriginalPriority это настроенный (базовый) приоритет задачи.
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) Сообщает, что текущая запущенная задача будет заблокирована, т.к. выполнила попытку чтения из пустой очереди или "взятия" пустого семафора/мьютекса. pxQueue указывает на очередь/семафор/мьютекс, откуда пытались прочитать. pxCurrentTCB указывает на задачу, из которой выполнялась попытка чтения.
traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) Сообщает, что текущая запущенная задача будет заблокирована, т.к. выполнила попытку чтения из пустой очереди или "взятия" пустого семафора/мьютекса. pxQueue указывает на очередь/семафор/мьютекс, откуда пытались прочитать. pxCurrentTCB указывает на задачу, из которой выполнялась попытка чтения.
traceBLOCKING_ON_QUEUE_SEND( pxQueue ) Сообщает, что текущая запущенная задача будет заблокирована, т.к. пыталась записать в заполненную очередь/семафор/мьютекс. pxQueue указывает на очередь/семафор/мьютекс, куда пытались записать. pxCurrentTCB указывает на задачу, которая пыталась записать.
Далее - макросы для вызовов API.
traceMOVED_TASK_TO_READY_STATE( pxTCB ) Вызывается когда задача переходит в состояние "готова".
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
traceQUEUE_CREATE( pxNewQueue ) Вызывается из xQueueCreate() или xQueueCreateStatic(), если очередь была успешно создана.
traceQUEUE_CREATE_FAILED() Вызывается из xQueueCreate() или xQueueCreateStatic(), если очередь не удалось создать из-за нехватки памяти кучи.
traceQUEUE_SEND( pxQueue ) Вызывается из xQueueSend(), xQueueSendToFront(), xQueueSendToBack(), а также из любой функции, "выдающей" семафор, если отправка в очередь была успешно выполнена.
traceQUEUE_SEND_FAILED( pxQueue ) Вызывается из xQueueSend(), xQueueSendToFront(), xQueueSendToBack(), а также из любой функции, "выдающей" семафор, если отправку в очередь выполнить не удалось, поскольку очередь полна (после любого указанного времени блокировки для ожидания).
traceQUEUE_RECEIVE( pxQueue ) Вызывается из xQueueReceive(), а также из любой функции, "берущей" семафор, если извлечение из очереди успешно выполнено.
traceQUEUE_RECEIVE_FAILED( pxQueue ) Вызывается из xQueueReceive(), а также из любой функции, "берущей" семафор, если извлечение из очереди выполнить не удалось, т.к. очередь пуста (после любого указанного времени блокировки для ожидания).
traceQUEUE_PEEK( pxQueue ) Вызывается из xQueuePeek().
traceQUEUE_PEEK_FAILED( pxQueue ) Вызывается из xQueuePeek().
traceQUEUE_PEEK_FROM_ISR( pxQueue ) Вызывается из xQueuePeekFromISR().
traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) Вызывается из xQueuePeekFromISR().
traceQUEUE_SEND_FROM_ISR( pxQueue ) Вызывается из xQueueSendFromISR(), когда отправка в очередь успешно выполнена.
traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) Вызывается из xQueueSendFromISR(), когда операцию отправки в очередь выполнить не удалось, т.к. очередь уже заполнена.
traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) Вызывается из xQueueReceiveFromISR(), когда операция извлечения из очереди успешно выполнена.
traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) Вызывается из xQueueReceiveFromISR(), когда операцию извлечения из очереди выполнить не удалось, т.к. очередь была пуста.
traceQUEUE_DELETE( pxQueue ) Вызывается из vQueueDelete().
traceCREATE_MUTEX( pxNewMutex ) Вызывается из xSemaphoreCreateMutex(), если мьютекс был успешно создан. (в исходниках параметр - pxNewQueue).
traceCREATE_MUTEX_FAILED() Вызывается из xSemaphoreCreateMutex(), если мьютекс не удалось создать из-за нехватки памяти кучи.
traceGIVE_MUTEX_RECURSIVE( pxMutex ) Вызывается из xSemaphoreGiveRecursive(), если мьютекс был успешно "выдан".
traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) Вызывается из xSemaphoreGiveRecursive(), если мьютекс не был выдан, т.к. выдающая задача не является владельцем мьютекса.
traceTAKE_MUTEX_RECURSIVE( pxMutex ) Вызывается из xQueueTakeMutexRecursive().
traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) Вызывается из xQueueTakeMutexRecursive().
traceCREATE_COUNTING_SEMAPHORE() Вызывается из xSemaphoreCreateCounting(), если семафор был успешно создан.
traceCREATE_COUNTING_SEMAPHORE_FAILED() Вызывается из xSemaphoreCreateCounting(), если семафор не удалось создать из-за нехватки памяти в куче.
traceTASK_CREATE( pxNewTCB ) Вызывается из xTaskCreate() или xTaskCreateStatic(), когда задача успешно создана.
traceTASK_CREATE_FAILED() Вызывается из xTaskCreate() или xTaskCreateStatic(), когда задачу создать не удалось из-за нехватки свободного места в куче.
traceTASK_DELETE( pxTaskToDelete ) Вызывается из vTaskDelete().
traceTASK_DELAY_UNTIL( x ) Вызывается из vTaskDelayUntil().
traceTASK_DELAY() Вызывается из vTaskDelay().
traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) Вызывается из vTaskPrioritySet().
traceTASK_SUSPEND( pxTaskToSuspend ) Вызывается из vTaskSuspend().
traceTASK_RESUME( pxTaskToResume ) Вызывается из vTaskResume().
traceTASK_RESUME_FROM_ISR( pxTaskToResume ) Вызывается из xTaskResumeFromISR().
traceTASK_INCREMENT_TICK( xTickCount ) Вызывается из обработчика прерывания тиков ОС, из функции xTaskIncrementTick() в файле tasks.c.
traceTIMER_CREATE( pxNewTimer) Вызывается из xTimerCreate(), если таймер был успешно создан.
traceTIMER_CREATE_FAILED() Вызывается из xTimerCreate(), если таймер не был создан из-за нехватки памяти в куче.
traceTIMER_COMMAND_SEND( pxTimer, xMessageID, xMessageValue, xReturn) Вызывается из любой функции API, которая отправляет команду задаче обслуживания таймеров, например, xTimerReset(), xTimerStop(), и т.д... xReturn (ранее - xStatus) примет значение pdFAIL, если команда не удастся отправить в очередь команд таймера.
traceTIMER_EXPIRED( pxTimer ) Вызывается, когда истёк период программного таймера, перед тем, как будет вызвана функция обратного вызова таймера.
traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) Вызывается из задачи обслуживания таймеров каждый раз, когда она принимает команду, перед тем, как команда будет выполнена.
Свежачок в API.
traceMALLOC( pvAddress, uiSize )
traceFREE( pvAddress, uiSize )
traceEVENT_GROUP_CREATE( xEventGroup )
traceEVENT_GROUP_CREATE_FAILED()
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor )
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor )
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear )
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet )
traceEVENT_GROUP_DELETE( xEventGroup )
tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret)
tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret)
traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName)
traceTASK_NOTIFY_TAKE_BLOCK()
traceTASK_NOTIFY_TAKE()
traceTASK_NOTIFY_WAIT_BLOCK()
traceTASK_NOTIFY_WAIT()
traceTASK_NOTIFY()
traceTASK_NOTIFY_FROM_ISR()
traceTASK_NOTIFY_GIVE_FROM_ISR()
traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )
traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer )
traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer )
traceSTREAM_BUFFER_DELETE( xStreamBuffer )
traceSTREAM_BUFFER_RESET( xStreamBuffer )
traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer )
traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent )
traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer )
traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent )
traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer )
traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength )
traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer )
traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength )

 

Hobby's category: