【编写自己的RTOS】先理清楚几个基本问题

一个RTOS具有的基本功能

 1. 任务调度策略
 2. 内存管理
 3. 中断处理
 4. 共享资源的访问

1、理解几个基本问题:

Q1: RTOS最主要的特性(优势)是什么?
A1: 实时性,不同以往的前后台系统的轮询调度方法,RTOS通过CPU调度使得多个任务并发处理,每个任务都能得到更快的响应。

补充
.前后台系统:单任务系统,应用程序基本都放在一个大循环while(1)中,有时需要在中断中完成一些处理。中断服务函数即为前台程序,while(1)即为后台程序。
.轮询:由CPU定时发出询问,依序询问每一个任务是否需要其服务,有即给予服务,服务结束后再问下一个任务。
前后台系统中,各个任务都是排队等待执行的,只有轮到这个任务,它才能执行;实时性很差。

Q2:为什么RTOS能够并发处理多个任务?
A2:处理器在任一时刻只能执行一个任务。但通过快速的任务切换,一个多任务操作系统可以使它看起来好像每个任务并行执行一样。

关于并行与并发的解释(来自知乎):

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。

Q3:编写自己的RTOS,首先要解决哪些核心问题
A3:
 a. 系统心跳:SysTick初始化
 b. SysTick和PendSV的优先级设置
 c. 任务控制块TCB结构与堆栈初始化
 d. 上下文切换:PendSV_Handler函数
 e. 系统延时函数(阻塞,调度)
 f. 任务调度:SysTick_Handler函数


2、了解Cortex-M3

寄存器组
 在这里插入图片描述

1、R0-R12 通用寄存器
R0-R12都是32位通用寄存器,用于数据操作。
但是注意,绝大多数16位thumb指令只能访问R0-R7,
而32位thumb-2指令可以访问所有寄存器。
    
2、Banked R13: 两个堆栈指针
Cortex-M3有两个堆栈指针,它们是banked,所以任一时刻只能使用其中之一。

MSP: 复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程
PSP: 由用户的应用程序代码使用
(堆栈的最低两位永远是0,这意味着堆栈问题4字节对齐的)

在ARM编程领域,凡是打断程序顺序执行的事件,都被称为异常。除了外部中断,当有指令执行了“非法操作”,或访问被禁的内存区间,因各种错误产生的fault,以及不可屏蔽中断发生时,都会打断程序的执行,这些情况统称为异常。


3、怎么进行任务切换:

任务切换时,我们需要保存任务运行环境(xPSR,PC,LR,R0-R12这16个寄存器)到任务堆栈,以便下次恢复运行。

Cortex-M3有两个堆栈指针,但同时刻只能使用一个,我们可以用一个来作为任务切换时保存“上下文”。

任务切换流程:从A任务切换到B任务,把任务A运行时的寄存器参数入栈,保存到任务A的栈中;再把任务B栈里的内容出栈处理,最后让程序计数器PC指向任务B( PC指向哪儿,处理器就去哪 )。

《Cortex-M3权威指南》给我们的提示:

在系统中使用双堆栈
CM3的出现,让单片机业界也能出双枪李向阳。v7-M架构的一个重要能力,就是提供了这个双堆栈的设计,允许把用户应用程序的堆栈与特权级/操作系统内核的堆栈分开。(如果再辅以MPU,还能进一步地阻止用户程序访问内核的堆栈,同时也消除了内核数据被破坏的可能。)

要在CM3中创建可靠扛打的系统,必须两手抓,两手都要硬。典型地,一个真正健壮的CM3软件系统都要使用RTOS内核的,其通常会符合如下的要求:
a. 服务例程使用MSP
b. 尽管异常服务例程使用MSP,但是它们在形式上返回后,内容却可以依然继续—而且此时还能使用PSP,从而实现“可抢占式的系统调用”,大幅提高实时性能。
c. 通过SysTick,实时内核的代码每隔固定时间都被调用一次,运行在特权级水平上,负责任务的调度、任务时间管理以及其它系统例行维护。
d. 用户应用程序以线程的形式运行,使用PSP,并且在用户级下运行
e. 内核在执行关键部件的代码时,使用MSP(在辅以MPU时,MSP对应的堆栈只允许特权级访问)

假设系统内存是一块SRAM,则我们可以通过MPU,把它分为两个regions,其中一个用于用户级,另一个用于特权级。另外,CM3的堆栈是“向下生长的满栈”,因此需要把这两个SP初始为指向两个regions的顶端。

关键点

SysTick中断,周期性地把执行点转入操作系统,从而使例行的系统管理以及必要轮转调度得以维持(SysTick作为系统“心跳”)
②CM3的堆栈是“向下生长的满栈”。


关于上下文切换的提示:

PendSV(可悬起的系统调用),它和SVC协同使用。一方面,SVC异常是必须得到响应的(若因优先级不比当前正处理的高,或是其它原因使之无法得到响应,将上访成硬fault),应用程序执行SVC时都是希望所需的请求立即得到响应。另一方面,PendSV则不同,它是可以像普通的中断中断一样被悬起(不像SVC那样会上访)。

OS可以利用它“缓期执行”一个异常—直到其它重要的任务完成后才执行动作。悬起PendSV的方法是:手工往NVIC的PendSV悬起寄存器中写1。悬起后,如果优先级不够高,则将缓期等待执行。(PendSV优先级设为最低)

PendSV的典型使用场合是在上下文切换时(在不同任务之间切换)。例如一个系统中有两个或多个就绪的任务,上下文被触发的场合可以是:
a. 执行一个系统调用
b. 系统滴答定时器(SysTick)中断(转轮调度中需要)


下一篇:【编写自己的RTOS】搞定任务调度

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值