fans-rt 任务调度-堆栈切换篇(2)堆栈模型

原创 2015年07月08日 22:13:03

前面我们提到,任务的切换就是堆栈的切换(当然首先是任务上下文的切换),也通过代码简单的描述了堆栈切换的切换过程。但是,要成功从一个任务切换到另一个任务还必须了解CPU当前运行模式下,中断处理时的特性。例如,进入堆栈时会保存哪些寄存器,CPU是否支持硬件双堆栈(甚至更多层次的堆栈),如果支持多层堆栈,那么在进入中断前,外层堆栈保存哪些寄存器,内层堆栈保存哪些寄存器,是否会将外层堆栈指针保存在内层堆栈中等等,这些特性决定断点现场的状态,也决定了操作系统代码在进行任务切换前需要将哪些不会被CPU自动保存的寄存器入栈,以及创建新任务时如何初始化新任务的堆栈。

在 fans-rt 源码路径的 /platform/board/stm32 下有5个子文件夹,这5个文件夹中都存在一个 kboard_interrupt.s 文件,每个文件的文件头注释中都有一段配置描述:

;    Configuration:
;     System global core stack                  YES/NO
;     The local core stack of general task      YES/NO
;     The loacl core stack of kernel task       YES/NO
;     The local user stack of general task      YES/NO
;     Hardware supported task switch IRQ        YES/NO
;     Hardware supported double stack           YES/NO
这是关于CPU堆栈模型的配置描述,这些配置与CPU特性相关,直接影响堆栈切换代码的实现。每个项描述对的含义以及影响如下:

第一项:系统全局内核栈

表明是否支持系统全局内核栈,如果该项为YES,则表明系统中只有一个内核堆栈,所有普通任务使用同一个内核堆栈(系统中同时只有一个任务能够请求内核功能,如果任务正在内核中执行,必须在内核功能执行完成,从软中断上下文返回任务时才能执行任务切换),实际上cortex-m3正好支持这种堆栈模型,CPU提供MSP和PSP两个堆栈指针,发生中断时自动从用户态的PSP切换到MSP,全局内核栈的好处是所有任务共享一个内核栈,内核的最大堆栈深度是可预估的,而不同的任务在非特权层执行的代码需要的堆栈容量不同,可以单独为每个任务配置不同的用户栈大小,这样既起到了对内核的保护作用,也可以避免需要大量任务的环境在堆栈空间上的浪费。

第二项:普通任务局部内核栈

表明系统是否支持每个任务一个内核栈,实际上cortex-m3硬件上并不能直接支持这种模型,因为cortex-m3硬件实现上并没有支持任务的概念,不能支持自动重载MSP,/platform/board/huge 中的代码是通过软件方式实现的。具备局部内核栈的堆栈模型在X86的CPU上可以得到支持,X86提供了一个称为任务状态段(TSS)的结构,通过装入TSS可以获得任何任务从 ring0-ring3 不同特权层的堆栈指针,并且硬件支持任务堆栈指针的自动切换。

第三项:内核任务局部内核栈

表明系统是否需要支持内核任务,所谓内核任务是指具备特权级的任务,任务在执行时可以访问内核能够访问的所有资源,此类任务是为后续驱动模型设计时预留(也许用不到,我希望能够将除系统服务之外的所有功能放到用户层实现),内核任务的堆栈初始化方法和普通任务不同(参考源码路径/platform/arch/stm32/karch-stack.c中的函数 CORE_FillStack),内核任务的中断返回LR值为0xfffffff9,普通任务返回用户层的LR值为0xfffffffd(X86上通过iretd指令获得ss和cs寄存器,并通过ss和cs的CPL确定返回的代码段的特权级)。内核任务在发生中断时,不进行堆栈切换,从中断返回时也不进行堆栈切换。

第四项:普通任务局部用户栈

表明系统是否支持局部用户栈(没有全局用户栈),如果支持局部用户栈,那么系统一定支持双堆栈,普通任务执行过程中发生中断时,需要将堆栈从用户栈切换到内核栈(软件实现切换或者硬件自动切换)。如果不支持局部任务用户栈,则所有任务均使用内核栈(每个任务一个内核栈),均拥有内核特权级,可以访问所有内核资源。该中断模型出现在不支持特权级的CPU平台上,例如intel 8086/8088。在小容量的cortex-m3芯片上支持该中断模型,对于极少任务需求的环境可以节省堆栈上的开销。

第五项:硬件支持任务切换

实际上就是指是否支持类似cortex-m3的PendSV中断,PendSV属于CPU平台的特性,不是所有平台都支持此类中断。如果支持,那么PendSV中断的出入栈方式和其他中断的出入栈方式不同。在此模型下,PendSV中断需要对所有CPU寄存器压栈,但其他中断可以只对使用到的寄存器压栈,因为其他中断中不会发生任务上下文切换,不需要构建任务切换场景的断点堆栈状态。

第六项:硬件支持双堆栈

就像cortex-m3能够有MSP/PSP,发生特权级变化时,自动进行堆栈切换。如果硬件不能支持双堆栈,而软件希望使用双堆栈以减少大量任务环境上堆栈对内存的开销,那么可以通过在中断服务程序的代码中实现软件堆栈切换(例如 /platform/board/stm32/soft的实现)。在进行堆栈切换前,中断处理程序先将当前任务的CPU寄存器保存到外层栈,然后切换到内层栈再调用中断服务程序,返回时取出保存在任务上下文中的外层栈指针,从外层栈恢复CPU寄存器,然后返回任务断点继续执行。

fans-rt 与堆栈相关的有六项配置,但这六项配置可以组合出很多种环境,而fans-rt在cortex-m3上实现了5种常见的环境,实际上这5种环境在cortex-m3上并不是都有意义,实现他们的目的只是为了验证当前fans-rt的内核代码在任务切换部分能否支持各种单片机硬件形态。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

fans-rt 任务调度-堆栈切换篇(4)tiny模型详细分析

优化后的Tiny模型代码: ; ; Copyright(C) 2013-2015, Fans-rt development team. ; ; All rights reserved. ...
  • sevek
  • sevek
  • 2015年07月11日 23:32
  • 260

μC/OS-II与RT-Thread对比——任务调度

在任务调度器的实现上,μC/OS-II和RT-Thread都采用了位图调度(bitmap scheduling),任务优先级的值越小则代表具有越高的优先级,主要区别在于实现形式,是采用多级队列的形式,...

μC/OS-II与RT-Thread对比——任务调度

在任务调度器的实现上,μC/OS-II和RT-Thread都采用了位图调度(bitmap scheduling),任务优先级的值越小则代表具有越高的优先级,主要区别在于实现形式,是采用多级队列的形式,...
  • hcx25909
  • hcx25909
  • 2014年04月17日 19:53
  • 13257

μC/OS和RT-Thread任务调度详解

在任务调度器的实现上,μC/OS-II和RT-Thread都采用了位图调度(bitmap scheduling),任务优先级的值越小则代表具有越高的优先级,主要区别在于实现形式,是采用多级队列的形式,...

UCOS任务调度模型的分析与改进

  • 2009年06月25日 18:04
  • 212KB
  • 下载

任务调度(uCOS2)

  • 2013年01月06日 15:28
  • 462KB
  • 下载

任务调度与上下文切换时间测试

创建两个进程(实时进程)并在它们之间传送一个令牌,如此往返传送一定的次数。其中一个进程在读取令牌时就会引起阻塞。另一个进程发送令牌后等待其返回时也处于阻塞状态。发送令牌带来的开销与上下文切换带来的开销...

1、表达式求值问题 2、任务调度

  • 2017年11月10日 07:26
  • 229KB
  • 下载

uCOS中任务调度时的上下文切换

这里以STM32处理器为例,也就是Cortex-M3内核。 所谓的上下文切换呢,就是当 uC/OS转向执行另一个任务的时候,它保存了当前任务的CPU 寄存器到堆栈。并从新任务的的堆栈中 CPU ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:fans-rt 任务调度-堆栈切换篇(2)堆栈模型
举报原因:
原因补充:

(最多只允许输入30个字)