烟草味道|嵌入式系统优先级详解

在嵌入式软件开发中 , 我们不可避免的需要接触优先级的概念 , 掌握优先级的概念对于设计一个好的软件系统尤为重要 。
本篇笔记的主要内容有以下几个方面:
1、中断优先级
2、操作系统中的任务优先级
3、同等优先级处理
4、中断嵌套
今天鱼鹰借助大家熟悉的 STM32F103 平台和各位聊聊其中的密事 。
烟草味道|嵌入式系统优先级详解首先 , 我们从一个裸机系统的变量自加开始说起 。
烟草味道|嵌入式系统优先级详解这里有三个变量 , A、B、C , 其中 B 变量除了在 main 函数中自加外 , 还会在中断处理函数中进行自加 。
这里面考虑了 B 的两种情况 , 一是先执行 main 中的自加再执行中断的自加 , 二是先执行中断的自加再进行 main 的自加 。
不管发生哪种情况 , 当程序执行到 C 位置时 , B 的值都是一样的 。
当然 , 以上分析是从 C 语言的角度进行分析的 , 如果以汇编的视角进行分析(自加操作在汇编中分为三个步骤) , 你会发现 , 这里面其实还有第三种情况:
烟草味道|嵌入式系统优先级详解这里面的 B’ 可以认为是寄存器 , 即变量的 B 的副本 。
正因为副本的存在 , 在 main 函数的写入过程中导致丢失了中断中 B 的自加操作 。
对于程序而言 , 就好像根本没有进入中断一样!
这就是全局变量的使用隐患 。
但是善于分析的道友可能会提出这样一个疑问 , 为什么上面只考虑了 main 函数中的 B++被打断的可能 , 却没有考虑中断(橙色部分)的 B++被打断的可能 , 是鱼鹰忽略了吗?
不不 , 其实这里面就涉及到了今天的主题 , 优先级 。
在裸机系统中 , 中断优先级高于 main 函数的处理 , 也就是说 , 一且中断来临 ,不管 main 函数执行到哪个位置 , 都会优先处理中断程序 , 只有中断程序执行完成后 , 才会继续执行 main 函数 , 所以中断的 B++ 不可能被 main 函数打断!
这里插两个问题:
怎么进入中断函数的?
当中断请求(中断请求可以认为是种电平信号 , 在寄存器中就表现为某一位的标志位)来临时 , 硬件负责把部分寄存器存储到栈(一种特殊的数据结构)中 , 这里面就包含了 PC 寄存器(用于指示下一条指令执行的位置) , 之后从向量表中找到中断处理函数的入口地址 , 开始进入中断处理函数中执行 。
怎么回到原来的位置?
因为在进入中断前已经保存了 PC 等其他寄存器的值 , 所以只要在执行完中断处理函数后 , 将之前的保存到栈中的值恢复回来 , 那么 CPU 就可以继续从被打断的指令开始继续执行 。
更多相关的中断行为请查看《权威指南》 , 鱼鹰不再细说 。
回到刚才的优先级话题 , 正因为中断的执行优先级比 main 高 , 所以中断中的 B++ 不会被打断 , 这也是为什么有些时候 , 我们不需要对中断中的变量进行临界保护的原因所在 。
在 Cortex-M3 内核中 , 中断分为可屏蔽和不可屏蔽中断 , 同时又有可编程优先级和不可编程优先级之分 。
烟草味道|嵌入式系统优先级详解所谓可屏蔽 , 就是说这个中断是可以屏蔽掉的 , 即使发生了中断 , 也不会让 CPU 执行中断里面的程序 。
比如我们的定时器中断 , 如果我们没有开启相应的中断的话 , 即使定时器溢出中断来了 , 那也不会进入中断处理函数处理的 。