【11】uC/OS-III应用开发————>RAM内存管理(STM32F767)

  1. 简述
    1. 在嵌入式系统中,内存分配应根据系统特点选择使用
      1. 动态内存分配算法:普通业务系统,动态内存上限取决于硬件,使用效率高
      2. 静态内存分配算法:可靠性非常高的系统,需要考虑内存上限,使用效率低
    2. uC/OS内存管理是采用内存池的方式进行管理
    3. 静态划分一大块连续空间做为内存管理的空间,内部划分若干块
    4. 使用的时候就从内存池中获取内存块,使用完将其放回
    5. 核心机制:
      1. 内存池的创建
      2. 分配
      3. 释放
  2. 存储空间分类:
    1. 内部存储空间:RAM(本节所讲)
    2. 外部存储空间:ROM
  3. 运行机制
    1. 内存池(Memory Pool)是一种用于分配大量大小相同的内存对象的技术,可以加快内存分配/释放的速度
    2. 系统编译时,编译器静态划分一个数组做为系统的内存池,将其分成大小相等的内存块,通过链表链接起来
    3. 先创建内存池才能使用内存块,
    4. 内存控制块
      1. 内存池名称
      2. 起始地址
      3. 空闲内存块列表
      4. 大小
      5. 内存块数量
      6. 空闲内存块数量
  4. 应用场景
    1. 在不确定数组应该有多大的时候,静态方法,会浪费大量的内存空间,有可能会引起下标越界
    2. uC/OS将系统静态分配的大数组做为内存池,然后分配固定大小的内存块
    3. 如果某个任务内存需求很大,只能按照最大的内存块分配
  5. 常用函数
    1. OSMemCreate();  内存创建函数
    2. OSMemGet();  内存申请函数
    3. OSMemPut();  内存释放函数
  6. 例程
    1. 创建
          //创建内存管理对象 mem
          OSMemCreate( (OS_MEM        *)&mem,         //指向内存管理对象
                       (CPU_CHAR      *)"mem for test",//命名内存管理对象
                       (void          *)ucArray,      //内存分区的首地址
                       (OS_MEM_QTY     )3,            //内存分区中内存块数目
                       (OS_MEM_SIZE    )20,           //内存块的字节数目
                       (OS_ERR        *)&err);        //返回错误类型

       

    2. 申请
      /**************************************************
       * 函数名:static void AppTaskKey(void *p_arg)
       * 描述  :按键检测
       * 输入  :无
       * 输出  :无
       * 返回  :无 
       * 调用  :内部调用 
       **************************************************/
      static void AppTaskKey(void *p_arg)
      {
          OS_ERR err;
          
          char * p_mem_blk;
          uint32_t ulcount = 0;
          
          (void)p_arg;
      
          for(;;)
          {
              //向mem获取内存块
              p_mem_blk = OSMemGet( (OS_MEM       *)&mem,     //指向内存管理对象
                                    (OS_ERR       *)&err);    //返回错误类型
              
              sprintf(p_mem_blk, "%d", ulcount ++);           //向内存块存取计数值
              
              OSTaskQPost( (OS_TCB        *)&AppTaskLedTCB,       //目标任务控制块
                           (void          *)p_mem_blk,     //消息内容的首地址
                           (OS_MSG_SIZE    )strlen(p_mem_blk),  //  消息长度
                           (OS_OPT         )OS_OPT_POST_FIFO,         //发送到任务消息队列的入口
                           (OS_ERR        *)&err);                    //返回错误类型
          
              OSTimeDlyHMSM ( 0, 0, 1, 0, OS_OPT_TIME_DLY, & err );                   //每1s发送一次           
          }
      }

       

    3. 释放
      /**************************************************
       * 函数名:static void AppTaskLed(void *p_arg)
       * 描述  :led应用
       * 输入  :无
       * 输出  :无
       * 返回  :无 
       * 调用  :内部调用 
       **************************************************/
      static void AppTaskLed(void *p_arg)
      {
          OS_ERR err;
          
          CPU_INT32U  cpu_clk_freq;
          CPU_TS  ts;
          OS_MSG_SIZE msg_size;
          char * pMsg;
          
          (void)p_arg;
      
          cpu_clk_freq = BSP_CPU_ClkFreq();   //获取系统时钟
          
          for(;;)
          {
              pMsg = OSTaskQPend( (OS_TICK        )0,     //无期限等待
                                  (OS_OPT         )OS_OPT_PEND_BLOCKING,      //没有消息任务就阻塞
                                  (OS_MSG_SIZE   *)&msg_size,                 //返回消息长度
                                  (CPU_TS        *)&ts,                       //返回消息被发送的时间戳
                                  (OS_ERR        *)&err);                     //返回错误类型
              
              ts = OS_TS_GET() - ts;  //计算时间差
              LED1_TOGGLE;
              
              printf("\r\n 接收到的消息内容为: %s,长度是: %d 字节 \r\n", pMsg,msg_size);
              printf("\r\n 任务消息从被发送到被接收的时间差是: %d us \r\n", ts / (cpu_clk_freq / 1000000));    
      
              //退还内存块
              OSMemPut( (OS_MEM       *)&mem,         //指向内存管理对象
                        (void         *)pMsg,         //内存块的首地址
                        (OS_ERR       *)&err);        //返回错误类型
          }    
      }

       

  7. 下载验证
  8. 总结
    1. uC/OS的内存分配算法是只允许用户分配固定大小的内存块,使用完将其放回内存池中;
    2. 内存池中的内存块是通过单链表连接起来的,创建的内存块地址是连续的,空闲的内存块地址上不一定连续
    3. uC/OS将系统静态分配的大数组做为内存池,然后分配固定大小的内存块
    4. uC/OS的内存分配只能解决内存利用率的问题
  9. 参考资料:
    1. 正点原子《STM32F767 UCOS开发手册》
    2. 野火《uC/OS-III内核应用与开发》
    3. 《嵌入式实时操作系统 uC/OS-II原理及应用(第二版)》
    4. 官方源码
  10. 硬件平台:
    1. 正点原子阿波罗F767
  11. 软件平台:
    1. MDK5.2.5
  12. 库版本:
    1. TM32Cube_FW_F7_V1.4.0
  13. uC/OS-III版本
    1. UCOSIII 3.04
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值