type
status
password
date
slug
summary
category
URL
tags
icon
1. 前后台系统结构
1.1 概述
- 前后台结构实现为主循环 + ISR,我们需要自己实现主循环并处理ISR与主循环之间的交互
- 如果中断要处理的事情很简短,可以在ISR中完成;如果时间要处理的事情较多,则返回后台程序处理
1.2 前后台系统存在的问题
1.2.1 实时性不能保证
实时性不能保证,事件可能无法得到及时处理。示例中在处理flag1事件时延时2秒,会影响对flag2事件的处理
1.2.2 CPU利用率不高
存在CPU空转的情况,CPU利用率不高
说明:上述CPU空转就是因为当前要操作的资源尚未准备好,但是前后台系统又无法去处理其他事务
1.2.3 编程思维不自然
强迫人按照机器的顺序工作方式思考编码。当执行的任务越多,代码结构越复杂,编码难度越大。
不能并行处理,只能顺序处理
2. RTOS原理及功能简介
2.1 概述
RTOS是一种通用的任务管理框架,用于控制任务的运行和任务之间的交互,保证事件得到实时处理。RTOS的三要素:实时性 + 操作系统 + 嵌入式
- 实时性:在规定的时间内对事件进行响应的软件,实时并不意味着快
- 操作系统:提供任务管理和协调的控制功能的系统软件
- 嵌入式:运行于特定的嵌入式硬件,功能可裁剪、代码可移植
2.2 RTOS与前后台结构的比较
① RTOS相当于实现了后台的主循环,并能够处理ISR与主循环的交互
② 使得用户可以只考虑任务的设计
③ RTOS还提供了各种组件用于实现任务间交互及其他控制管理功能(e.g. 存储管理)
2.3 工作原理简介
2.3.1 提供任务概念
提供多个执行流,虽然实际只有一颗CPU,但通过"虚拟化",每个Task好像独占CPU。task可以认为自己独占一颗CPU,所以可以实现为一个死循环。而CPU上实际的执行流,会由于操作系统的控制,在不同task之间进行切换。这样既简化了task的设计,也充分利用了CPU。
这就引入了一个问题,即"操作系统的控制"本身在实现上也是一段代码,那么这段代码在什么时机运行呢 ? 其实就是在中断或者task主动交出CPU控制权的时候(e.g. task调用可能导致阻塞的函数)
2.3.2 提供任务调度机制
通过RTOS控制任务的运行时机,事件处理的实时性得到有效保证
说明1:一般中断ISR只会进行简短的预处理,而将耗时的操作交给task来执行。RTOS可以确保在ISR执行完成后,立即调度ISR的后续task执行(当然,这需要task优先级的保障)
说明2:ISR后续task在运行时,如果需要等待资源,RTOS会调度其他task执行
说明3:高优先级task可以抢占低优先级task
2.3.3 提供资源管理与通信组件
提供一些组件用于简化任务对资源的访问,事件的处理,以及任务之间的通信,有效降低任务之间的代码耦合
2.4 总结
下图体现了RTOS相对于前后台系统的优势
3. 调试工具使用
RTOS原理与实现01:芯片内核简介
5. 内核编程实践
5.1 需求说明
触发PendSV异常,在异常处理函数中,保存R4 ~ R11寄存器到缓冲区,再恢复R4 ~ R11寄存器,以模拟任务切换时的寄存器保存与恢复
5.2 代码说明
5.2.1 寄存器操作
说明1:中断控制状态寄存器设置该寄存器的bit 28即可将pendSV中断挂起,当没有更高优先级的中断需要处理时,将进入pendSV中断的ISR运行
说明2:系统处理器优先级寄存器pendSV中断为第14号中断,由于可以按字节访问NVIC寄存器,所以将0xE000ED22设置为0xFF即可将pendSV中断设置为最低优先级
5.2.2 triggerSV函数说明
triggerPendSV函数的作用就是先将pendSV中断的优先级设为最低,然后触发该中断,用于模拟请求任务切换的场景
5.2.3 main函数说明
5.2.4 PendSV_Handler函数说明
说明1:PendSV_Handler函数名该函数为pendSV异常的ISR,之所以使用该函数名,是因为在Keil初始化环境中将pendSV的异常向量设置为PendSV_Handler
说明2:缓冲区指针的维护先来说明一下缓冲区的定义方式,如此便可理解加载缓冲区地址的操作了,之所以可以通过第2次{ LDR R0, [R0] }可以获取stackPtr指针变量的值,是因为stackPtr是BlockType_t结构的第1个成员,而C语言要求结构体变量的首地址与其第1个成员的首地址相同
说明3:EXC_RETURN值的设置响应pendSV异常时,LR的值被设置为0xFFFFFFF9,即异常返回时进入线程模式且使用MSP(线程模式 + 特权级)这是因为系统启动时默认为线程模式 + MSP,而中断返回是默认返回中断触发前的运行状态