Integrate the new heap implementation from InfiniTime (https://github.com/InfiniTimeOrg/InfiniTime/pull/1709).
Since FreeRTOS.h, portmacro_cmsis.h and task.h are now built in C (by lv_mem.c), I had to change some includes and declarations to make them compatible with a C compiler. Integrating the new memory management from InfiniTime in InfiniSim is not easy because InfiniSim does not include the whole FreeRTOS. Which means that, for example, pvPortMalloc() and vPortFree() are not accessible from InfiniSim. As a first step, I provided custom implementations for pvPortMalloc(), vPortFree() which are based on ... malloc(). These function keep track of the memory that is currently allocated so that xPortGetFreeHeapSize(), xPortGetMinimumEverFreeHeapSize() return something. Not that this implementation do not keep track of all the memory allocations done in InfiniTime. It can only "see" those done via pvPortMalloc(). It means that the available memory displayed by InfiniSim will probably be very optimistic.
This commit is contained in:
parent
e416f2cf74
commit
8ae5ba7c0a
5 changed files with 87 additions and 31 deletions
23
main.cpp
23
main.cpp
|
@ -429,8 +429,7 @@ public:
|
||||||
motorController.Init();
|
motorController.Init();
|
||||||
settingsController.Init();
|
settingsController.Init();
|
||||||
|
|
||||||
lv_mem_monitor(&mem_mon);
|
printf("initial free_size = %u\n", xPortGetFreeHeapSize());
|
||||||
printf("initial free_size = %u\n", mem_mon.free_size);
|
|
||||||
|
|
||||||
// update time to current system time once on startup
|
// update time to current system time once on startup
|
||||||
dateTimeController.SetCurrentTime(std::chrono::system_clock::now());
|
dateTimeController.SetCurrentTime(std::chrono::system_clock::now());
|
||||||
|
@ -882,17 +881,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_memory_usage) {
|
if (print_memory_usage) {
|
||||||
lv_mem_monitor(&mem_mon);
|
auto currentFreeHeap = xPortGetFreeHeapSize();
|
||||||
if (mem_mon.free_size != mem_mon_last_free_size) {
|
auto minimumEverFreeHeap = xPortGetMinimumEverFreeHeapSize();
|
||||||
|
if (currentFreeHeap != lastFreeHeapSize) {
|
||||||
// 14KiB is the LVGL memory size used in InfiniTime
|
// 14KiB is the LVGL memory size used in InfiniTime
|
||||||
constexpr uint32_t pinetime_lvgl_memory = 14U*1024U;
|
constexpr uint32_t pinetime_heap_memory = configTOTAL_HEAP_SIZE;
|
||||||
uint32_t mem_used = LV_MEM_SIZE - mem_mon.free_size;
|
uint32_t mem_used = pinetime_heap_memory - currentFreeHeap;
|
||||||
// The "budget" value shows how much free lvgl memory the PineTime
|
// The "budget" value shows how much free lvgl memory the PineTime
|
||||||
// would have free and will go negative when more memory is used
|
// would have free and will go negative when more memory is used
|
||||||
// in the simulator than is available on the real hardware.
|
// in the simulator than is available on the real hardware.
|
||||||
int32_t budget = pinetime_lvgl_memory - mem_used;
|
int32_t budget = configTOTAL_HEAP_SIZE - mem_used;
|
||||||
printf("Mem: %5u used (change: %+5d, peak: %5u) %d budget left\n", mem_used, mem_mon_last_free_size - mem_mon.free_size, mem_mon.max_used, budget);
|
printf("Mem: %5u used (change: %+5d, peak: %5u) %d budget left\n", mem_used, lastFreeHeapSize - currentFreeHeap, minimumEverFreeHeap, budget);
|
||||||
mem_mon_last_free_size = mem_mon.free_size;
|
lastFreeHeapSize = currentFreeHeap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,7 +903,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_memory_usage = false;
|
bool print_memory_usage = false;
|
||||||
lv_mem_monitor_t mem_mon;
|
|
||||||
|
|
||||||
// variables to create and destroy an lvgl overlay to indicate a turned off screen
|
// variables to create and destroy an lvgl overlay to indicate a turned off screen
|
||||||
bool screen_off_created = false;
|
bool screen_off_created = false;
|
||||||
|
@ -947,11 +946,13 @@ private:
|
||||||
bool left_release_sent = true; // make sure to send one mouse button release event
|
bool left_release_sent = true; // make sure to send one mouse button release event
|
||||||
bool right_last_state = false; // varable used to send message only on changing state
|
bool right_last_state = false; // varable used to send message only on changing state
|
||||||
|
|
||||||
uint32_t mem_mon_last_free_size = LV_MEM_SIZE;
|
size_t lastFreeHeapSize = configTOTAL_HEAP_SIZE;
|
||||||
|
|
||||||
GifManager gif_manager;
|
GifManager gif_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int mallocFailedCount = 0;
|
||||||
|
int stackOverflowCount = 0;
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// parse arguments
|
// parse arguments
|
||||||
|
|
|
@ -1,3 +1,44 @@
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
void NVIC_SystemReset(void) {}
|
void NVIC_SystemReset(void) {}
|
||||||
|
|
||||||
|
void APP_ERROR_HANDLER(int err) {
|
||||||
|
fprintf(stderr, "APP_ERROR_HANDLER: %d", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::map<void *, size_t> allocatedMemory;
|
||||||
|
size_t currentFreeHeap = configTOTAL_HEAP_SIZE;
|
||||||
|
size_t minimumEverFreeHeap = configTOTAL_HEAP_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pvPortMalloc( size_t xWantedSize ) {
|
||||||
|
void* ptr = malloc(xWantedSize);
|
||||||
|
allocatedMemory[ptr] = xWantedSize;
|
||||||
|
|
||||||
|
size_t currentSize = 0;
|
||||||
|
std::for_each(allocatedMemory.begin(), allocatedMemory.end(), [¤tSize](const std::pair<void*, size_t>& item){
|
||||||
|
currentSize += item.second;
|
||||||
|
});
|
||||||
|
|
||||||
|
currentFreeHeap = configTOTAL_HEAP_SIZE - currentSize;
|
||||||
|
minimumEverFreeHeap = std::min(currentFreeHeap, minimumEverFreeHeap);
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
void vPortFree( void *pv ) {
|
||||||
|
allocatedMemory.erase(pv);
|
||||||
|
return free(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize(void) {
|
||||||
|
return currentFreeHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize(void) {
|
||||||
|
return minimumEverFreeHeap;
|
||||||
|
}
|
||||||
|
|
|
@ -59,21 +59,17 @@
|
||||||
#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
|
#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
|
||||||
#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
|
#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
|
||||||
#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
|
#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
|
||||||
#include <stdexcept>
|
|
||||||
#include <string> // std::to_string()
|
|
||||||
template<typename T>
|
|
||||||
void APP_ERROR_HANDLER(T err) {
|
|
||||||
throw std::runtime_error("APP_ERROR_HANDLER: " + std::to_string(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SCB_t {
|
void APP_ERROR_HANDLER(int err);
|
||||||
unsigned ICSR = 0;
|
|
||||||
};
|
typedef struct SCB_t {
|
||||||
|
unsigned ICSR;
|
||||||
|
} SCB_t;
|
||||||
static SCB_t SCB_member;
|
static SCB_t SCB_member;
|
||||||
static SCB_t *SCB = &SCB_member;
|
static SCB_t *SCB = &SCB_member;
|
||||||
|
|
||||||
//#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
|
//#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
|
||||||
constexpr unsigned SCB_ICSR_VECTACTIVE_Msk = 0x01;
|
const unsigned SCB_ICSR_VECTACTIVE_Msk = 0x01;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief System Reset
|
\brief System Reset
|
||||||
|
@ -82,4 +78,21 @@ constexpr unsigned SCB_ICSR_VECTACTIVE_Msk = 0x01;
|
||||||
// copied from nRF5_SDK_15.3.0_59ac345/components/toolchain/cmsis/include/core_cm4.h
|
// copied from nRF5_SDK_15.3.0_59ac345/components/toolchain/cmsis/include/core_cm4.h
|
||||||
void NVIC_SystemReset(void);
|
void NVIC_SystemReset(void);
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#define configTOTAL_HEAP_SIZE (1024 * 40)
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize(void);
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void *pvPortMalloc(size_t xWantedSize);
|
||||||
|
void vPortFree(void *pv);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INC_FREERTOS_H */
|
#endif /* INC_FREERTOS_H */
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#ifndef PORTMACRO_CMSIS_H
|
#ifndef PORTMACRO_CMSIS_H
|
||||||
#define PORTMACRO_CMSIS_H
|
#define PORTMACRO_CMSIS_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint32_t TickType_t;
|
typedef uint32_t TickType_t;
|
||||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
@ -41,8 +41,8 @@ typedef unsigned long UBaseType_t;
|
||||||
#define pdPASS pdTRUE
|
#define pdPASS pdTRUE
|
||||||
|
|
||||||
/* RTC register */
|
/* RTC register */
|
||||||
using NRF_RTC_Type = uint32_t;
|
typedef uint32_t NRF_RTC_Type;
|
||||||
constexpr NRF_RTC_Type portNRF_RTC_REG = 1;
|
const NRF_RTC_Type portNRF_RTC_REG = 1;
|
||||||
|
|
||||||
void portYIELD_FROM_ISR(BaseType_t);
|
void portYIELD_FROM_ISR(BaseType_t);
|
||||||
|
|
||||||
|
|
15
sim/task.h
15
sim/task.h
|
@ -32,7 +32,8 @@
|
||||||
|
|
||||||
#include "portmacro_cmsis.h"
|
#include "portmacro_cmsis.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
// copied from InfiniTime/src/FreeRTOSConfig.h
|
// copied from InfiniTime/src/FreeRTOSConfig.h
|
||||||
#define configTICK_RATE_HZ 1024
|
#define configTICK_RATE_HZ 1024
|
||||||
#define configSTACK_DEPTH_TYPE uint16_t
|
#define configSTACK_DEPTH_TYPE uint16_t
|
||||||
|
@ -65,11 +66,11 @@ typedef void (*TaskFunction_t)(void *instance);
|
||||||
* \ingroup Tasks
|
* \ingroup Tasks
|
||||||
*/
|
*/
|
||||||
//typedef void * TaskHandle_t;
|
//typedef void * TaskHandle_t;
|
||||||
struct TaskHandle_t {
|
typedef struct TaskHandle_t {
|
||||||
void *thread_handle = nullptr;
|
void *thread_handle;
|
||||||
TaskFunction_t task_fn;
|
TaskFunction_t task_fn;
|
||||||
void *instance = nullptr;
|
void *instance;
|
||||||
};
|
}TaskHandle_t;
|
||||||
|
|
||||||
/* Task states returned by eTaskGetState. */
|
/* Task states returned by eTaskGetState. */
|
||||||
enum eTaskState
|
enum eTaskState
|
||||||
|
@ -101,7 +102,7 @@ is used in assert() statements. */
|
||||||
|
|
||||||
/* Used with the uxTaskGetSystemState() function to return the state of each task
|
/* Used with the uxTaskGetSystemState() function to return the state of each task
|
||||||
in the system. */
|
in the system. */
|
||||||
struct TaskStatus_t {
|
typedef struct TaskStatus_t {
|
||||||
TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
|
TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
|
||||||
const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||||
UBaseType_t xTaskNumber; /* A number unique to the task. */
|
UBaseType_t xTaskNumber; /* A number unique to the task. */
|
||||||
|
@ -111,7 +112,7 @@ struct TaskStatus_t {
|
||||||
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
|
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
|
||||||
//StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
|
//StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
|
||||||
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
|
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
|
||||||
};
|
}TaskStatus_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
|
* configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
|
||||||
|
|
Loading…
Reference in a new issue