Author: JF <jf@codingfield.com>
Reduce RAM memory usage by tuning the stack of the stasks and the heap allocated for FreeRTOS. Add Monitor to log the stack usage of each task.
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a30fb568115c74cda4f5796ec1fdf7dc86deafae..8b39d2b55e9260a486db71f6055d15ec1edbcda0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -442,6 +442,7 @@ libs/date/includes/date/ptz.h libs/date/includes/date/tz_private.h DisplayApp/LittleVgl.h SystemTask/SystemTask.h + SystemTask/SystemMonitor.h ) include_directories( diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 93289e1ae09b7a2004742cfd428fab43c4310c4c..a18a292763cf6c05df9475581e116a7fffe0bba1 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -63,7 +63,7 @@ #define configCPU_CLOCK_HZ ( SystemCoreClock ) #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES ( 3 ) #define configMINIMAL_STACK_SIZE ( 120 ) -#define configTOTAL_HEAP_SIZE ( 1024*20 ) +#define configTOTAL_HEAP_SIZE ( 1024*11 ) #define configMAX_TASK_NAME_LEN ( 4 ) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -85,7 +85,7 @@ #define configUSE_MALLOC_FAILED_HOOK 0 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 0 +#define configUSE_TRACE_FACILITY 1 #define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Co-routine definitions. */ @@ -96,7 +96,7 @@ /* Software timer definitions. */ #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY ( 0 ) #define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH ( 240 ) +#define configTIMER_TASK_STACK_DEPTH ( 200 ) /* Tickless Idle configuration. */ #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 diff --git a/src/Logging/NrfLogger.cpp b/src/Logging/NrfLogger.cpp index 1c47a10878fb009a36fae8cdc3c9fe7e47a8decb..7ccacc82deb513ad11c20537a614936c20f9d29b 100644 --- a/src/Logging/NrfLogger.cpp +++ b/src/Logging/NrfLogger.cpp @@ -13,7 +13,7 @@ APP_ERROR_CHECK(result); NRF_LOG_DEFAULT_BACKENDS_INIT(); - if (pdPASS != xTaskCreate(NrfLogger::Process, "LOGGER", 512, nullptr, 0, &m_logger_thread)) + if (pdPASS != xTaskCreate(NrfLogger::Process, "LOGGER", 200, this, 0, &m_logger_thread)) APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); } diff --git a/src/SystemTask/SystemMonitor.h b/src/SystemTask/SystemMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..50dd295a62698eff9058325448b5043e589e953d --- /dev/null +++ b/src/SystemTask/SystemMonitor.h @@ -0,0 +1,46 @@ +#pragma once +#include <FreeRTOS.h> +#include <task.h> +#include <nrf_log.h> + + +namespace Pinetime { + namespace System { + struct DummyMonitor {}; + struct FreeRtosMonitor {}; + + template<class T> + class SystemMonitor { + public: + SystemMonitor() = delete; + }; + + template<> + class SystemMonitor<DummyMonitor> { + public: + void Process() const {} + }; + + template<> + class SystemMonitor<FreeRtosMonitor> { + public: + void Process() const { + if(xTaskGetTickCount() - lastTick > 10000) { + NRF_LOG_INFO("---------------------------------------\nFee heap : %d", xPortGetFreeHeapSize()); + auto nb = uxTaskGetSystemState(tasksStatus, 10, NULL); + for (int i = 0; i < nb; i++) { + NRF_LOG_INFO("Task [%s] - %d", tasksStatus[i].pcTaskName, tasksStatus[i].usStackHighWaterMark); + if (tasksStatus[i].usStackHighWaterMark < 20) + NRF_LOG_INFO("WARNING!!! Task %s task is nearly full, only %dB available", tasksStatus[i].pcTaskName, + tasksStatus[i].usStackHighWaterMark * 4); + } + lastTick = xTaskGetTickCount(); + } + } + + private: + mutable TickType_t lastTick = 0; + mutable TaskStatus_t tasksStatus[10]; + }; + } +} \ No newline at end of file diff --git a/src/SystemTask/SystemTask.cpp b/src/SystemTask/SystemTask.cpp index 61b3c6383c9c905a0851c6dfe7a9e3b50a7a5aaa..1f01b1b5393e65560e6f91daacef007b2f04c45e 100644 --- a/src/SystemTask/SystemTask.cpp +++ b/src/SystemTask/SystemTask.cpp @@ -169,6 +169,8 @@ uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG); dateTimeController.UpdateTime(systick_counter); batteryController.Update(); + monitor.Process(); + if(!nrf_gpio_pin_read(pinButton)) watchdog.Kick(); } diff --git a/src/SystemTask/SystemTask.h b/src/SystemTask/SystemTask.h index ab5f7010ab75cd2596a0f57cedede4defc328c2b..e006058f451c676b00cd79e09979436e235ed08b 100644 --- a/src/SystemTask/SystemTask.h +++ b/src/SystemTask/SystemTask.h @@ -10,6 +10,7 @@ #include#include <drivers/Watchdog.h> #include <Components/Ble/NimbleController.h> #include <drivers/SpiNorFlash.h> +#include "SystemMonitor.h" namespace Pinetime { namespace System { @@ -72,6 +73,12 @@ TimerHandle_t idleTimer; bool doNotGoToSleep = false; void GoToRunning(); + +#if configUSE_TRACE_FACILITY == 1 + SystemMonitor<FreeRtosMonitor> monitor; +#else + SystemMonitor<DummyMonitor> monitor; +#endif }; } } \ No newline at end of file diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c index 8ee3475adffad8830f40ca7a927c110cf2264c0f..64196b3659477702d9e0dcd4daa2aa1847cfb6fb 100644 --- a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c +++ b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -37,7 +37,7 @@ * own event queue and should have highest priority. The task function is * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * since it has compatible prototype. */ - xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, + xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 100, NULL, configMAX_PRIORITIES - 1, &ll_task_h); #endif @@ -46,6 +46,6 @@ * Create task where NimBLE host will run. It is not strictly necessary to * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ - xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 400, + xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 200, NULL, tskIDLE_PRIORITY + 1, &host_task_h); }