From 3eaf1ef3c3407a72460fe99f71a33d89c07ca490 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Mon, 17 Aug 2015 16:29:44 +0200 Subject: [PATCH] LP-96 - Implement CPU idle counters and calibration functions --- flight/modules/System/systemmod.c | 7 ++- flight/pios/common/pios_task_monitor.c | 67 ++++++++++++++-------- flight/pios/inc/pios_task_monitor.h | 35 +++++++++-- shared/uavobjectdefinition/systemstats.xml | 2 + 4 files changed, 79 insertions(+), 32 deletions(-) diff --git a/flight/modules/System/systemmod.c b/flight/modules/System/systemmod.c index 8c94ec1b1..a4706235f 100644 --- a/flight/modules/System/systemmod.c +++ b/flight/modules/System/systemmod.c @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef PIOS_INCLUDE_INSTRUMENTATION #include @@ -528,7 +529,6 @@ static uint16_t GetFreeIrqStackSize(void) static void updateStats() { SystemStatsData stats; - // Get stats and update SystemStatsGet(&stats); stats.FlightTime = xTaskGetTickCount() * portTICK_RATE_MS; @@ -558,7 +558,9 @@ static void updateStats() stats.UsrSlotsActive = fsStats.num_active_slots; } #endif - stats.CPULoad = 100 - PIOS_TASK_MONITOR_GetIdlePercentage(); + stats.CPUIdleTicks = PIOS_TASK_MONITOR_GetIdleTicksCount(); + stats.CPUZeroLoadTicks = PIOS_TASK_MONITOR_GetZeroLoadTicksCount(); + stats.CPULoad = 100 - (uint8_t)((100 * stats.CPUIdleTicks) / stats.CPUZeroLoadTicks); #if defined(PIOS_INCLUDE_ADC) && defined(PIOS_ADC_USE_TEMP_SENSOR) float temp_voltage = PIOS_ADC_PinGetVolt(PIOS_ADC_TEMPERATURE_PIN); @@ -642,6 +644,7 @@ static void updateSystemAlarms() */ void vApplicationIdleHook(void) { + PIOS_TASK_MONITOR_IdleHook(); NotificationOnboardLedsRun(); #ifdef PIOS_INCLUDE_WS2811 LedNotificationExtLedsRun(); diff --git a/flight/pios/common/pios_task_monitor.c b/flight/pios/common/pios_task_monitor.c index 958a744a6..c6616b503 100644 --- a/flight/pios/common/pios_task_monitor.c +++ b/flight/pios/common/pios_task_monitor.c @@ -1,11 +1,12 @@ /** ****************************************************************************** - * @addtogroup OpenPilotSystem OpenPilot System + * @addtogroup LibrePilotSystem LibrePilot System * @{ - * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @addtogroup LibrePilotLibraries LibrePilot System Libraries * @{ - * @file pios_task_monitor.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @file pios_task_monitor.c + * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2015. * @brief Task monitoring functions * @see The GNU Public License (GPL) Version 3 * @@ -36,6 +37,9 @@ static uint32_t mLastMonitorTime; static uint32_t mLastIdleMonitorTime; static uint16_t mMaxTasks; +volatile uint32_t idleCounter; +uint32_t zeroLoadIdleCounterPerSec = UINT32_MAX; +volatile bool idleCounterClear; /** * Initialize the Task Monitor */ @@ -149,31 +153,44 @@ void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, void *c xSemaphoreGiveRecursive(mLock); } + uint8_t PIOS_TASK_MONITOR_GetIdlePercentage() { -#if defined(ARCH_POSIX) || defined(ARCH_WIN32) - return 50; + uint32_t ticks = PIOS_TASK_MONITOR_GetIdleTicksCount(); -#elif (configGENERATE_RUN_TIME_STATS == 1) - xSemaphoreTakeRecursive(mLock, portMAX_DELAY); - - uint32_t currentTime = portGET_RUN_TIME_COUNTER_VALUE(); - - /* avoid divide-by-zero if the interval is too small */ - uint32_t deltaTime = ((currentTime - mLastIdleMonitorTime) / 100) ? : 1; - mLastIdleMonitorTime = currentTime; - uint8_t running_time_percentage = 0; - - /* Generate idle time percentage stats */ - running_time_percentage = uxTaskGetRunTime(xTaskGetIdleTaskHandle()) / deltaTime; - xSemaphoreGiveRecursive(mLock); - return running_time_percentage; - -#else - return 0; - -#endif + return (uint8_t)((100 * ticks) / zeroLoadIdleCounterPerSec); } +uint32_t PIOS_TASK_MONITOR_GetIdleTicksCount() +{ + static portTickType lastTickCount = 0; + uint32_t ticks = 0; + portTickType now = xTaskGetTickCount(); + + if (idleCounterClear) { + idleCounter = 0; + } + + if (now > lastTickCount) { + uint32_t dT = (xTaskGetTickCount() - lastTickCount) * portTICK_RATE_MS; // in ms + ticks = (1000 * idleCounter) / dT; + } // else: TickCount has wrapped, do not calc now + lastTickCount = now; + idleCounterClear = true; + return ticks; +} + +void PIOS_TASK_MONITOR_CalibrateIdleCounter() +{ + idleCounterClear = true; + PIOS_TASK_MONITOR_GetIdleTicksCount(); + vTaskDelay(20); + zeroLoadIdleCounterPerSec = PIOS_TASK_MONITOR_GetIdleTicksCount(); +} + +uint32_t PIOS_TASK_MONITOR_GetZeroLoadTicksCount() +{ + return zeroLoadIdleCounterPerSec; +} #endif // PIOS_INCLUDE_TASK_MONITOR diff --git a/flight/pios/inc/pios_task_monitor.h b/flight/pios/inc/pios_task_monitor.h index 42edc104f..17306ba5f 100644 --- a/flight/pios/inc/pios_task_monitor.h +++ b/flight/pios/inc/pios_task_monitor.h @@ -1,15 +1,17 @@ /** ****************************************************************************** - * @addtogroup OpenPilotSystem OpenPilot System + * @addtogroup LibrePilotSystem LibrePilot System * @{ - * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @addtogroup LibrePilotLibraries LibrePilot System Libraries * @{ - * @file task_monitor.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013. + * @file pios_task_monitor.h + * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015. + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2015. * @brief Task monitoring functions * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ + /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +31,8 @@ #define PIOS_TASK_MONITOR_H #include - +extern volatile uint32_t idleCounter; +extern volatile bool idleCounterClear; /** * Initializes the Task Monitor. * @@ -109,4 +112,26 @@ extern void PIOS_TASK_MONITOR_ForEachTask(TaskMonitorTaskInfoCallback callback, */ extern uint8_t PIOS_TASK_MONITOR_GetIdlePercentage(); +static inline void PIOS_TASK_MONITOR_IdleHook() +{ + if (!idleCounterClear) { + ++idleCounter; + } else { + idleCounter = 0; + idleCounterClear = false; + } +} + +/** + * Calibrate the idle counter. it should be run with a single task (caller) created + */ +extern void PIOS_TASK_MONITOR_CalibrateIdleCounter(); +/** + * return the number of idle hook execution per second + * @return number of idle hook execution per second + */ +extern uint32_t PIOS_TASK_MONITOR_GetIdleTicksCount(); + +extern uint32_t PIOS_TASK_MONITOR_GetZeroLoadTicksCount(); + #endif // PIOS_TASK_MONITOR_H diff --git a/shared/uavobjectdefinition/systemstats.xml b/shared/uavobjectdefinition/systemstats.xml index 4de866eb2..8d4163a99 100644 --- a/shared/uavobjectdefinition/systemstats.xml +++ b/shared/uavobjectdefinition/systemstats.xml @@ -6,6 +6,8 @@ + +