FreeRTOS: как получить информацию о загрузке процессора
Добавил(а) microsin
У FreeRTOS есть опционально активируемая возможность собирать информацию по затрачиваемому процессорному времени для каждой задачи. API-функция vTaskGetRunTimeStats() может представить эту информацию в виде текстовой таблицы.
Функция напечатает в консоль информацию по потокам в виде таблицы.
Чтобы эта функция была доступна, должны быть определены в 1 макросы конфигурации configGENERATE_RUN_TIME_STATS, configUSE_STATS_FORMATTING_FUNCTIONS и configSUPPORT_DYNAMIC_ALLOCATION (в файле FreeRTOSConfig.h).
Также приложение должно предоставить определения для макросов portCONFIGURE_TIMER_FOR_RUN_TIME_STATS (чтобы сконфигурировать периферийное устройство таймера/счетчика, используемого для отсчета реального времени) и portGET_RUN_TIME_COUNTER_VALUE (для возврата текущего значения этого счетчика). Этот счетчик должен инкрементироваться как минимум в 10 раз за 1 инкремент тика FreeRTOS.
Замечание: эта функция запретит прерывания на время своего выполнения. Поэтому она не предназначена для использования в релизе приложения, и её следует использовать однократно (например для команды в консоли или по нажатию кнопки), и только в целях отладки.
Функция vTaskGetRunTimeStats() вызовет uxTaskGetSystemState(), затем отформатирует сырые данные, которые сгенерировала uxTaskGetSystemState() в удобочитаемую для человека таблицу в виде текста ASCII. В этой таблице будет показано количество времени, которое каждая задача проводит в состоянии Running (т. е. сколько времени CPU каждая задача потребляет). Данные представлены как в абсолютном, так и в процентном выражении. Разрешающая способность в абсолютных значениях зависит от частоты сбора статистики времени выполнения, которую предоставило приложение (т. е. от частоты инкрементирования счетчика, сконфигурированного в portCONFIGURE_TIMER_FOR_RUN_TIME_STATS).
Функция vTaskGetRunTimeStats() эта просто утилита, предоставленная только для удобства. Она не считается частью ядра FreeRTOS. См. также описание функции vTaskList(), которая генерирует информацию о состоянии каждой задачи.
Параметр:
pcWriteBuffer Указатель на текстовый буфер, куда будет записана информация о статистике времени выполнения потоков. Подразумевается, что этот буфер достаточно большой, чтобы содержать сгенерированный отчет. Должно быть достаточным примерно 40 байт на одну задачу.
Информация выводится в 3 столбца. Первый столбец это имя задачи. Второй столбец показывает абсолютное время, которое использовала задача. Это условное "время", которое каждая задача потратила на обработку задачи (т. е. время, в течение которого задача находилась в состоянии Running). Единицы базового времени выбирает пользователь (по умолчанию длительность тика составляет 1 мс.), в зависимости от требований приложения. Третий столбец показывает статистику загрузки в более удобной и привычной форме - проценты от общего времени системы, которое было использовано каждой задачей.
[Настройка и использование]
Нужно в проекте определить 3 макроса, обычно это делается в файле FreeRTOSConfig.h.
1. configGENERATE_RUN_TIME_STATS
Сбор статистики по использованию процессорного времени разрешается, если этот макрос определен как 1. Когда это определение сделано, необходимо определить еще 2 макроса, чтобы компиляция прошла успешно.
2. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
Для сбора статистики времени выполнения нужна база времени с более точным разрешением, чем прерывание тика. Иначе статистика может быть слишком неточной и в итоге бесполезной. Это реализуется настройкой отдельного таймера с прерыванием в несколько раз чаще, чем прерывание тика - рекомендуется частоту прерываний сделать в 10 или даже в 100 раз чаще, чем прерывание тика. Чем выше будет частота прерываний таймера статистики, тем точнее будет эта статистика. Однако слишком часто частоту прерываний делать не рекомендуется, потому что есть риск переполнения счетчиков статистики, и слишком нерационально будет расходоваться время CPU.
Если определен в 1 макрос configGENERATE_RUN_TIME_STATS, то ядро FreeRTOS будет автоматически вызывать portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() при запуске планировщика (т. е. внутри API-функции vTaskStartScheduler()). Разработчику приложения необходимо использовать макрос portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(), где должен быть соответствующий код настройки базы времени статистики, примеры см. далее.
3. portGET_RUN_TIME_COUNTER_VALUE()
Этот макрос просто должен возвратить текущее "время", как это было сконфигурировано в portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(), см. примеры ниже.
Для получения захваченной статистики используется API-функция vTaskGetRunTimeStats().
4. В каком-нибудь модуле необходимо определить переменную ulHighFrequencyTimerTicks:
volatileunsignedlong ulHighFrequencyTimerTicks;
Чтобы устранить ошибку ассемблера, extern-объявление этой переменной в файле должно быть заключено в оператор препроцессора:
В качестве примера см. демо-приложения LM3Sxxxx Eclipse [3] и LPC17xx LPCXpresso [4], где сконфигурирована генерация статистики времени выполнения задач.
В демо-приложении LM3Sxxxx Eclipse уже настроен тестовый таймер, прерывания которого срабатывают с частотой 20 кГц. Обработчик прерывания просто инкрементирует переменную ulHighFrequencyTimerTicks. По этой причине portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() просто устанавливает эту переменную в 0, и portGET_RUN_TIME_COUNTER_VALUE() возвращает это значение. Для реализации этого функционала в файл FreeRTOSConfig.h нужно добавить несколько строчек:
В демо-приложении LPC17xx не настроен соответствующий таймер, поэтому в portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() был написан код, инициализирующий таймер 0 для генерации базы времени статистики. Макрос portGET_RUN_TIME_COUNTER_VALUE() просто возвращает текущее значение счетчика таймера 0.
Boffalo SDK позволяет использовать FreeRTOS для чипов TG7100C (аналог BL602), BL602, BL604, BL606P, BL616, BL618, BL702, BL706. Как запустить отображение статистики по потокам:
1. В любом модуле приложения (например в main.c) добавьте глобальную переменную для счетчика реального времени:
Этот способ сбора статистики потребляет довольно мало процессорного времени - приблизительно 0.3% (процессор STM32F429, конфигурация проекта Release, тактовая частота ядра 168 МГц, время тика 1 мс, частота срабатывания таймера статистики 44.1 кГц).
[Оценка свободного времени процессора]
Если нужно только узнать, насколько загружен CPU всеми задачами, то есть еще один более простой способ, опубликованный в статье [2]. Он менее ресурсоемкий, не требует настройки дополнительного таймера и позволяет получить только информацию о свободном текущем свободном времени CPU (информация о потоках недоступна). Метод определение загруженности процессора основан на механизме CPU idle hook API FreeRTOS, реализованном в функции vApplicationIdleHook. Эта функция вызывается из бесконечного цикла потока IDLE, у которого самый низкий приоритет. Чтобы была доступна функция vApplicationIdleHook нужно определить в 1 макрос configUSE_IDLE_HOOK.
[Ссылки]
1. Run Time Statistics site:freertos.org. 2. FreeRTOS определяем среднюю загрузку ядра микропроцессора (CPU utilization) site:easyelectronics.ru. 3. FreeRTOS Stellaris Web Server Demo site:freertos.org. 4. NXP LPC1766 ARM Cortex-M3 demo site:freertos.org. 5. FreeRTOS vTaskList.