有了Systick中断为什么还要PendSV中断?

文章目录

  • 问题:
  • 原因:
    • 1.在SysTick中断里完成任务切换会降低操作系统的实时性:
  • 2.把systick优先级设置为最高把PendSV设置为最低的好处:
  • 3、结语:

问题:

看过Cortex-m3/m4操作系统RTOS内核代码的伙伴们都知道,OS中的任务调度实现方式如下:
1、开启SysTick中断,也就是系统滴答定时器中断。然后在SysTick中断中触发PendSV中断,实际的任务切换是在PendSV的中断服务函数中完成的。
2、PendSV的中断服务函数一般用汇编来写。
那为什么不直接在SysTick的中断服务函数里完成任务切换呢?
其中原因如下:

原因:

1.在SysTick中断里完成任务切换会降低操作系统的实时性:

首先我们需要了解Cortex-m3/m4内核的中断和优先级。内核共有256个中断优先级,并且前16个中断分配给了系统内核异常中断,因此外设中断只能排在前16个以后,因此外部中断最多只能有256-16=240个。比如中断0的异常号是16。
有了Systick中断为什么还要PendSV中断?_第1张图片
有了Systick中断为什么还要PendSV中断?_第2张图片

系统内核发生异常时会触发中断,内核的异常情况如下:
有了Systick中断为什么还要PendSV中断?_第3张图片
其中外部中断的优先级有中断优先级配置寄存器,因为外部中断最多只能有256-16=240个,因此外部中断优先级寄存器有240个。看下图可知,确实有240个寄存器控制着外部240个中断的中断优先级。
有了Systick中断为什么还要PendSV中断?_第4张图片
而内部系统异常中断的中断优先级则不在这个寄存器里面,而是单独的一块寄存器来保存内部中断的中断优先级:
有了Systick中断为什么还要PendSV中断?_第5张图片
有了这些知识,我们就可以回答为什么不在systick中断里面进行操作系统任务切换了。

假设在systick里面,即要保证系统的心跳(也就是系统的时间,或者说节拍),也进行任务切换。那么就必须把systick的中断优先级设置为最低,因为有其他外中断时,是不能进行任务切换的。

如果不把systick的优先级设置为最低,而是设置为最高,1ms执行一次。有个串口中断,执行一次需要5ms。
在0ms时刻,系统初始化完成。

在0.5ms时刻,来了一个串口中断,

在1ms时刻,systick发起中断请求,因为systick中断优先级比串口中断优先级高,systick就会抢占串口中断并执行任务切换函数,而任务切换需要占用一定的时间,等任务切换执行完毕后,程序指针就已经改变为下一个任务的地址了,就没法再回到串口中断服务函数里面了。因此切换任务时需要关闭所有中断。

而如果把systick的优先级设置为最低,确实可以解决有其他中断时不执行任务切换。但是这样就没法保证系统的时钟了。
假设systick每1ms执行1次,而有个串口中断执行一次要5ms。

在0ms时刻,系统初始化完成。

在0.5ms时刻,进了串口中断。

在1ms时刻,systick发出中断请求,但是因为systick优先级比较低,无法抢占串口中断,只有等5ms时刻串口中断退出,才会进入systick中断。

在5ms时刻,串口中断执行完毕,此时进入systick中断。在systick中断里面会把系统时间+1,认为现在系统时间为1ms,但实际此时的系统时间是5ms,这样整个实时系统的时间就全部不准确了。而如果有6个串口中断,那么systick计数的时间很可能每30ms才计数1下,这对于实时系统是根本无法接受的。
有了Systick中断为什么还要PendSV中断?_第6张图片

2.把systick优先级设置为最高把PendSV设置为最低的好处:

用systick的高优先级来保证操作系统时间的正确性,而用最低优先级的PendSV来保证不会在有其他中断时进行任务切换。我们还来演绎一下:
假设有个串口中断,systick优先级为最高,1ms进一次。PendSV优先级为最低,会在systick中触发PendSV中断,则无其他中断时,PendSV也是1ms执行一次。串口中断依然是执行一次需要耗时5ms。

在0ms时刻,系统初始化完成。

在0.5ms时刻,进了串口中断。

在1ms时刻,systick发起中断请求,因为systick优先级为最高,则systick会抢占串口中断。在systick中完成系统时钟+1,然后就立即退出了systick。整个systick函数执行很快,只需要对一个数+1,并且将pendsv触发位置为1即可。退出systick后程序会返回到串口中断函数里面,此时pendsv也发起了中断请求。但因为pendsv优先级为最低,因此不能抢占串口中断。

到5ms时刻时,systick已经计数了5次,保证了操作系统的时钟没错误。此时串口中断函数执行完毕,退出串口中断服务函数。如没其他中断,就会执行优先级最低的pendsv中断,在pendsv中断里执行任务切换。

虽然5ms才执行了pendsv一次,但是因为systick依旧是1ms执行一次,因此各任务的检测到的时间也都是5ms,没有错误,因此保证了实时操作系统的实时性。

3、结语:

因此在配置操作系统时,要把systick配置为优先级最高,把pendsv配置为优先级最低。

以上是我画了很长时间琢磨出来并且验证了的,有帮助的话还麻烦点个赞,收藏一下!!!^~^

你可能感兴趣的:(嵌入式软件开发)