FreeRTOS内存管理:创建了三个任务,但是发现有一个任务没有运行

其实就是任务创建失败
所有任务内存总和超过了FreeRTOSConfig.h的configTOTAL_HEAP_SIZE。

FreeRTOS内存管理

学习自[中字] RTOS入门 Part 4 - 内存分配

stack(栈)、heap(堆)、static

了解stack(栈)、heap(堆)、static
请添加图片描述

任务内存组成

任务被创建时,会在heap占用一块空间存放,这段内存会被分为TCB(任务控制块)+STACK1(任务专属栈空间)。

TCBSTACK
结构体调用vTaskCreate产生的,告诉CPU需要分配多少heap来存放task stack
任务函数、任务地址、任务优先级……当任务要被切换时,存放当前任务的状态

不同任务创建时内存位置

请添加图片描述

task heap管理策略

动态分配内存时,程序会试图寻找最大的连续堆空间提供给你,但当你不停地分配和释放堆空间,可能会导致堆空间碎片化,(尽管还有剩下一些可用的碎片堆空间),因此FreeRTOS就提供了一些堆管理策略。

  • heap_1:不允许释放堆空间,使堆的一部分变成静态内存
  • heap_2:过时
  • heap_3:封装了malloc和free,使它们变得线程安全
  • heap_4:推荐使用,可以合并化碎片堆空间。
  • heap_5:最高级的,能联合使用不连续的堆空间
    ps:C的malloc和free都是不安全的,它们所需运行时间编译时无法确定。

计算任务所占内存

TCB

通常定义在task.c中,结构体命名为tskTCB,在FreeRTOS.g中也有定义,为StaticTask_t
请添加图片描述

printf("TCB Size: %d bytes\n", (int)sizeof(StaticTask_t));//可以发现,tskTAB后面被多次define套壳
配置项对 TCB 大小的影响
configUSE_TRACE_FACILITY=1增加调试字段,TCB 增大 20~50 字节
configUSE_TASK_NOTIFICATIONS=0移除通知字段,TCB 减小约 8 字节
configUSE_APPLICATION_TASK_TAG=1增加标签字段,TCB 增大 4 字节

堆栈大小

s t a c k = S t a c k D e p t h ∗ s i z e o f ( S t a c k T y p e t ) stack = StackDepth * sizeof(StackType_t) stack=StackDepthsizeof(StackTypet)
StackDepth:创建任务时指定的堆栈深度(如 xTaskCreate(..., 256, ...) 中的 256)。
StackType_t:通常为 uint32_t(4 字节),因此 256 字的堆栈占用 256 * 4 = 1024 字节

printf("TCB Size: %d bytes\n", (int)sizeof(StackType_t));//可以发现,tskTAB后面被多次define套壳

监控内存是否超限

// 示例:3 个任务的总内存需求
uint32_t total_memory = 3 * (sizeof(StaticTask_t) + (256 * sizeof(StackType_t)));
if (total_memory > configTOTAL_HEAP_SIZE) {
    printf("内存不足!需增大堆或减少任务堆栈!");
}

运行时监控堆内存

void check_memory() {
    printf("剩余堆内存: %d 字节\n", xPortGetFreeHeapSize());
}

检测堆栈使用率

void task_function(void *pvParameters) {
    UBaseType_t high_watermark;
    while(1) {
        high_watermark = uxTaskGetStackHighWaterMark(NULL);
        printf("堆栈剩余: %d 字\n", high_watermark);
        osDelay(1000);
    }
}

本次程序存在的问题:任务创建失败

任务分配的堆栈超出FreeRTOSConfig.h的configTOTAL_HEAP_SIZE

#define configTOTAL_HEAP_SIZE                    ((size_t)3072)

当前程序计算得到:
请添加图片描述
( 84 + 200 ∗ 4 ) ∗ 2 + ( 84 + 256 ∗ 4 ) = 2858 < 3072 (84 + 200 * 4) * 2 + (84 + 256 * 4) = 2858 < 3072 (84+2004)2+(84+2564)=2858<3072
( 4 + 256 ∗ 4 ) ∗ 3 = 3291 > 3072 (4 + 256 * 4) * 3 = 3291 > 3072 (4+2564)3=3291>3072
导致第三个任务创建失败。
即只需要修改:

  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 200);
  //osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 256);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of myTask02 */
  osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 200);
  //osThreadDef(defaultTask, StartTask02, osPriorityNormal, 0, 256);
  myTask02Handle = osThreadCreate(osThread(myTask02), NULL);

  /* definition and creation of myTask03 */
  osThreadDef(myTask03, StartTask03, osPriorityNormal, 0, 256);
  myTask03Handle = osThreadCreate(osThread(myTask03), NULL);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值