完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转rtx操作系统
本章节为大家讲解如何采用SVC中断方式调用用户函数。当用户将RTX任务设置为工作在非特权级模式时,任务中是不允许访问特权级寄存器的,这个时候使用SVC中断,此问题就迎刃而解了。 本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。 19.1 SVC中断 19.2 RTX中SVC中断方式调用函数方法 19.3 实验例程说明 19.4 总结 19.1 SVC中断 19.1.1 SVC功能介绍 SVC用于产生系统函数的调用请求。例如,操作系统通常不让用户程序直接访问硬件,而是通过提供一些系统服务函数,让用户程序使用SVC发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就要产生一个SVC异常,然后操作系统提供的SVC异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。 SVC这种“提出要求——得到满足”的方式很好: l 它使用户程序从控制硬件的繁文缛节中解脱出来,而是由OS负责控制具体的硬件。 l OS的代码可以经过充分的测试,从而能使系统更加健壮和可靠。 l 它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险。 l 通过SVC的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。开发应用程序唯一需要知道的就是操作系统提供的应用编程接口(API),并且在了解了各个请求代号和参数表后,就可以使用SVC来提出要求了(事实上,为使用方便,操作系统往往会提供一层封皮,以使系统调用的形式看起来和普通的函数调用一致。各封皮函数会正确使用SVC指令来执行系统调用)。其实,严格地讲,操作硬件的工作是由设备驱动程序完成的,只是对应用程序来说,它们也相当于操作系统的一部分。如下图所示: SVC异常通过执行”SVC”指令来产生。该指令需要一个立即数,充当系统调用代号。SVC异常服务例程稍后会提取出此代号,从而获知本次调用的具体要求,再调用相应的服务函数。例如, SVC 0x3 ; 调用3号系统服务 在SVC服务例程执行后,上次执行的SVC指令地址可以根据自动入栈的返回地址计算出。找到了SVC指令后,就可以读取该SVC指令的机器码,从机器码中萃取出立即数,就获知了请求执行的功能代号。如果用户程序使用的是PSP,服务例程还需要先执行MRS Rn, PSP指令来获取应用程序的堆栈指针。通过分析LR的值,可以获知在SVC指令执行时,正在使用哪个堆栈。 注意,我们不能在SVC服务例程中嵌套使用SVC指令(事实上这样做也没意义),因为同优先级的异常不能抢占自身。这种作法会产生一个用法fault。同理,在NMI服务例程中也不得使用SVC,否则将触发硬fault。 |
|
相关推荐
|
|
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)); /* 任务栈大小,单位字节数 */ } |
|
|
|
|
|
消息邮箱的创建:
复制代码 #define PoolBlocks 10 #define PoolPerBlockSize 8 /* 声明一个支持10个消息的消息邮箱 */ os_mbx_declare (mailbox, 10); /* ********************************************************************************************************* * 函 数 名: AppObjCreate * 功能说明: 创建任务通信机制 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void AppObjCreate (void) { /* 创建消息邮箱 */ os_mbx_init (&mailbox, sizeof(mailbox)); } |
|
|
|
|
|
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 = %drn", _arg1); printf("_arg2 = %drn", _arg2); printf("_arg3 = %drn", _arg3); printf("_arg4 = %lldrn", *_arg4); __enable_irq(); } void __SVC_2(void) { /* 1. 根据需要做开关中断操作。 2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。 所以可以在此中断中设置NVIC分组。 */ __disable_irq(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); __enable_irq(); } |
|
|
|
|
|
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 |
|
|
|
|
|
19.4 总结
本章节主要大家讲解了如何采用SVC中断方式调用用户函数,更多SVC中断方面的知识可以看Cortex-M3或者M4权威指南。 |
|
|
|
|
|
464 浏览 0 评论
478 浏览 1 评论
基于瑞萨FPB-RA4E2智能床头灯项目——1编译环境搭建与点亮驱动ws2812全彩LED
439 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
994 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
1056 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11780 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 03:01 , Processed in 0.789784 second(s), Total 52, Slave 44 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号