### 什么是零中断延迟
零中断延迟并非是中断的响应时间为零,而是指当引入了RTOS以后,中断的响应时间仍然能够达到MCU内核特性的响应时间,即只要中断发生,就能按中断优先级立即抢占,绝不延误。也就是说,中断响应时间不受RTOS影响,与裸机编程是一样的。
### CosyOS-实时运行模型
* **中断层** 【用户中断按中断优先级实时抢占、零中断延迟】
* **用户中断**
**->** 中断本地服务的执行
**->** 中断挂起服务的装载
* **服务层** 【内核服务】
* **SysTick** [minpri]
**->** 软件RTC/定时器计数
**->** 恢复定时任务
**->** 调用定时钩子/滴答钩子(滴答服务的执行)
* **PendSV** [minpri]
**->** 中断挂起服务的执行
**->** 任务调度/切换
* **任务临界区** [关闭SysTick/PendSV]
**->** 任务服务的执行
* **任务层** 【不同优先级的任务抢占式调度,相同优先级的任务时间片轮转调度】
* Taskmgr[maxpri]
* Debugger[maxpri]
* Starter[maxpri-1]
* 一般用户任务[maxpri-1 ~ minpri+1:1]
* 用户空闲任务[minpri:0]
* 系统空闲任务[minpri:0]
### 零中断延迟基本原理
* 服务层中,SysTick、PendSV、任务临界区,三者间是互斥访问的。换言之,整个服务层是一个大临界区。
* 所有内核服务(中断本地服务除外),均在服务层(临界区)执行,从而保证服务的“操作流”不会被打断。
* 中断本地服务采用互斥访问机制。
#### 服务详解
* **任务服务**,是指在任务中调用的服务,并在任务临界区中执行。
* **滴答服务**,是指在滴答中调用的服务,并在 SysTick 中执行。用户可在滴答钩子、定时中断钩子、定时查询钩子中调用滴答服务。
* **中断服务**,是指在中断中调用的服务,分为中断本地服务和中断挂起服务。
* **中断本地服务**,是指在中断中调用并直接执行的服务,需要互斥访问机制相配合。
* **中断挂起服务**,是指在中断中调用的服务不在本地直接执行,而是把服务的相关信息存入局部的结构体中,
再把结构体指针存入中断挂起服务缓存,再触发PendSV,而后在PendSV中执行。
#### 互斥访问机制
* 用户中断中读全局变量
重入访问:如果变量正在被写入,仍可成功读取变量。
首先,用户需定义全局变量的副本,并按照指定方式来更新副本。
中断中读全局变量时,需调用“iWhichGVarToRead”来询问:“应该读哪一个全局变量”?返回0读正本,返回1读副本。
* 用户中断中接收邮件
重入访问:如果邮箱正在被写入,仍可成功接收邮件(将读取写入过程所读取的局部邮箱)。
互斥访问:如果邮箱正在被写入,将返回失败(false)。
* 用户中断中接收消息
互斥访问:如果队列正在被访问,将返回失败(NULL)。
### 中断挂起服务缓存队列
CosyOS-II 中断挂起服务缓存队列,已实现所有内核的MCU均为先入先出队列(FIFO)。
中断挂起服务缓存队列,有必要先入先出吗?答案是确定的,原因在于当中断并发时,服务的执行顺序要符合“不同中断间可能存在的”和“同一个中断中必然存在的”提请服务的时序逻辑关系。
再有,“入队列”与“出队列”的过程必须是原子操作,不能被打断。
好了,CosyOS-II 零中断延迟基本原理 就简单介绍到这了,想要深入了解的朋友可自行阅读源码,一探究竟!