RTX之——内存管理

Posted Albert Nie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RTX之——内存管理相关的知识,希望对你有一定的参考价值。

内存管理

在创建一个线程的时候,我们会为该线程专门分配一个,称之为线程栈,用于线程切换时保存相关数据。这个栈区别于微处理器本身的栈。线程栈(thread stack)是一块内存。线程栈的默认大小定义在RTOS配置文件RTX_Config.h中,当然我们也可以在线程属性结构体中自定义线程栈的大小。
有关线程的知识,请见:☞多线程-RGB_LED灯闪烁

要自定义线程栈大小,首先得知道RTX的内存分配模型。

内存分配模型

keil RTX5通常支持三种对象内存分配模型,分别是:

  • Global Memory Pool: 全局内存池,将所有对象放在一个内存池里面,对象用多少内存,就分配多少内存。优点是配置简单;缺点是在对象创建和删除的过程中,容易造成内存碎片。keil RTX5默认的对象内存分配模型是全局内存池模型。

在这里插入图片描述

  • Object-specific Memory Pools: 对象专用内存池,即为每种对象类型分配一块固定大小的内存。由于对象的大小是固定的,所以在创建和删除的过程中不会造成内存碎片。

在这里插入图片描述

  • Static Object Memory: 静态对象内存,需要编译期即为对象分配内存。这就要求用户在定义某个对象的时候指定其大小。

在这里插入图片描述

全局内存池

在全局内存池模型中,对象的创建和销毁可能会造成内存碎片的问题。全局内存池的大小定义在配置文件RTX_Config.h中。

#define OS_DYNAMIC_MEM_SIZE  4096   // 4KB

在这里插入图片描述

对象专用内存池

我们也可以选择Object-specific Memory Pools为专用对象分配内存。不过,我们需要指定专用对象类型的最大数量和其内存大小。RTOS负责为专用对象计算和保留所需的内存大小。Object-specific Memory Pools也在配置文件RTX_Config.h中,通过使能Object specific Memory allocation选项即可可视化配置。

#define OS_THREAD_OBJ_MEM  1               // 1KB
#define OS_THREAD_NUM  3                   // 总线程个数
#define OS_THREAD_DEF_STACK_NUM 2          // 使用默认栈大小的线程个数
#define OS_STACK_SIZE               200    // 线程栈大小
#define OS_THREAD_USER_STACK_SIZE  1024    // 用户提供的总线程栈大小

在这里插入图片描述

上面,总共创建了三个线程,其中两个线程使用默认栈大小 200 bytes,另外一个线程使用自定义栈大小为1024 bytes,如下:

 // 自定义线程栈大小
static const osThreadAttr_t threadAttr_thread3 = {  
	"thread3",
	NULL,
	NULL,
	NULL,
	NULL,
	1024,     // stack size
	osPriorityNormal,
	NULL,
	NULL
};

静态对象内存池

我们也可以静态定义对象内存大小。首先,定义一个静态线程栈数组。

static uint64_t thread_stk[64];  //使用uint64_t 确保8字节对齐

在这里插入图片描述

然后定义一个RTX线程控制块,osRtxThread类型定义在rtx_os.h头文件中,所以要包含头文件。

#include "rtx_os.h"
static osRtxThread_t thread_tcb;

最后,配置线程属性结构体,就实现了静态配置对象内存了。

 // 自定义线程栈大小
static const osThreadAttr_t threadAttr_thread4 = {  
	"thread4",
	NULL,
	&thread_tcb,          // cb memory
	sizeof(thread_tcb),   // cb size
	&thread_stk[0],       // stack memory
	sizeof(thread_stk),   // stack size
	osPriorityNormal,
	NULL,
	NULL
};

官方案例

为方便大家理解,贴出官方案例。

/*----------------------------------------------------------------------------
 * CMSIS-RTOS 'main' function template
 *---------------------------------------------------------------------------*/
#include "RTE_Components.h"
#include  CMSIS_device_header
#include "cmsis_os2.h"
 
//include rtx_os.h for types of RTX objects
#include "rtx_os.h"
 
//The thread function instanced in this example
void worker(void *arg)
{
  while(1) 
  {
    //work
    osDelay(10000);
  }  
}
 
// Define objects that are statically allocated for worker thread 1
__attribute__((section(".bss.os.thread.cb")))
osRtxThread_t worker_thread_tcb_1;
 
// Reserve two areas for the stacks of worker thread 1
// uint64_t makes sure the memory alignment is 8
uint64_t worker_thread_stk_1[64];
 
// Define the attributes which are used for thread creation
// Optional const saves RAM memory and includes the values in periodic ROM tests 
const osThreadAttr_t worker_attr_1 = {
  "wrk1",
  osThreadJoinable,
  &worker_thread_tcb_1,
  sizeof(worker_thread_tcb_1),
  &worker_thread_stk_1[0],
  sizeof(worker_thread_stk_1),
  osPriorityAboveNormal,
  0
};
 
// Define ID object for thread
osThreadId_t th1;
 
/*----------------------------------------------------------------------------
 * Application main thread
 *---------------------------------------------------------------------------*/
void app_main (void *argument) {
  uint32_t param = NULL;
 
  // Create an instance of the worker thread with static resources (TCB and stack)
  th1 = osThreadNew(worker, &param, &worker_attr_1);
 
  for (;;) {}
}
 
int main (void) {
  // System Initialization
  SystemCoreClockUpdate();
  // ...
  osKernelInitialize();                 // Initialize CMSIS-RTOS
  osThreadNew(app_main, NULL, NULL);    // Create application main thread
  osKernelStart();                      // Start thread execution
  for (;;) {}
}

小结

本文主要介绍了RTX5的三大内存分配模型:

  • 全局内存池
  • 对象专用内存池
  • 静态对象内存

了解了对象内存分配模型,才好更方便地配置我们需要的对象资源~

参考资料

想看原滋原味的英文资料?,喏~

☞Memory allocation

☞RTX5 tutorial

以上是关于RTX之——内存管理的主要内容,如果未能解决你的问题,请参考以下文章

RTX 线程通信之——内存池

RTX 线程通信之——内存池

RTX——第18章 内存管理

RTX之——时间管理

RTX之——时间管理

迁移学习 - 尝试在 RTX 2070 上重新训练efficientnet-B07 内存不足