|
楼主 |
发表于 2016-1-6 15:39:24
|
显示全部楼层
18.4 实验例程说明(8字节对齐)
18.4 实验例程说明(8字节对齐)
18.4.1 STM32F103开发板实验
配套例子:
V4-418_RTX实验_内存管理(8字节对齐)
实验目的:
1. 学习RTX的内存管理(8字节对齐)。
2. 函数_declare_box8和_init_box8用于8字节对齐的内存池初始化。这里8字节对齐的含义:
a. 内存池的首地址是8字节对齐(8字节对齐就是地址对8求余等于0)。
b. 每个内存块大小也得是8字节的倍数,这样才能保证每申请到的一个内存块的首地址也是8字节对齐。
c. 8字节对齐是由RTX系统完成的。
实验内容:
1.K1按键按下,串口打印。
2.K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
3.K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
4.摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
5.摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据。
6.各个任务实现的功能如下:
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
RTX配置向导详情如下:
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任务调试信息:
程序设计:
u 任务栈大小分配:
staticuint64_t AppTaskUserIFStk[512/8]; /* 任务栈 */
staticuint64_t AppTaskLEDStk[256/8]; /* 任务栈 */
staticuint64_t AppTaskMsgProStk[512/8]; /* 任务栈 */
staticuint64_t AppTaskStartStk[512/8]; /* 任务栈 */
将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u 系统栈大小分配:
u RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码 u RTX任务创建:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCreate
- * 功能说明: 创建应用任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- 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
-
- /* 声明一个支持10个消息的消息邮箱 */
- os_mbx_declare (mailbox, 10);
-
- /* 声明一个内存池,10个块,每块大小8字节 */
- _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建消息邮箱 */
- os_mbx_init (&mailbox, sizeof(mailbox));
-
- /* 初始化内存池,8字节对齐,*/
- _init_box8 (mpool, sizeof (mpool), PoolPerBlockSize);
- }
复制代码 u 四个RTX任务的实现:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskUserIF
- * 功能说明: 按键消息处理
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 1 (数值越小优先级越低,这个跟uCOS相反)
- *********************************************************************************************************
- */
- __task void AppTaskUserIF(void)
- {
- uint8_t *pucMsg;
- uint16_t *pusMsg;
- uint32_t *pulMsg;
- uint64_t *pullMsg;
-
- uint8_t ucKeyCode, ucCount = 0;
-
- while(1)
- {
- ucKeyCode = bsp_GetKey();
-
- if (ucKeyCode != KEY_NONE)
- {
- switch (ucKeyCode)
- {
- /* K1键按下,打印调试说明 */
- case KEY_DOWN_K1:
- printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
- break;
-
- /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */
- case KEY_DOWN_K2:
- /* 申请一个内存块用于8位整形变量 */
- pucMsg = _alloc_box (mpool);
- *pucMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pucMsg);
- }
- else
- {
- /* 发送成功 */
- printf("K2键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pucMsg);
- }
- break;
-
- /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */
- case KEY_DOWN_K3:
- /* 申请一个内存块用于16位整形变量 */
- pusMsg = _alloc_box (mpool);
- *pusMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pusMsg);
- }
- else
- {
- /* 发送成功 */
- printf("K3键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pusMsg);
- }
- break;
-
- /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */
- case JOY_DOWN_OK:
- /* 申请一个内存块用于32位整形变量 */
- pulMsg = _alloc_box (mpool);
- *pulMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pulMsg);
- }
- else
- {
- /* 发送成功 */
- printf("摇杆OK键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pulMsg);
- }
- break;
-
- /* 摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据 */
- case JOY_DOWN_U:
- /* 申请一个内存块用于32位整形变量 */
- pullMsg = _alloc_box (mpool);
- *pullMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pullMsg);
- }
- else
- {
- /* 发送成功 */
- printf("摇杆OK键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pullMsg);
- }
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
-
- os_dly_wait(20);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskLED
- * 功能说明: LED闪烁。
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 2
- *********************************************************************************************************
- */
- __task void AppTaskLED(void)
- {
- const uint16_t usFrequency = 200; /* 延迟周期 */
-
- /* 设置延迟周期 */
- os_itv_set(usFrequency);
-
- while(1)
- {
- bsp_LedToggle(2);
- bsp_LedToggle(3);
-
- /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
- os_itv_wait();
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskMsgPro
- * 功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 3
- *********************************************************************************************************
- */
- __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;
-
- /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
- 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;
- }
- }
- }
复制代码
18.4.2 STM32F407开发板实验
配套例子:
V5-418_RTX实验_内存管理(8字节对齐)
实验目的:
1. 学习RTX的内存管理(8字节对齐)。
2. 函数_declare_box8和_init_box8用于8字节对齐的内存池初始化。这里8字节对齐的含义:
a. 内存池的首地址是8字节对齐(8字节对齐就是地址对8求余等于0)。
b. 每个内存块大小也得是8字节的倍数,这样才能保证每申请到的一个内存块的首地址也是8字节对齐。
c. 8字节对齐是由RTX系统完成的。
实验内容:
1.K1按键按下,串口打印。
2.K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
3.K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
4.摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
5.摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据。
6.各个任务实现的功能如下:
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
RTX配置向导详情如下:
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任务调试信息:
程序设计:
u 任务栈大小分配:
staticuint64_t AppTaskUserIFStk[512/8]; /* 任务栈 */
staticuint64_t AppTaskLEDStk[256/8]; /* 任务栈 */
staticuint64_t AppTaskMsgProStk[512/8]; /* 任务栈 */
staticuint64_t AppTaskStartStk[512/8]; /* 任务栈 */
将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u 系统栈大小分配:
u RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码 u RTX任务创建:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCreate
- * 功能说明: 创建应用任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- 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
-
- /* 声明一个支持10个消息的消息邮箱 */
- os_mbx_declare (mailbox, 10);
-
- /* 声明一个内存池,10个块,每块大小8字节 */
- _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建消息邮箱 */
- os_mbx_init (&mailbox, sizeof(mailbox));
-
- /* 初始化内存池,8字节对齐,*/
- _init_box8 (mpool, sizeof (mpool), PoolPerBlockSize);
- }
复制代码 u 四个RTX任务的实现:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskUserIF
- * 功能说明: 按键消息处理
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 1 (数值越小优先级越低,这个跟uCOS相反)
- *********************************************************************************************************
- */
- __task void AppTaskUserIF(void)
- {
- uint8_t *pucMsg;
- uint16_t *pusMsg;
- uint32_t *pulMsg;
- uint64_t *pullMsg;
-
- uint8_t ucKeyCode, ucCount = 0;
-
- while(1)
- {
- ucKeyCode = bsp_GetKey();
-
- if (ucKeyCode != KEY_NONE)
- {
- switch (ucKeyCode)
- {
- /* K1键按下,打印调试说明 */
- case KEY_DOWN_K1:
- printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
- break;
-
- /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */
- case KEY_DOWN_K2:
- /* 申请一个内存块用于8位整形变量 */
- pucMsg = _alloc_box (mpool);
- *pucMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pucMsg);
- }
- else
- {
- /* 发送成功 */
- printf("K2键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pucMsg);
- }
- break;
-
- /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */
- case KEY_DOWN_K3:
- /* 申请一个内存块用于16位整形变量 */
- pusMsg = _alloc_box (mpool);
- *pusMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pusMsg);
- }
- else
- {
- /* 发送成功 */
- printf("K3键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pusMsg);
- }
- break;
-
- /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */
- case JOY_DOWN_OK:
- /* 申请一个内存块用于32位整形变量 */
- pulMsg = _alloc_box (mpool);
- *pulMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pulMsg);
- }
- else
- {
- /* 发送成功 */
- printf("摇杆OK键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pulMsg);
- }
- break;
-
- /* 摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据 */
- case JOY_DOWN_U:
- /* 申请一个内存块用于32位整形变量 */
- pullMsg = _alloc_box (mpool);
- *pullMsg = ucCount++;
-
- /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
- if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
- {
- /* 发送失败,即使等待了100个时钟节拍 */
- printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\\r\\n");
- _free_box (mpool, pullMsg);
- }
- else
- {
- /* 发送成功 */
- printf("摇杆OK键按下,向消息邮箱发送数据成功\\r\\n");
- _free_box (mpool, pullMsg);
- }
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
-
- os_dly_wait(20);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskLED
- * 功能说明: LED闪烁。
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 2
- *********************************************************************************************************
- */
- __task void AppTaskLED(void)
- {
- const uint16_t usFrequency = 200; /* 延迟周期 */
-
- /* 设置延迟周期 */
- os_itv_set(usFrequency);
-
- while(1)
- {
- bsp_LedToggle(2);
- bsp_LedToggle(3);
-
- /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
- os_itv_wait();
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskMsgPro
- * 功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据
- * 形 参: 无
- * 返 回 值: 无
- * 优 先 级: 3
- *********************************************************************************************************
- */
- __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;
-
- /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
- 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;
- }
- }
- }
复制代码 |
|