【FreeRTOS源码阅读】<3> heap_x.c

 

heap_1 内存管理阅读

直接数组向后一直申请,不支持释放


heap_2 内存管理阅读

除了不合并空闲块以外,其他和heap_4一样


heap_3 内存管理阅读

直接调用系统的malloc和free


heap_4 内存管理阅读

在创建任务时,会给TCB申请内存空间、给任务的栈申请空间、给状态链表申请空间;在使用队列以及信号量时,会给队列申请空间。申请空间时会调用vPortMalloc函数进行申请。下面就来介绍heap_4的管理机制。

首先根据FreeRTOSConfig.h文件下的configTOTAL_HEAP_SIZE大小定义一个unsigned char的数组,这个数组就是整个内存管理的整个堆空间。整个对空间使用类型为BlockList_t的链表进行维护。

在第一次调用vPortMalloc时,会先调用static void prvHeapInit( void )函数将整个RTOS的堆进行初始化,流程如下:

当堆初始化完成后,对数组这段内存的分块如下图:

字节对齐舍弃字节 FirstFreeBlock FreeHeap pxEnd 字节对齐舍弃字节
xStart        

堆空间初始化完成后,继续进行堆内存申请的工作。流程如下:此时xStart.pxNextFreeBlock只想FirstFreeBlock。

申请完堆内存以后,内存表如下图:

字节对齐舍弃字节 MallocedBlock MallocedHeap
在使用 Keil 编译 FreeRTOS 项目时,遇到 **L6218E: Undefined symbol** 错误通常表明某些关键函数或符号未被正确实现或未包含在项目中。以下是一些常见原因和解决方法: ### 1. 未实现 FreeRTOS 适配函数 FreeRTOS 需要一些特定平台的适配函数,例如内存管理函数 `pvPortMalloc` 和 `vPortFree`,以及任务钩子函数 `vApplicationIdleHook`、`vApplicationStackOverflowHook` 和 `vApplicationTickHook`。如果这些函数未在项目中定义,编译器将无法找到它们的实现并报错[^1]。 **解决方法:** - 确保包含 `heap_1.c`、`heap_2.c` 或 `heap_4.c` 文件(位于 FreeRTOS 源码的 `Source/portable/MemMang` 目录中),并将其添加到项目中以提供 `pvPortMalloc` 和 `vPortFree` 的实现。 - 实现空闲任务钩子函数 `vApplicationIdleHook()`、堆栈溢出钩子函数 `vApplicationStackOverflowHook()` 和时间片钩子函数 `vApplicationTickHook()`,即使它们为空函数。 ```c void vApplicationIdleHook(void) { // 空闲钩子函数实现 } void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { // 堆栈溢出处理 (void)xTask; (void)pcTaskName; } void vApplicationTickHook(void) { // 时间片钩子函数实现 } ``` ### 2. FreeRTOS 配置选项未启用 某些功能(如 `xTaskGetCurrentTaskHandle`)需要在 `FreeRTOSConfig.h` 中启用相应的配置选项。例如,使用 `INCLUDE_xTaskGetCurrentTaskHandle` 宏来启用任务句柄获取功能[^2]。 **解决方法:** - 在 `FreeRTOSConfig.h` 中定义以下宏以启用相关功能: ```c #define INCLUDE_xTaskGetCurrentTaskHandle 1 ``` ### 3. 缺少必要的初始化函数 在 STM32 项目中,FreeRTOS 的初始化通常由 `MX_FREERTOS_Init()` 函数完成,该函数可能未在 `main()` 函数中调用,或者其定义未包含在项目中。 **解决方法:** - 检查 `main()` 函数是否调用了 `MX_FREERTOS_Init()`。 - 如果该函数未定义,请在 `freertos.c` 或类似文件中添加其实现。 ```c void MX_FREERTOS_Init(void) { // 初始化 FreeRTOS 资源,如创建任务、队列等 } ``` ### 4. SysTick 中断未正确配置 FreeRTOS 需要一个周期性的 SysTick 中断来驱动任务调度器。如果未正确配置 SysTick 中断处理程序 `xPortSysTickHandler`,则可能导致编译错误或运行时问题。 **解决方法:** - 确保在 `stm32fXxx_it.c` 文件中正确实现了 `SysTick_Handler`,并调用 `xPortSysTickHandler`。 ```c void SysTick_Handler(void) { HAL_IncTick(); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } } ``` ### 5. 未正确链接 FreeRTOS 库文件 如果项目未正确链接 FreeRTOS 的库文件或源文件,编译器将无法找到必要的符号定义。 **解决方法:** - 确认 FreeRTOS 的源文件路径已正确添加到项目的 `Include Paths`。 - 确保 `tasks.c`、`queue.c` 和 `event_groups.c` 等核心源文件已添加到项目中。 ### 6. 使用 CMSIS-Pack 时的配置问题 在 STM32CubeIDE 或 Keil 中使用 CMSIS-Pack 时,某些 FreeRTOS 功能可能未被正确启用。 **解决方法:** - 检查 `freertos.c` 文件中是否启用了必要的功能,例如定时器任务内存分配函数 `vApplicationGetTimerTaskMemory()`。 ```c void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) { static StaticTask_t xTimerTaskTCB; static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; *ppxTimerTaskTCBBuffer = &amp;xTimerTaskTCB; *ppxTimerTaskStackBuffer = uxTimerTaskStack; *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值