|
楼主 |
发表于 2016-1-7 16:24:53
|
显示全部楼层
19.3 实验例程说明
19.3.1 STM32F103开发板实验
配套例子:
V4-419_RTX实验_SVC中断方式调用用户函数
实验目的:
1. 学习SVC中断方式调用用户函数
实验说明:
1. RTX支持配置所有任务工作特权级模式或者用户模式,宏配置在文件RTX_Conf_CM.c文件里面
#defineOS_RUNPRIV 0
配置为0的话,任务工作在用户级,配置为1的话,任务工作在特权级。本实验配置为0,所有任务都工作在用户级模式。
2. 本实验演示SVC中断号调用方法。
SVC指令带一个8位的立即数(范围0-255),可以视为是它的参数,被封装在指令本身中,如:
SVC 3 ; 呼叫3号系统服务
SVC0被RTX系统所使用了,用户只能使用从1开始的服务号。用户使用的时候一定要保证从1开始,而且需要连续的使用。实验中使用了SVC 1和SVC 2。
实验内容:
1.K1按键按下,串口打印。
2.K2键按下,向消息邮箱发送数据。任务AppTaskMsgPro接收到消息后进行消息处理。
3.K3键按下,调用SVC的1号系统服务。
4.摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可以在中断中设置NVIC。
5.各个任务实现的功能如下:
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个任务都是采用自定义堆栈方式。
l Run in privileged mode
设置任务运行在非特权级模式
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);
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建消息邮箱 */
- os_mbx_init (&mailbox, sizeof(mailbox));
-
- }
复制代码 u SVC中断函数的创建:
- void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);
- void __svc(2) SVC_2_FunCall(void);
-
- /*
- *********************************************************************************************************
- * 函 数 名: __SVC_1和__SVC_2系统服务号
- * 功能说明: 被SVC中断所调用的__SVC_1和__SVC_2
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)
- {
- /*
- 1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示
- 2. 根据需要做开关中断操作。
- */
- __disable_irq();
- printf("_arg1 = %d\\r\\n", _arg1);
- printf("_arg2 = %d\\r\\n", _arg2);
- printf("_arg3 = %d\\r\\n", _arg3);
- printf("_arg4 = %lld\\r\\n", *_arg4);
- __enable_irq();
- }
-
- void __SVC_2(void)
- {
- /*
- 1. 根据需要做开关中断操作。
- 2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。
- 所以可以在此中断中设置NVIC分组。
- */
- __disable_irq();
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
- __enable_irq();
- }
复制代码 u SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
- void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);
- AREA SVC_TABLE, CODE, READONLY
-
- EXPORT SVC_Count
-
- SVC_Cnt EQU (SVC_End-SVC_Table)/4
- SVC_Count DCD SVC_Cnt
-
- ; Import user SVC functions here.
- IMPORT __SVC_1
- IMPORT __SVC_2
-
- EXPORT SVC_Table
- SVC_Table
- ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
- DCD __SVC_1 ; user SVC function
- DCD __SVC_2 ; user SVC function
-
- SVC_End
-
- END
复制代码 u 四个RTX任务的实现:
19.3.2 STM32F407开发板实验
配套例子:
V5-419_RTX实验_SVC中断方式调用用户函数
实验目的:
1. 学习SVC中断方式调用用户函数
实验说明:
1. RTX支持配置所有任务工作特权级模式或者用户模式,宏配置在文件RTX_Conf_CM.c文件里面
#defineOS_RUNPRIV 0
配置为0的话,任务工作在用户级,配置为1的话,任务工作在特权级。本实验配置为0,所有任务都工作在用户级模式。
2. 本实验演示SVC中断号调用方法。
SVC指令带一个8位的立即数(范围0-255),可以视为是它的参数,被封装在指令本身中,如:
SVC 3 ; 呼叫3号系统服务
SVC0被RTX系统所使用了,用户只能使用从1开始的服务号。用户使用的时候一定要保证从1开始,而且需连续的使用。实验中使用了SVC 1和SVC 2。
实验内容:
1.K1按键按下,串口打印。
2.K2键按下,向消息邮箱发送数据。任务AppTaskMsgPro接收到消息后进行消息处理。
3.K3键按下,调用SVC的1号系统服务。
4.摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可以在中断中设置NVIC。
5.各个任务实现的功能如下:
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个任务都是采用自定义堆栈方式。
l Run in privileged mode
设置任务运行在非特权级模式
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);
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建消息邮箱 */
- os_mbx_init (&mailbox, sizeof(mailbox));
-
- }
复制代码 u SVC中断函数的创建:
- void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);
- void __svc(2) SVC_2_FunCall(void);
-
- /*
- *********************************************************************************************************
- * 函 数 名: __SVC_1和__SVC_2系统服务号
- * 功能说明: 被SVC中断所调用的__SVC_1和__SVC_2
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)
- {
- /*
- 1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示
- 2. 根据需要做开关中断操作。
- */
- __disable_irq();
- printf("_arg1 = %d\\r\\n", _arg1);
- printf("_arg2 = %d\\r\\n", _arg2);
- printf("_arg3 = %d\\r\\n", _arg3);
- printf("_arg4 = %lld\\r\\n", *_arg4);
- __enable_irq();
- }
-
- void __SVC_2(void)
- {
- /*
- 1. 根据需要做开关中断操作。
- 2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。
- 所以可以在此中断中设置NVIC分组。
- */
- __disable_irq();
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
- __enable_irq();
- }
复制代码 u SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
- void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);
- AREA SVC_TABLE, CODE, READONLY
-
- EXPORT SVC_Count
-
- SVC_Cnt EQU (SVC_End-SVC_Table)/4
- SVC_Count DCD SVC_Cnt
-
- ; Import user SVC functions here.
- IMPORT __SVC_1
- IMPORT __SVC_2
-
- EXPORT SVC_Table
- SVC_Table
- ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
- DCD __SVC_1 ; user SVC function
- DCD __SVC_2 ; user SVC function
-
- SVC_End
-
- END
复制代码 u 四个RTX任务的实现:
|
|