### 相关名词解释
* 系统中断，包括SysTick_Handler/定时器0中断、PendSV_Handler/其它替代中断，均为最低优先级。
* 进入任务临界区，8051/251内核：关闭上述两个系统中断；Arm内核：屏蔽最低优先级的中断/关闭上述两个系统中断。
* 退出任务临界区，8051/251内核：开启上述两个系统中断；Arm内核：开放最低优先级的中断/开启上述两个系统中断。
* [vTASKING]，当前任务节点的指针。
* [vISS]，中断服务栈（interrupt service stack），用于push/pop中断异步服务的结构体指针。

### 全局不关总中断原理

#### SysTick_Handler/定时器0中断

* 软件RTC计时
* 调用滴答钩子
* 定时中断定时器计数 && 恢复定时中断任务 && 调用定时中断钩子
* 定时查询定时器计数 && 恢复定时查询任务 && 调用定时查询钩子
* 延时定时器计数
* 同步服务：本地执行服务（滴答钩子、定时中断钩子、定时查询钩子）

#### PendSV_Handler/其它替代中断

* 中断异步服务的执行
* 任务调度与切换

#### 任务中调用服务

* 同步服务：<br>
  进入任务临界区 → 本地执行服务 → 退出任务临界区（并返回）<br>
* 异步服务（超时服务）：<br>
  第一阶段：进入任务临界区 → 服务入[vTASKING] → 退出任务临界区并触发任务调度<br>
  切换任务<br>
  第二阶段：再次进入任务临界区 → 继续执行服务 → 退出任务临界区并返回<br>

#### 用户中断中调用服务

* 同步服务（只读访问）：本地执行服务
* 异步服务（含写访问）：<br>
  Arm内核：服务入[vISS] → 触发PendSV<br>
  8051/251内核：服务入[vISS] → 设置中断服务标志 → 触发PendSV<br>

首先，SysTick和PendSV中断优先级相同，均为最低优先级。任务中调用服务时会进入任务临界区（关闭SysTick和PendSV），这就实现了SysTick、PendSV、任务临界区，三者间的互斥访问。只有中断同步服务需另行安排，以实现用户中断中的“只读访问”与上述三者（SysTick、PendSV、任务临界区）中的“写访问”之间的互斥，这就是互斥访问机制。

#### 互斥访问机制

* 用户中断中读全局变量：<br>
  可重入访问：如果变量正在被写入，仍可成功读取变量（将读取写入过程所读取的局部变量）。<br>
* 用户中断中接收邮件：<br>
  可重入访问：如果邮箱正在被写入，仍可成功接收邮件（将读取写入过程所读取的局部邮箱）。<br>
  互斥量访问：如果邮箱正在被写入，将返回失败（false）。<br>
* 用户中断中接收消息：<br>
  互斥量访问：如果队列正在被访问，将返回失败（空指针）。<br>

详情请参阅源码。

#### 中断服务栈（vISS）
需实现中断异步服务的结构体指针入出vISS为原子操作。<br>
1、Arm内核：<br>
vISS为LIFO队列，利用Arm内核的特性及Arm汇编即可实现（详情请参阅源码）。<br>
2、8051/251内核：<br>
8051/251内核无法使用与Arm相同的方法入出vISS，只能采用如下的标志位法。<br>
服务的结构体指针入vISS[svid]，设置中断服务标志（vISV_F##svid）；<br>
在PendSV中执行时，从中断服务标志（vISV_F0）开始依次查询，为真则从vISS[n]中取出结构体指针并执行服务。<br>
详情请参阅源码。

 **_由此，可实现CosyOS的所有内核全局不关总中断（零中断延迟）。_** <br>

以上所述如有异议，或您有更好的实现方法，请与作者联系，共同探讨！<br>

### Keil RTX与CosyOS全局不关中断特性的简单对比
RTX4/5，采用SysTick+PendSV+SVC+互斥访问指令[STREX/LDREX]，实现了Cortex-M3/M4内核全局不关所有中断。<br>
CosyOS，采用SysTick+PendSV+任务临界区+互斥访问机制，实现了所有内核全局不关总中断。<br>

### 相关资料
[技术要点-中断优先级](https://gitee.com/cosyos/cosyos/blob/master/%E6%8A%80%E6%9C%AF%E8%A6%81%E7%82%B9.md#%E4%B8%AD%E6%96%AD%E4%BC%98%E5%85%88%E7%BA%A7)
