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


而不可屏蔽 , 就是说这个中断是不可以屏蔽的 , 比如复位中断(是不是不可思议 , 代码执行的第一条指令竟然是中断处理函数里面的) , 如果复位中断都被屏蔽了 , 那么系统也就别想运行了 。
可编程 , 意味着这个中断的优先级可以由软件修改(不可编程 , 即优先级固定死了 , 不能修改) 。
中断的优先级在设置时又有抢占式优先级和非抢占式优先级两种设置(根据单片机不同 , 抢占式和非抢占式可设置的位数不同 , 并且可以分配各自的位数 , 即所谓的中断分组 , 如 STM32F103 共有四位 , 通过设置中断分组来决定抢占式和非抢占的位数) 。
抢占优先级 , 即如果中断 1 的优先级比中断 2 的抢占优先级高的话 , 一旦中断 1 发出中断请求 , 即使已经在中断 2 执行了 , 也会强制进入中断 1 执行 , 这个类似于 main 函数与中断的关系 , 只不过这里两个都是中断而已 。
烟草味道|嵌入式系统优先级详解【烟草味道|嵌入式系统优先级详解】在抢占优先级相同情况下 , 非抢占优先级就会开始起作用了 。
如果中断 1 和中断 2 的抢占优先级设置成一样 , 而非抢占优先级不一样 , 此时如果两个中断同时发出请求 , 那么优先处理非抢占优先级高的中断 。
但是如果不是同时发生呢?那么就会依次处理中断请求 , 在其中一个中断处理过程中 , 是不可以被另一个中断打断的 , 同时如果本中断再来一个请求 , 也不会重新进入中断函数处理 。
即中断本身不可打断自身的处理 , 换句话说中断不会执行到一半时又因为自身新的中断请求来临而重新再次进入本中断处理函数执行 。
如果抢占优先级和非抢占优先级都设置成一样呢 , 此时如果两个中断同时发生 , 又该选择哪个先执行 , 随机吗?
这里就涉及到硬件优先级了 。
在上图中 , 每一个中断其实都是有固定的默认优先级的 , 这个优先级肯定不同 , 所以当抢占优先级和非抢占优先级一样的情况下 , 在中断同时发生时 , 先执行默认优先级高的 。
看图:
烟草味道|嵌入式系统优先级详解讲到了中断 , 就不可不说如何禁止中断的问题了 。
在常规操作中 , 我们会使用禁止全局中断来禁止中断的处理 , 一旦禁止了全局中断 , 那么除了不可屏蔽中断外 , 所有的中断都会被屏蔽掉 , 即如果在禁止中断后发生了中断 , 也不会再执行 。
但是一旦中断打开了 , 那么之前被屏蔽的中断就会立刻开始执行(有一个中断挂起位 , 代表中断的发生 , 只有 CPU 执行了中断处理函数 , 并清零相应标志位 , 该挂起位才会清除) 。
如果在关闭中断的过程中发送了两次中断 , 比如外部中断发生了两次 , 那么在开启中断后 , 也只会响应一次中断 , 因为挂起位就只有那么一位(不像队列一样可以保留多个标志位) 。
对于一般功能而言 , 禁止全局中断确实有用 , 对于保护全局变量也非常有效 , 但是对于整个系统而言会有一定的影响 。
如果禁止中断的时间很短 , 那么确实无关紧要 , 但是一旦需要禁止较长的时间(毫秒级别) , 对于那些需要及时处理的中断而言 , 就是一个不可忽视的延迟 。
而在操作系统中 , 为了保护那些全局变量 , 禁止中断的操作时有发生 , 那么是否有一种方法可以屏蔽部分中断 , 而让高优先级的中断不被屏蔽呢?
有的 , 在 Cortex-M3 内核中 , 有一个寄存器专门干这事 , 即 BASEPRI 。
当设置该寄存器时 , 将屏蔽所有优先级不高于某个具体值的中断 。
比如设置该寄存器为 3 , 那么优先级 0~ 2 的中断不会被屏蔽 。