加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【RTX操作系统教程】第18章 内存管理(中)

(2016-01-06 15:50:26)
标签:

安富莱

rtx

cosiii

emwin

stm32f407

分类: RTX及其中间件

第18章     内存管理

本章节为大家讲解RTX支持的内存管理。

本章教程配套的例子含Cortex-M3内核的STM32F103Cortex-M4内核的STM32F407

18.1 内存管理介绍

18.2 内存管理API函数

18.3 实验例程说明(4字节对齐)

18.4 实验例程说明(8字节对齐)

18.5       总结


18.3 实验例程说明(4字节对齐)

18.3.1 STM32F103开发板实验

配套例子:

V4-417_RTX实验_内存管理(4字节对齐)

实验目的:

1.     学习RTX的内存管理(4字节对齐)。

2.     函数_declare_box_init_box用于4字节对齐的内存池初始化。这里4字节对齐的含义

a. 内存池的首地址是4字节对齐(4字节对齐就是地址对4求余等于0)。

b. 每个内存块大小也得是4字节的倍数,这样才能保证每申请到的一个内存块的首地址也是4节对齐。

c. 4字节对齐是由RTX系统完成的。

实验内容:

1. K1按键按下,串口打印。

2. K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。

3. K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。

4. 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。

5. 各个任务实现的功能如下:

AppTaskUserIF任务   :按键消息处理。

AppTaskLED任务     LED闪烁。

AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。

AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

RTX配置:

RTX配置向导详情如下:

【RTX操作系统教程】第18章 <wbr>内存管理(中)

 

u  Task Configuration

l  Number of concurrent running tasks

允许创建4个任务,实际创建了如下四个任务:

              AppTaskUserIF任务   :按键消息处理。

              AppTaskLED任务     LED闪烁。

              AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。

              AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

l  Number of tasks with user-provided stack

创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:

【RTX操作系统教程】第18章 <wbr>内存管理(中)

 

程序设计:

u  任务栈大小分配:

static uint64_t AppTaskUserIFStk[512/8];   

static uint64_t AppTaskLEDStk[256/8];      

static uint64_t AppTaskMsgProStk[512/8];  

static uint64_t AppTaskStartStk[512/8];     

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。

u  系统栈大小分配:

【RTX操作系统教程】第18章 <wbr>内存管理(中)

 

u  RTX初始化:

 

int main (void)

  

     

     bsp_Init();

    

     

     os_sys_init_user (AppTaskStart,             

                       4,                        

                       &AppTaskStartStk,         

                       sizeof(AppTaskStartStk));

     while(1);

}

u  RTX任务创建:

 

static void AppTaskCreate (void)

{

     HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             

                                          1,                         

                                          &AppTaskUserIFStk,         

                                           sizeof(AppTaskUserIFStk));

    

     HandleTaskLED = os_tsk_create_user(AppTaskLED,              

                                       2,                       

                                        &AppTaskLEDStk,          

                                        sizeof(AppTaskLEDStk));  

    

     HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             

                                          3,                         

                                          &AppTaskMsgProStk,         

                                           sizeof(AppTaskMsgProStk));

}

u  内存管理的初始化和消息邮箱的创建:

 

#define PoolBlocks           10

#define PoolPerBlockSize     8

 

 

os_mbx_declare (mailbox, 10);

 

 

_declare_box(mpool, PoolPerBlockSize, PoolBlocks);

 

 

static void AppObjCreate (void)

{

     

      os_mbx_init (&mailbox, sizeof(mailbox));

    

     

     _init_box (mpool, sizeof (mpool), PoolPerBlockSize);

}

u  四个RTX任务的实现:

 

__task void AppTaskUserIF(void)

{

     uint8_t  *pucMsg;

     uint16_t *pusMsg;

     uint32_t *pulMsg;

     uint8_t ucKeyCode, ucCount = 0;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                   

                   case KEY_DOWN_K1:

                       printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");

                       break;  

 

                   

                   case KEY_DOWN_K2:

                       

                       pucMsg  = _alloc_box (mpool);

                       *pucMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)

                       {

                            

                            printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pucMsg);

                       }

                       else

                       {

                            

                            printf("K2键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pucMsg);

                       }

                       break;  

 

                   

                   case KEY_DOWN_K3:

                       

                       pusMsg  = _alloc_box (mpool);

                       *pusMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)

                       {

                            

                            printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pusMsg);

                       }

                       else

                       {

                            

                            printf("K3键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pusMsg);

                       }

                       break;  

                  

                   

                   case JOY_DOWN_OK:

                       

                       pulMsg  = _alloc_box (mpool);

                       *pulMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)

                       {

                            

                            printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pulMsg);

                       }

                       else

                       {

                            

                            printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pulMsg);

                       }

                       break;

 

                   

                   default:                    

                       break;

              }

         }

        

         os_dly_wait(20);

     }

}

 

 

__task void AppTaskLED(void)

{

     const uint16_t usFrequency = 200;

    

     

     os_itv_set(usFrequency);

    

    while(1)

    {

         bsp_LedToggle(2);

         bsp_LedToggle(3);

 

         

         os_itv_wait();

    }

}

 

 

__task void AppTaskMsgPro(void)

{

     uint8_t *pMsg;

     OS_RESULT xResult;

     const uint16_t usMaxBlockTime = 200;

    

    while(1)

    {

         xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);

        

         switch (xResult)

         {

              

              case OS_R_OK:

                   printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);

                   break;  

 

              

              case OS_R_MBX:

                   printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);

                   break;

 

              

              case OS_R_TMO:

                   bsp_LedToggle(1);

                   bsp_LedToggle(4);

                   break;

             

              

              default:                    

                   break;

           

    }

}

 

 

__task void AppTaskStart(void)

{

     

     AppTaskCreate();

    

     

     AppObjCreate();

    

    while(1)

    {

         

         bsp_KeyScan();

        os_dly_wait(10);

    }

}

18.3.2 STM32F407开发板实验

配套例子:

V5-417_RTX实验_内存管理(4字节对齐)

实验目的:

1.     学习RTX的内存管理(4字节对齐)。

2.     函数_declare_box_init_box用于4字节对齐的内存池初始化。这里4字节对齐的含义

a. 内存池的首地址是4字节对齐(4字节对齐就是地址对4求余等于0)。

b. 每个内存块大小也得是4字节的倍数,这样才能保证每申请到的一个内存块的首地址也是4节对齐。

c. 4字节对齐是由RTX系统完成的。

实验内容:

1. K1按键按下,串口打印。

2. K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。

3. K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。

4. 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。

5. 各个任务实现的功能如下:

AppTaskUserIF任务   :按键消息处理。

AppTaskLED任务     LED闪烁。

AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。

AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

RTX配置:

RTX配置向导详情如下:

 【RTX操作系统教程】第18章 <wbr>内存管理(中)

u  Task Configuration

l  Number of concurrent running tasks

允许创建4个任务,实际创建了如下四个任务:

              AppTaskUserIF任务   :按键消息处理。

              AppTaskLED任务     LED闪烁。

              AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。

              AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

l  Number of tasks with user-provided stack

创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:

【RTX操作系统教程】第18章 <wbr>内存管理(中)

 

程序设计:

u  任务栈大小分配:

static uint64_t AppTaskUserIFStk[512/8];   

static uint64_t AppTaskLEDStk[256/8];      

static uint64_t AppTaskMsgProStk[512/8];  

static uint64_t AppTaskStartStk[512/8];     

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。

u  系统栈大小分配:

【RTX操作系统教程】第18章 <wbr>内存管理(中)

 

u  RTX初始化:

 

int main (void)

  

     

     bsp_Init();

    

     

     os_sys_init_user (AppTaskStart,             

                       4,                        

                       &AppTaskStartStk,         

                       sizeof(AppTaskStartStk));

     while(1);

}

u  RTX任务创建:

 

static void AppTaskCreate (void)

{

     HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             

                                          1,                         

                                          &AppTaskUserIFStk,         

                                           sizeof(AppTaskUserIFStk));

    

     HandleTaskLED = os_tsk_create_user(AppTaskLED,              

                                       2,                       

                                        &AppTaskLEDStk,          

                                        sizeof(AppTaskLEDStk));  

    

     HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             

                                          3,                         

                                          &AppTaskMsgProStk,         

                                           sizeof(AppTaskMsgProStk));

}

u  内存管理的初始化和消息邮箱的创建:

#define PoolBlocks           10

#define PoolPerBlockSize     8

 

 

os_mbx_declare (mailbox, 10);

 

 

_declare_box(mpool, PoolPerBlockSize, PoolBlocks);

 

 

static void AppObjCreate (void)

{

     

      os_mbx_init (&mailbox, sizeof(mailbox));

    

     

     _init_box (mpool, sizeof (mpool), PoolPerBlockSize);

}

u  四个RTX任务的实现:

 

__task void AppTaskUserIF(void)

{

     uint8_t  *pucMsg;

     uint16_t *pusMsg;

     uint32_t *pulMsg;

     uint8_t ucKeyCode, ucCount = 0;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                   

                   case KEY_DOWN_K1:

                       printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");

                       break;  

 

                   

                  case KEY_DOWN_K2:

                       

                       pucMsg  = _alloc_box (mpool);

                       *pucMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)

                       {

                            

                            printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pucMsg);

                       }

                       else

                       {

                            

                            printf("K2键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pucMsg);

                       }

                       break;  

 

                   

                   case KEY_DOWN_K3:

                       

                       pusMsg  = _alloc_box (mpool);

                       *pusMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)

                       {

                            

                            printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pusMsg);

                       }

                       else

                       {

                            

                            printf("K3键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pusMsg);

                       }

                       break;  

                  

                   

                   case JOY_DOWN_OK:

                       

                       pulMsg  = _alloc_box (mpool);

                       *pulMsg = ucCount++;

                  

                       

                       if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)

                        {

                            

                            printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");

                            _free_box (mpool, pulMsg);

                       }

                       else

                       {

                            

                            printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   

                            _free_box (mpool, pulMsg);

                       }

                       break;

 

                   

                   default:                    

                       break;

              }

         }

        

         os_dly_wait(20);

     }

}

 

 

__task void AppTaskLED(void)

{

     const uint16_t usFrequency = 200;

    

     

     os_itv_set(usFrequency);

    

    while(1)

    {

         bsp_LedToggle(2);

         bsp_LedToggle(3);

 

         

         os_itv_wait();

    }

}

 

 

__task void AppTaskMsgPro(void)

{

     uint8_t *pMsg;

     OS_RESULT xResult;

     const uint16_t usMaxBlockTime = 200;

    

    while(1)

    {

         xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);

        

         switch (xResult)

         {

              

              case OS_R_OK:

                   printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);

                   break;  

 

              

              case OS_R_MBX:

                   printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);

                   break;

 

              

              case OS_R_TMO:

                   bsp_LedToggle(1);

                   bsp_LedToggle(4);

                   break;

             

              

              default:                    

                   break;

           

    }

}

 

 

__task void AppTaskStart(void)

{

     

     AppTaskCreate();

    

     

     AppObjCreate();

    

    while(1)

    {

         

         bsp_KeyScan();

        os_dly_wait(10);

    }

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有