搜索
bottom↓
回复: 30

RTX 不关中断的奥秘

[复制链接]

出0入0汤圆

发表于 2014-6-7 10:25:11 | 显示全部楼层 |阅读模式
我现在研读rtx代码,按照2个思路展开,第一个是深入理解rtx内部机理,分析其实现原理,这样对其他rtos的理解会有极大帮助,再一个就是批判性的分析其代码了,我之前已经发过了几个帖子,其中还是有很多不明白的,个人感觉还有待商榷的地方,我都先挂出来,等到我最后真正理解透彻了这个rtos,也许这些一开始产生的疑问都不再是问题,到时候再一一解答

今天上点原理分析的料,不妥之处还请各路大神一一指点

RTX这个rtos系统在cm3中实现了全局不关中断这个特性,和其他类似的rtos相比是一个非常醒目的特性,基本原理如下

RTX内核管理了SVC、SYSTICK和PENDSV这3个中断,并且SVC是14级中断,后两个都是15级(最低)中断

外设中断调用内核服务,首先注册到OSFIFO中,同时启动PENDSV中断,当外设中断退出时,进入PENSV这个最低优先级中断进行真实的内核服务调用,
这样做的缺点相当明显,进入了2次中断,响应肯定比不上1次中断的速度,这也是RTX手册推荐外设中断尽量短小的原因
优点当然也很突出,由于在用户程序中,所有内核服务都是使用SVC 0进行调用,即使SVC中断被外设中断抢占,内核服务的线程安全也会被保证,因为
其没有真实操作内核对象

SVC 0调用内核服务,外设中断调用内核服务因PENDSV优先级较低无法抢占而被挂起,线程安全得以保证。。。。
外设中断调用内核服务进入到PENDSV,此时SVC 0 绝不可能发生,因为SVC 0调用内核服务只可能在用户程序中调用,而此时尚在中断态;如果在外设中断调用用户svc,除了要保证svc不能被屏蔽这个问题,用户svc也是无法调用内核复位的


由此  保证了RTX程序可以全局不关中断的特性,相当的巧妙

出0入0汤圆

发表于 2014-6-7 10:44:25 | 显示全部楼层
对于初学者,难点就在RTX的内核都是由SVC调用的,懂了这个,其它都好说。

出0入0汤圆

 楼主| 发表于 2014-6-7 10:48:06 | 显示全部楼层
Eric2013 发表于 2014-6-7 10:44
对于初学者,难点就在RTX的内核都是由SVC调用的,懂了这个,其它都好说。

Eric2013 大神,你可以搞搞rtx的分析啊,我现在不自量力的在胡诌啊嘿嘿

出0入0汤圆

发表于 2014-6-7 11:13:19 | 显示全部楼层
myxiaonia 发表于 2014-6-7 10:48
Eric2013 大神,你可以搞搞rtx的分析啊,我现在不自量力的在胡诌啊嘿嘿

你已经很牛啦,比我以前看的速度快多啦。

出0入0汤圆

发表于 2014-6-7 13:03:50 | 显示全部楼层
SVC+PSV一开始就是设计给OS使用的一对指令.
实际上就是把硬件的异常分成了两部分,一个是传统的硬件中断,一个是OS的系统调用,而且挺麻烦的一点是,两者几乎是绝缘的.
我之前尝试在中断中去调用OS的API,结果不成功,单步跟下去发现几乎所有的API进去第一件事就是检查CPU当前的执行权限,特权级下直接就退出来...相当恼火的情况...

出0入0汤圆

 楼主| 发表于 2014-6-7 13:10:07 | 显示全部楼层
error_dan 发表于 2014-6-7 13:03
SVC+PSV一开始就是设计给OS使用的一对指令.
实际上就是把硬件的异常分成了两部分,一个是传统的硬件中断,一 ...

rtx可以在中断中调用isr前缀的api,它被设计成注册到osfifo,然后在pensv中真正调用api,如果你使用的是os前缀的api,很有可能直接就进入hard fault了,因为svc不能被屏蔽嘛,虽然其可以被抢占

出0入0汤圆

发表于 2014-6-7 13:14:13 | 显示全部楼层
myxiaonia 发表于 2014-6-7 13:10
rtx可以在中断中调用isr前缀的api,它被设计成注册到osfifo,然后在pensv中真正调用api,如果你使用的是o ...

CMSIS那层皮一蒙就啥都没了,我就是坑在这里的,后来发现要去自己包含OS的各种模块,就没搞了.
SVC的中断优先级是必须要置顶的,不然硬件不给过,这个OS初始化的他自己就搞定了吧.
等你理顺了,写点心得分享一下呗~

出0入0汤圆

 楼主| 发表于 2014-6-7 13:32:31 | 显示全部楼层
error_dan 发表于 2014-6-7 13:14
CMSIS那层皮一蒙就啥都没了,我就是坑在这里的,后来发现要去自己包含OS的各种模块,就没搞了.
SVC的中断优 ...

哈哈 好的啊  搞定了写个笔记嘛

出10入0汤圆

发表于 2014-6-7 15:47:11 | 显示全部楼层
用CMSIS OS包起来的RTX就没有区分原来在中断里和任务里的几个API了

出0入0汤圆

 楼主| 发表于 2014-6-7 16:25:19 | 显示全部楼层
奇怪的是  为何svc中断要比pendsv和SYSTICK高一级呢,我觉得同级也没问题啊

出0入0汤圆

 楼主| 发表于 2014-6-11 07:54:29 | 显示全部楼层
myxiaonia 发表于 2014-6-7 16:25
奇怪的是  为何svc中断要比pendsv和SYSTICK高一级呢,我觉得同级也没问题啊

除掉上面这个中断优先级的疑问,现在又有一个新疑问,有关邮箱的isr操作

之前我提到,isr中调用内核服务的话,是先存放在osfifo中,但是isr_mbx_receive却不同

  1. OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) {
  2.   /* Receive a message in the interrupt function. The interrupt function   */
  3.   /* should not wait for a message since this would block the rtx os.      */
  4.   P_MCB p_MCB = mailbox;

  5.   if (p_MCB->count) {
  6.     /* A message is available in the fifo buffer. */
  7.     *message = p_MCB->msg[p_MCB->last];                        //1
  8.     if (p_MCB->isr_st == 1) {
  9.       /* A task is locked waiting to send message */
  10.       p_MCB->isr_st = 2;
  11.       rt_psq_enq (p_MCB, 0);
  12.       rt_psh_req ();
  13.     }
  14.     rt_dec (&p_MCB->count);
  15.     if (++p_MCB->last == p_MCB->size) {                        //1
  16.       p_MCB->last = 0;                                                        //1
  17.     }
  18.     return (OS_R_MBX);
  19.   }
  20.   return (OS_R_OK);
  21. }
复制代码


在这里直接操作了邮箱内容,个人觉得将会有问题产生,尤其是那些读修改写内容,我将其标为//1

出0入0汤圆

 楼主| 发表于 2014-6-11 13:00:45 | 显示全部楼层
由于rtx的mailbox使用了分开的读写计数器,因此以上isr_mbx_receive 与发送相关的程序基本不会造成冲突,但是将与rt_mbx_wait产生冲突,冲突的地方如下
  1. OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
  2. ...
  3.   if (p_MCB->count) {
  4.     *message = p_MCB->msg[p_MCB->last];           //这语句之间发生中断调用isr_mbx_receive
  5.     if (++p_MCB->last == p_MCB->size) {
  6.       p_MCB->last = 0;
  7.     }
  8.     if (p_MCB->p_lnk != NULL) {
  9.       /* A task is waiting to send message */
  10.       p_TCB = rt_get_first ((P_XCB)p_MCB);
  11.       p_TCB->ret_val = OS_R_OK;
  12.       p_MCB->msg[p_MCB->first] = p_TCB->msg;
  13.       if (++p_MCB->first == p_MCB->size) {
  14.         p_MCB->first = 0;
  15.       }
  16.       rt_rmv_dly (p_TCB);
  17.       rt_dispatch (p_TCB);
  18.       os_tsk.run->ret_val = OS_R_OK;
  19.     }
  20.     else {
  21.       rt_dec (&p_MCB->count);
  22.     }
  23.     return (OS_R_OK);
  24.   }
  25. ...
  26. }
复制代码

与isr_mbx_receive基本类似的这段代码将会产生错误,是不可重入的,在以上注释处即可触发一次冲突

出0入0汤圆

 楼主| 发表于 2014-6-11 13:03:55 | 显示全部楼层
产生错误的原因,我看就是对这个p_MCB->count计数值判断需要互斥访问操作,具体怎么做我还没想好

出0入0汤圆

发表于 2014-6-11 13:25:34 | 显示全部楼层
myxiaonia 发表于 2014-6-7 16:25
奇怪的是  为何svc中断要比pendsv和SYSTICK高一级呢,我觉得同级也没问题啊

我之前回复过的,SVC的优先级是需要保证为整个系统里面最高的(除掉复位和NMI,他们的优先级是负的),这个是由硬件保证的,遇到SVC指令的时候如果因为优先级的问题得不到执行,直接上访成硬fault。
刚刚又翻书确认了一下,确实是这样,在CM3权威指南129页,真诚的建议LZ再看看这个书。反正我是常看常新,很多内容记下来日常写程序也方便的多。

多说一句,SVC+PSV的模式实际上可以想象成系统中所有的异常都按照优先级列表,SVC在最上面,PSV在最下面,OS通过SVC把需要立即处理的任务马上调出来处理掉,可以滞后的加入任务队列让PSV一件一件取出来执行掉。在两者之间是用户可以自由配置的其他异常(中断)。
而且这些都是异常需要运行在特权级,普通线程级代码又是一级,整个系统是一级一级隔离开的,OS的交互都是通过API完成的。(而且写的好麻烦

出0入0汤圆

 楼主| 发表于 2014-6-11 23:08:40 | 显示全部楼层
本帖最后由 myxiaonia 于 2014-6-12 19:35 编辑
error_dan 发表于 2014-6-11 13:25
我之前回复过的,SVC的优先级是需要保证为整个系统里面最高的(除掉复位和NMI,他们的优先级是负的),这 ...


兄弟啊,正如你所说,每次遇上问题回头去看看权威指南,总是有新的收获新的认识,比如这个svc问题,我网上也找过,这个权威指南上这个地方也是关注了好久

我总结了下,svc的不可屏蔽性只体现在其不可以错误的使用,也就是在不小于svc中断优先级的中断例程中是不可以调用的,否则用法fault,其原因是因为此时svc指令是未定义的(引用自ARMv7-M Architecture Reference Manual)

但是高优先级中断可以抢占

svc就是在用户态程序中调用的,此时必定可以正常陷入异常,即使此时正好来一高优先级中断,我想也不会产生用法fault,svc在中断例程中调用是必须小心的,实际上也应该尽量避免,rtx内核服务避免了这个问题


权威指南中确实提到svc不能被挂起,但是其紧接着一个括号解释,是因为用户程序希望立刻调用系统服务,这仅仅是对以上原因的总结,只是把这种极端例外的情况没有列出罢了

——————一以下内容修改自6月12号—————————
在rl手册中usage hints一节看到如下说法
The lowest two pre-emption priorities are reserved for RTX kernel, all remaining pre-emption priorities are available to use in your application
很明显svc不会是最高优先级,呵呵

Allowed values for PRIGROUP are from 0 to 6. The PRIGROUP value 7 will cause RTX to fail
我在rtx blink这个例程中,软件仿真,故意设为7,也就是没有抢占优先级,貌似也没有错误嘛,官方文档到底是何意?

出0入0汤圆

 楼主| 发表于 2014-6-11 23:47:03 | 显示全部楼层
本帖最后由 myxiaonia 于 2014-6-11 23:51 编辑
myxiaonia 发表于 2014-6-7 16:25
奇怪的是  为何svc中断要比pendsv和SYSTICK高一级呢,我觉得同级也没问题啊


我在ARM v7-M Architecture  Reference Manual 这里找到了一个证据,表明svc和pensv可以都用最低优先级即可完成相同功能,
P438有如下描述

SVCall, PendSV and critical region code avoidance
Context switching typically requires a critical region of code where interrupts must be disabled to avoid
context corruption of key data structures during the change. This can be a severe constraint on system design
and deterministic performance. ARMv7-M can support context switching with no critical region such that
interrupts never need to be disabled.
An example usage model supporting crit ical region avoidance is to confi gure both SVCall and PendSV with
the same, lowest exception priority.
SVCall can be used for supervisor calls from threads, and PendSV can
be used to handle context critical work offloaded from the exception ha ndlers, including the equal priority
SVCall handler. Because SVCall and PendSV have the same execution  priority they will never pre-empt
each other, therefore one will always process to completion before the other starts. SVCall and PendSV
exceptions are always enabled, which means they will  each execute at some point  once all other exceptions
have been handled. In addition, the associated exception handlers do not need to check whether they are
returning to a process on exit with this usage model, as the PendSV exception will occur when returning to
a process.
The example has all context switch requests issued by setting PendSV to Pending, however, both SVCall
and PendSV exceptions can be used  for context switching because they do not interfere with each other.
While not the only usage model, support of critical region software avoi dance is a key feature of ARMv7-M,
specifically the support provided by the SVCall and PendSV exception specifications.

此例程也顺带表明了svc确实不需要用最高优先级

出0入0汤圆

发表于 2014-6-12 01:09:24 | 显示全部楼层
中断,系统服务,都是属于系统级的,与用户线程级是完全隔离的。
所有OS都是这设计的。
目前来看,大部分的os,把应用代码分为2部分:用户线程、系统服务。

SVC调用,就是系统服务,其它中断,也是系统服务。

就你的问题,虽然可以在中断中发送和接收邮件,但中断处理程序不是线程,所以不能等待,所以也不能挂在IPC的等待线程队列中。
RTX中,所有以isr_开头的IPC函数,都是专门提供给中断处理程序用的。
os_开头的IPC函数,才是提供给用户线程用的。

作为常识,中断处理函数要尽可以的短,处理速度就尽可能的快。



出0入0汤圆

 楼主| 发表于 2014-6-12 12:41:58 | 显示全部楼层
本帖最后由 myxiaonia 于 2014-6-12 12:46 编辑
myxiaonia 发表于 2014-6-11 13:03
产生错误的原因,我看就是对这个p_MCB->count计数值判断需要互斥访问操作,具体怎么做我还没想好 ...


事情远比我想的复杂,发生冲突的情况我简单列了下,就是中断抢占的几种情况
SVC 0  被ISR抢占
PENDSV  被ISR抢占
ISR  被ISR抢占
,这其中PENDSV  被ISR抢占问题可能不大,原因是PENDSV 只处理邮箱发送,之前提到发送和接收不会互相冲突
其余两种情况都是很现实的问题


如果最后还是无法解决问题,就只好把调用isr_mbx_receive的中断优先级都不大于SVC的方法来实现内核服务的互斥访问了,不会抢占就可以保证线程安全

出0入0汤圆

 楼主| 发表于 2014-6-12 13:21:52 | 显示全部楼层
myxiaonia 发表于 2014-6-12 12:41
事情远比我想的复杂,发生冲突的情况我简单列了下,就是中断抢占的几种情况
SVC 0  被ISR抢占
PENDSV  被 ...

操了,在keil官网论坛随便一搜有关mailbox的问题,就搜出一个来,看来这个问题早就出现了,不知道keil是以什么样的态度来对待这个问题

RTX isr_mbx_send()  这个还是09年的帖子

他说两个背靠背的isr调用,也就是isr中断isr的情况,出现了问题,而手册中也没有对isr_mbx_send使用作出任何限制

出0入0汤圆

 楼主| 发表于 2014-7-3 14:58:10 | 显示全部楼层
算了,邮箱这个问题,不再考虑了,要想改造好isr_mbx_receive,估计相关操作全部都要互斥访问,实在是太麻烦太低效了,保证调用isr_mbx_receive的中断优先级为最低即可,否则出错是无法避免的

出0入0汤圆

 楼主| 发表于 2014-7-17 13:00:06 | 显示全部楼层
error_dan 发表于 2014-6-7 13:14
CMSIS那层皮一蒙就啥都没了,我就是坑在这里的,后来发现要去自己包含OS的各种模块,就没搞了.
SVC的中断优 ...

我已经写了一部分的rtx笔记了,error_dan兄还没有过来看看哈,多多指教啊
RTX学习笔记

出0入0汤圆

 楼主| 发表于 2014-7-19 16:08:39 | 显示全部楼层
myxiaonia 发表于 2014-6-11 23:47
我在ARM v7-M Architecture  Reference Manual 这里找到了一个证据,表明svc和pensv可以都用最低优先级即 ...

在另一个帖子RTX 学习笔记中,我已经确认了SVC必须要能够抢占SYSTICK,间接导致SVC也比PENDSV高一级
不过和此文引用的内容并不冲突,如果没有SYSTICK,SVC就可以和PENDSV同优先级

出0入0汤圆

发表于 2014-7-19 18:23:38 | 显示全部楼层
似乎cortex-m上的rtos一般都利用SVC

出0入0汤圆

 楼主| 发表于 2014-7-19 19:33:35 | 显示全部楼层
liurangzhou 发表于 2014-7-19 18:23
似乎cortex-m上的rtos一般都利用SVC

大多数通用rtos都不用的,只有专门针对cm3才是,更有现代rtos的特征

出0入0汤圆

发表于 2014-10-26 16:46:33 | 显示全部楼层
本帖最后由 ycysky 于 2014-10-26 16:57 编辑

楼主,您好!最近我在学用ardence rtx8.1 在vc6.0下开发pcie板卡的驱动,驱动用的rtx下的应用程序的方式写的,即后缀是.rtss,在rtx应用程序中可调用这些驱动函数,通过windows的程序启动rtx应用程序后,中断挂接正常,而且板卡上产生中断时能够进入中断处理线程,但是在中断处理线程中对板卡上的中断标志进行清除时,无法一次性操作成功,而是出现多次进入中断且进入次数不确定(最终中断标志能够清除)。不知您对这块熟悉不,烦请不吝赐教

出0入0汤圆

 楼主| 发表于 2014-10-26 19:54:21 | 显示全部楼层
ycysky 发表于 2014-10-26 16:46
楼主,您好!最近我在学用ardence rtx8.1 在vc6.0下开发pcie板卡的驱动,驱动用的rtx下的应用程序的方式写 ...

兄弟,你说的是windows改造成实时系统的rtx,我所说的arm的mcu用的一个rtos,两者是不同的。。。

我对你所说的系统毫无研究啊

出0入0汤圆

发表于 2014-10-26 22:54:24 | 显示全部楼层
还是非常感谢

出0入0汤圆

发表于 2015-8-20 10:54:56 | 显示全部楼层
你好,

SVC 0调用内核服务,外设中断调用内核服务因PENDSV优先级较低无法抢占而被挂起,线程安全得以保证。。。。,

这句话可以这么理解么?SVC调用使用的是特权模式PSP,中断调用使用的是特权模式MSP,以此来保证线程安全。

出0入0汤圆

 楼主| 发表于 2015-8-20 11:04:59 | 显示全部楼层
macaroni 发表于 2015-8-20 10:54
你好,

SVC 0调用内核服务,外设中断调用内核服务因PENDSV优先级较低无法抢占而被挂起,线程安全得以保证 ...

理解是对的。。。不过svc中断也是使用的msp,包括用户svc函数,只不过函数传递的参数需要从psp从取和写回,比较绕。。。用户svc函数等于也是使用的msp,使用时务必注意这一点

出0入0汤圆

发表于 2015-8-20 11:17:19 | 显示全部楼层
myxiaonia 发表于 2015-8-20 11:04
理解是对的。。。不过svc中断也是使用的msp,包括用户svc函数,只不过函数传递的参数需要从psp从取和写回 ...
  1.         /*------------------- User SVC ------------------------------*/

  2. SVC_User
  3.         PUSH    {R4,LR}                 ; Save Registers
  4.         LDR     R2,=SVC_Count
  5.         LDR     R2,[R2]
  6.         CMP     R1,R2
  7.         BHI     SVC_Done                ; Overflow

  8.         LDR     R4,=SVC_Table-4
  9.         LDR     R4,[R4,R1,LSL #2]       ; Load SVC Function Address

  10.         LDM     R0,{R0-R3,R12}          ; Read R0-R3,R12 from stack
  11.         BLX     R4                      ; Call SVC Function

  12.         MRS     R12,PSP                                                                        // 用户代码返回是不是已经做好了MSP到PSP的转换,我懂汇编,因此我不是很确定。
  13.         STM     R12,{R0-R3}             ; Function return values
  14. SVC_Done
  15.         POP     {R4,PC}                 ; RETI

  16.         ALIGN
复制代码


其次,如果SVC也使用MSP,如何保证中断中的函数不会破坏内核堆栈呢?如果在中断中调用用户函数,造成了堆栈溢出或者越界之类的。是不是在中断使用过程中必须严格限制仅能运行内核中前缀为isr的函数?

非常感谢您的解答。

出0入0汤圆

 楼主| 发表于 2015-8-20 11:24:50 | 显示全部楼层
本帖最后由 myxiaonia 于 2015-8-20 11:30 编辑
macaroni 发表于 2015-8-20 11:17
其次,如果SVC也使用MSP,如何保证中断中的函数不会破坏内核堆栈呢?如果在中断中调用用户函数,造成了 ...


所以我说要特别注意用户定义svc函数的问题。。。你要记住在里面调用的函数都是使用msp了,如果内部乱七八糟调用一堆用户自己的函数很容易把主栈搞穿了,而且这也不是被推荐的

中断函数请务必短小。。。用户svc函数是中断调用的函数,没有特别的必要不要使用用户svc函数

isr_的内核函数从本质看是可以在用户svc中调用的,并没有说一定要调用或者只能isr_内核函数,你只需要知道用户svc函数是在svc中断运行的,有哪些东西一定要到svc中运行你必须清楚,没事不要用svc函数:一般都是保证原子性操作,互斥访问,访问临界区资源,mcu内核规定只能在特权态或者中断态执行的内容
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 01:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表