精华内容
下载资源
问答
  • 为什么要设置PendSV为最低优先级? 应用程序执行SVC 时都是希望所需的请求立即得到响应。 PendSV 则不同,它是可以像普通的中断一样被抢占挂起的(不像SVC 那样会上访)。 操作系统 可以利用它“缓期执行”一个异常...

    为什么要设置PendSV为最低优先级?
    应用程序执行SVC 时都是希望所需的请求立即得到响应。 PendSV 则不同,它是可以像普通的中断一样被抢占挂起的(不像SVC 那样会上访)。
    操作系统 可以利用它“缓期执行”一个异常,一直到其它重要的任务完成后才执行动作
    PendSV是为系统设备而设的“可悬挂请求”(pendable request)。
    1)上下文切换 不能在中断中进行,会导致中断延期。为了解决这个问题,使用 PendSV。PendSV可以挂起,也就是等到别的 ISR结束后缓期执行。
    2)为了实现缓期执行PendSV,PendSV一定要被设置为最低优先级的异常

    如何设置PendSV?
    看下图,对于系统异常,可编程的在编号4—15:
    在这里插入图片描述
    在这里插入图片描述
    对于PendSV存储优先级的这个字节,其地址在0XE000_ED22,而寄存器的地址在0XE000_ED20,因此要做一些左移位操作
    在这里插入图片描述
    下图可知,是stm32f1X用了4个位来分配抢占优先级和子优先级
    在这里插入图片描述
    下图可知,configLIBRARY_LOWEST_INTERRUPT_PRIORITY为15 ,因为分组是4,即4个位都作为抢占优先级,有0—15,在中断中,数字越小优先级越高,所以15这个数字是最低优先级,用十六进制表示就是0x0000 000f。
    对于configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS),_其中NVIC_PRIO_BITS 为4 ,所以就是configLIBRARY_LOWEST_INTERRUPT_PRIORITY <<4,也就是15<<4即
    0x0000 000f<<4,结果为0x0000 00f0,即移到了最低字节的最高4位。
    那么configKERNEL_INTERRUPT_PRIORITY=0x0000 00f0;
    在这里插入图片描述
    下图可知,
    ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) 左移16位后取别名portNVIC_PENDSV_PRI,代表0x 00f0 0000
    ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY )左移24位后取别名
    portNVIC_SYSTICK_PRI,代表0x f000 0000
    在这里插入图片描述

    再看下图:portNVIC_SYSPRI2_REG分别和portNVIC_PENDSV_PRI,portNVIC_SYSTICK_PRI按位或,这就是置位,即把优先级15写入对应的字节,0XE000_ED22(PendSV)处和0XE000_ED23(sysTick)处,
    在这里插入图片描述
    因为采用的是小端存储,即高地址对应高字节,低地址对应低字节,如下图在这里插入图片描述

    展开全文
  • *工程模板(寄存器版本) */ #include "stm32f10x.h" /** * 主函数 */ int main(void) { // 开启GPIOB 端口时钟 RCC_APB2ENR |= (1<<3); //清空控制PB0的端口位 GPIOB_CRL &= ~( 0x0F<< (4...

    抢占优先级和响应优先级

    STM32 的中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号越小,表明它的优先级别越高。

    抢占

    抢占,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数A 的过程中被中断B 打断,执行完中断服务函数B 再继续执行中断服务函数A),抢占属性由NVIC_IRQChannelPreemptionPriority 的参数配置。

    响应

    响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达, 则先处理响应优先级高的中断, 响应属性由NVIC_IRQChannelSubPriority 参数配置。

    例如,现在有三个中断向量,如下表
    在这里插入图片描述

    若内核正在执行C 的中断服务函数,则它能被抢占优先级更高的中断A 打断,由于B 和C 的抢占优先级相同,所以C 不能被B 打断。但如果B 和C 中断是同时到达的,内核就会首先响应响应优先级别更高的B 中断(高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的,而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断)。

    NVIC 的优先级组

    在配置优先级的时候,还要注意一个很重要的问题,即中断种类的数量。

    NVIC 只可以配置16 种中断向量的优先级,也就是说,抢占优先级和响应优先级的数量由一个4 位的数字来决定,把这个4 位数字的位数分配成抢占优先级部分和响应优先级部分。

    有5 组分配方式:

    1. 第 0 组: 所有4 位用来配置响应优先级。即16 种中断向量具有都不相同的响应优先级。
    2. 第 1 组:最高1 位用来配置抢占优先级,低3 位用来配置响应优先级。表示有2 种级别的抢占优先级(0 级,1 级),有8 种响应优先级,即在16 种中断向量之中,有 8 种中断,其抢占优先级都为0 级,而它们的响应优先级分别为0~7,其余8 种中断向量的抢占优先级则都为1 级,响应优先级别分别为0~7。
    3. 第 2 组:2 位用来配置抢占优先级,2 位用来配置响应优先级。即4 种抢占优先级,4 种响应优先级。
    4. 第 3 组:高3 位用来配置抢占优先级,最低1 位用来配置响应优先级。即有8 种抢占优先级,2 种响应2 优先级。
    5. 第 4 组:所有4 位用来配置抢占优先级,即NVIC 配置的16 种中断向量都是只有抢占属性,没有响应属性。

    要配置这些优先级组,可以采用库函数NVIC_PriorityGroupConfig(),可输入的参数为NVIC_PriorityGroup_0 ~ NVIC_PriorityGroup_4,分别为以上介绍的5 种分配组。

    于是,有读者觉得疑惑了,如此强大的STM32,所有GPIO都能够配置成外部中断,USART、ADC 等外设也有中断,而NVIC 只能配置16 种中断向量,那么在某个工程中使用超过16 个中断怎么办呢?注意NVIC 能配置的是16 种中断向量,而不是16 个,当工程中有超过16 个中断向量时,必然有两个以上的中断向量是使用相同的中断种类,而具有相同中断种类的中断向量不能互相嵌套。

    中断寄存器

    ISER[8]

    全称 Interrupt Set-Enable Registers,是一个中断使能寄存器组。

    CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。

    但是 STM32F103 的可屏蔽中断只有 60 个,所以对我们来说,有用的就是两个(ISER[0]和 ISER[1]), 总共可以表示 64 个中断。

    而 STM32F103 只用了其中的前 60 位。ISER[0]的 bit0~bit31 分别对应中断 0~31。ISER[1]的 bit0~27 对应中断 32~59;这样总共 60 个中断就分别对应上了。

    你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中 断分组、屏蔽、IO 口映射等设置才算是一个完整的中断设置)。具体每一位对应哪个中断,请参考 stm32f10x.h 里面的第 140 行处(针对编译器 MDK5 来说)。

    ICER[8]

    全称 Interrupt Clear-Enable Registers,是一个中断除能寄存器组。

    该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICRT 一样。

    这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄 存器都是写 1 有效的,写 0 是无效的。具体为什么这么设计,请看《CM3 权威指南》第 125 页, NVIC 概览一章。

    ISPR[8]

    全称 Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。

    每个位对应的中断和 ISER 是一样的。

    通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别 的中断。写 0 是无效的。

    ICPR[8]

    全称 Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。

    其作用与 ISPR 相反,对应位也和 ISER 是一样的。

    通过设置 1,可以将挂起的中断接挂。写 0 无效。

    IABR[8]

    全称 Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。

    对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。

    这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

    IP[240]

    全称 Interrupt Priority Registers,是一个中断优先级控制的寄存器组。

    这个寄存器组相当重要!STM32 的中断分组与这个寄存器组密切相关。

    IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。

    而 STM32 只用到了其中的前 60 个。IP[59]~IP[0]分别对应中断 59~0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。


    STM32 将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。具体分配关系如下表:

    AIRCR[10:8]bit[7:4]分配情况分配结果
    01110: 40 位抢占优先级,4 位响应优先级
    11101: 31 位抢占优先级,3 位响应优先级
    21012: 22 位抢占优先级,2 位响应优先级
    31003: 13 位抢占优先级,1 位响应优先级
    40114: 04 位抢占优先级,0 位响应优先级

    例如,组设置为 3,那么此时所有的 60 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是响应优先级。这样每个中断,你就可以设置抢占优先级位 0~7(因为抢占优先级有 3 位,最高可表示为 000=0~111=7),响应优先级(只有 1 位因此)为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

    这里需要注意两点:
    第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
    第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的,而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

    结合实例说明一下:
    假定设置中断优先级组为 2,然后设置中断 3(RTC 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。

    那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。

    上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!


    接下来我们介绍如何使用库函数实现以上中断分组设置以及中断优先级管理,使得我们以后的中断设置简单化。NVIC 中断管理函数主要在 misc.c 文件里面。

    中断优先级分组函数

    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);	//中断优先级分组函数
    

    这个函数唯一目的就是通过设置 SCB->AIRCR 寄存器来设置中断优先级分组

    比如我们设置整个系统的中断优先级分组值为 2,那么方法是:

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    

    中断初始化函数

    void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);	//中断初始化函数
    

    其中 NVIC_InitTypeDef 是一个结构体,中间有三个成员变量,这三个成员变量的作用是:

    1. NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如 USART1_IRQn。
    2. NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。
    3. NVIC_IRQChannelSubPriority:定义这个中断的子优先级别。
    4. NVIC_IRQChannelCmd:该中断是否使能。

    比如我们要使能串口 1 的中断,同时设置抢占优先级为 1,子优先级位 2,初始化的方法是:

    NVIC_InitTypeDef NVIC_InitStructure; 
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;			// 串口 1 中断 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1 ;	// 抢占优先级为 1 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			// 子优先级位 2 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 			// IRQ 通道使能 
    NVIC_Init(&NVIC_InitStructure); 							// 根据上面指定的参数初始化 NVIC 寄存器
    

    中断优先级设置步骤总结

    1. 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的 分配位数。调用函数为
    NVIC_PriorityGroupConfig();
    
    1. 设置所用到的中断的中断优先级别。对每个中断调用函数为
    NVIC_Init();
    

    Ref.

    1. STM32的抢占优先级和响应优先级
    展开全文
  • 嵌入式系统优先级详解

    千次阅读 2020-08-19 21:00:00
    关注、星标公众号,不错过精彩内容作者:鱼鹰Osprey微信公众号ID:emOsprey在嵌入式软件开发中,我们不可避免的需要接触优先级的概念,掌握优先级的概念对于设计一个好的软件系统尤为...

    关注、星标公众,不错过精彩内容

    作者:鱼鹰Osprey

    微信公众号ID:emOsprey

    在嵌入式软件开发中,我们不可避免的需要接触优先级的概念,掌握优先级的概念对于设计一个好的软件系统尤为重要。

    本篇笔记的主要内容有以下几个方面:

    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执行中断里面的程序。

    比如我们的定时器中断,如果我们没有开启相应的中断的话,即使定时器溢出中断来了,那也不会进入中断处理函数处理的。

    而不可屏蔽,就是说这个中断是不可以屏蔽的,比如复位中断(是不是不可思议,代码执行的第一条指令竟然是中断处理函数里面的),如果复位中断都被屏蔽了,那么系统也就别想运行了。

    可编程,意味着这个中断的优先级可以由软件修改(不可编程,即优先级固定死了,不能修改)。

    中断的优先级在设置时又有抢占式优先级和非抢占式优先级两种设置(根据单片机不同,抢占式和非抢占式可设置的位数不同,并且可以分配各自的位数,即所谓的中断分组,如STM32F103 共有四位,通过设置中断分组来决定抢占式和非抢占的位数)。

    抢占优先级,即如果中断 1 的优先级比中断 2 的抢占优先级高的话,一旦中断1发出中断请求,即使已经在中断 2 执行了,也会强制进入中断 1 执行,这个类似于 main 函数与中断的关系,只不过这里两个都是中断而已。

    在抢占优先级相同情况下,非抢占优先级就会开始起作用了。

    如果中断 1 和中断 2 的抢占优先级设置成一样,而非抢占优先级不一样,此时如果两个中断同时发出请求,那么优先处理非抢占优先级高的中断。

    但是如果不是同时发生呢?那么就会依次处理中断请求,在其中一个中断处理过程中,是不可以被另一个中断打断的,同时如果本中断再来一个请求,也不会重新进入中断函数处理。

    即中断本身不可打断自身的处理,换句话说中断不会执行到一半时又因为自身新的中断请求来临而重新再次进入本中断处理函数执行。

    如果抢占优先级和非抢占优先级都设置成一样呢,此时如果两个中断同时发生,又该选择哪个先执行,随机吗?

    这里就涉及到硬件优先级了。

    在上图中,每一个中断其实都是有固定的默认优先级的,这个优先级肯定不同,所以当抢占优先级和非抢占优先级一样的情况下,在中断同时发生时,先执行默认优先级高的。

    看图:

    讲到了中断,就不可不说如何禁止中断的问题了。

    在常规操作中,我们会使用禁止全局中断来禁止中断的处理,一旦禁止了全局中断,那么除了不可屏蔽中断外,所有的中断都会被屏蔽掉,即如果在禁止中断后发生了中断,也不会再执行。

    但是一旦中断打开了,那么之前被屏蔽的中断就会立刻开始执行(有一个中断挂起位,代表中断的发生,只有CPU执行了中断处理函数,并清零相应标志位,该挂起位才会清除)。

    如果在关闭中断的过程中发送了两次中断,比如外部中断发生了两次,那么在开启中断后,也只会响应一次中断,因为挂起位就只有那么一位(不像队列一样可以保留多个标志位)。

    对于一般功能而言,禁止全局中断确实有用,对于保护全局变量也非常有效,但是对于整个系统而言会有一定的影响。

    如果禁止中断的时间很短,那么确实无关紧要,但是一旦需要禁止较长的时间(毫秒级别),对于那些需要及时处理的中断而言,就是一个不可忽视的延迟。

    而在操作系统中,为了保护那些全局变量,禁止中断的操作时有发生,那么是否有一种方法可以屏蔽部分中断,而让高优先级的中断不被屏蔽呢?

    有的,在 Cortex-M3 内核中,有一个寄存器专门干这事,即 BASEPRI。

    当设置该寄存器时,将屏蔽所有优先级不高于某个具体值的中断。

    比如设置该寄存器为 3,那么优先级0~ 2的中断不会被屏蔽。

    所以在操作系统中,我们可以修改禁止中断的代码,使其不会屏蔽高优先级的中断,对于高优先级中断来说,可增加实时性。

    uCOS II 中默认是直接全局禁止中断的(可以修改它),但是 FreeRTOS 是可以禁止部分中断的,使用的就是上述寄存器,当然这个功能需要单片机本身支持才行。

    以上就是中断优先级的内容,如果只会裸机的话,那么以上内容就差不多了,但是如果是操作系统,那么需要再增加一个任务优先级的概念。

    所谓任务,你也可以认为是一种中断,只不过,这种特殊的中断优先级低于所有的硬件触发的中断。

    中断的优先级凌驾于所有任务之上。

    也就是说,一旦中断来临,不管CPU正在执行哪个任务,在全局中断开启的情况下,都会立刻执行中断里的程序。

    在中断中,可以进行中断嵌套,所谓的中断嵌套即当前中断被另一个更高优先级的中断所打断(即抢占),被打断的中断必须在高优先级任务执行完成后才会继续执行。而在嵌入式实时操作系统中,为了更好的处理实时任务,一般而言也会设置成可抢占的任务(亦称可剥夺)。

    中断的优先级处理是由内核进行管理的,这里的内核是指单片机内核,比如STM32F103的内核是Cortex-M3(更准确的说是由 NVIC 管理)。

    一旦设置好相应的寄存器之后,只要中断来了,那么就会自动处理中断程序,这些工作由硬件完成,它会在多个中断同时来临时选择最高的优先处理;也会在中断执行时,如果有一个更高优先级的中断来临时,打断当前中断的执行而先执行更高优先级的中断。

    但是操作系统是纯软件行为,那么操作系统的任务优先级又是谁管理的?又是如何管理的呢?

    答案就在Systick中断。

    既然要管理所有任务的优先级,即在合适时选择运行优先级最高的任务,那么操作系统本身必然需要有能剥夺所有任务执行的能力,而中断是凌驾于任务之上的,可以在任何时候剥夺任务的执行,从而获得CPU的使用权,所以选择中断作为操作系统的核心是合适的。

    但是中断那么多,选择什么中断比较合适呢?没有比 Systick 中断更合适的了,因为它就是为此而生的。

    Systick说白了就是一个定时器,但是和普通定时器不同的是,功能比较单一,就是一个计数器而已,所以使用它管理任务是合适的,不会占用其他定时器。

    那么Systick又是如何管理任务的呢?

    一般而言,Systick 会设置成几毫秒中断一次,在每次中断时,Systick处理程序(即操作系统内核)都会从所有的任务中选择最高优先级的任务执行,也就是说,系统总是运行最高的任务。

    而这个特性也就导致你的高优先级任务不可以无限执行而不主动释放CPU,因为一旦高优先级任务无限执行了,那么低优先级任务将永远得不到执行机会,这就给人一种死机的假象。

    可能有道友会疑惑,为什么空闲任务不需要调用系统延时函数去主动释放CPU的使用权呢?

    那是因为空闲任务本身优先级就是所有任务中最低的,如果它主动释放 CPU 了,而其他任务都处于挂起状态,那么操作系统又该让谁去执行呢?

    所以,空闲任务需要永远处于运行状态。

    从这个角度来说,操作系统主要的功能就是定时从所有任务中寻找最高优先级的任务,然后让该任务得到运行机会(使用PendSV 中断切换到任务中,模拟中断切换过程),功能类似于中断管理器。

    而正因为操作系统只会寻找最高优先级的任务来执行(对于实时操作系统是这样,有些操作系统可能先来先处理的策略),所以任务本身主动释放 CPU 就显得尤为重要了。

    最常用的主动释放 CPU 的函数就是系统延时函数了,调用这个函数后,任务将延时一段时候才回来继续执行,而在延时过程中,操作系统就可以调用其他任务执行了,正因为如此,操作系统才显得高效。

    虽然操作系统需要中断来剥夺所有任务的执行,从而拥有 CPU 的控制权,但是一般而言,它的优先级却是所有中断中最低的,因为它的优先级只需要高于任务即可,如果设置的更高,那么就会影响到真正需要高优先处理的中断,因为Systick中断的处理还是比较频繁和繁重的,如果设置的太高,那么在Systick处理时,更低优先级的中断将无法处理,这可不是我们想看到的结果。

    而如果设置成中断优先级最低的话,既可以剥夺任务的执行,又可以在高优先级中断来临时及时处理中断,让系统的实时得到提高。

    与 Systick 配套的中断,还有一个 PendSV 中断,这个优先级一般和 Systick 设置成一样,一般而言该中断的触发是由操作系统内核主动触发的(在切换任务时软件触发该中断),而不像 Systick 一样,定时被动触发,关于两个中断更具体描述可参考《Cortex-M3 权威指南》。

    既然中断可以设置成优先级一样的,那么任务应该也可以才对,确实一般的操作系统都可以设置相同优先级的任务(uCOS II 不可以, uCOS III 和 FreeRTOS 、RT-Thread可以),那么操作系统又是如何处理同等优先级的任务?

    一般而言,在任务初始化时,会设置任务的时间片,这个时间片就是在任务优先级相同的情况下才会发生作用。

    比如,任务 1 设置 5 个时间片(即Systick中断时间),任务 2 设置 10 个时间片,如果两个任务的优先级一样,那么在 15 个时间片内,任务 1 将执行 5 个时间片,之后切换到任务 2 执行10个时间片,来回往复。

    那么比任务1 和任务 2 优先级更高的任务该什么时候执行呢?答案是随时,即只要高优先级任务有需要,那么不管任务 1 和 任务 2 是否主动释放 CPU,都会被操作系统强制切换到高优先级任务中执行(由 Systick完成,所以可能会有一点延时)。

    那么优先级比它们低的任务呢?这个就靠它们的自觉了,如果它们自觉的主动释放CPU(比如调用系统延时函数),那么低优先级任务就有执行机会,否则,低优先级任务将不会执行!

    该用一张图来说明整个系统的优先级关系了:

    最后鱼鹰再聊聊该如何设置任务优先级。

    很多人设计任务优先级时都会从 0、1、2、3 这样的顺序来设置,实际上,这种设置是不合理的,因为一旦后面需求变化了,要从中加入一个中间的优先级,那么很可能在加入后程序出现问题了。

    其实我们可以从 Cortex-M3 的中断优先级得到启发,即空开部分优先级不使用,留待后面扩展用,比如设计优先级时可以设置成 3、5、7、9、11,留出最高的0~2用于可能的高优先级任务,中间空出一个或两个优先级用于扩展,这样一旦后面需要增加其他优先级的任务,会显得异常简单(可能会有额外的一点内存损耗,但却是值得的)。

    ‧  END  

    以上内容转自公众号『鱼鹰谈单片机』,鱼鹰的公众号主要分享面向软件开发进阶读者的公众号,分享包括但不限于 C 语言、KEIL、STM32、51 等知识。

    终极串口接收方式,极致效率

    许久以后,你会感谢自己写的异常处理代码

    如何写一个健壮且高效的串口接收程序?

    鱼鹰整理的干货比较多,推荐关注他的微信公众号『鱼鹰谈单片机 』,识别下面二维码关注。

    长按前往图中包含的公众号关注

    展开全文
  • 其利用51系统内建的中断允许寄存器IE和中断优先级寄存器IP,通过屏蔽字机制来实现;以C51的形式,给出这种扩展方法的函数库实现,为该方法的使用赋予友好、简洁的用户接口。 关键词:MCS-51单片机 中断优先级 软扩展...
  • NVIC寄存器列表 中断使能寄存器 ...中断和复位控制寄存器(AIRCR)、系统处理优先级寄存器(SCB->SHP[0-11]) 系统处理控制和状态寄存器(SCB->SHCSR) PRIMASK、FAULTMASK BAS...

    NVIC寄存器列表

    中断使能寄存器

    设置中断挂起和清除中断挂起

    中断活跃状态寄存器

    中断优先级寄存器

    软件触发中断寄存器

    中断控制器类型寄存器

    SCB寄存器

    中断控制和状态寄存器(ICSR)、向量表偏移寄存器(VTOR)

    中断和复位控制寄存器(AIRCR)、系统处理优先级寄存器(SCB->SHP[0-11])

    系统处理控制和状态寄存器(SCB->SHCSR)

    PRIMASK、FAULTMASK

    BASEPRI

    展开全文
  • 嵌入式FreeRTOS操作系统中断优先级

    万次阅读 2019-06-05 10:08:30
    嵌入式FreeRTOS操作系统中断优先级配置(重要) 2016年09月23日 16:49:48偏执灬阅读数:8865更多 个人分类:嵌入式实时操作系统 本章节为大家讲解FreeRTOS中断优先级配置,此章节非常重要,初学者经常在这里犯...
  • NVIC中断优先级管理 CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核...
  • 一、系统寄存器 1. EFLAGS 寄存器 ① 存放system flags和IOPL; ②控制任务切换和模式切换,处理终端,指令追踪; 2.控制寄存器(CR0,CR2,CR3,CR4) ①控制系统级操作; ②支撑操作系统某些...
  • 操作系统程序员必须了解的四类寄存器 供操作系统程序员使用的寄存器可以分为下面这么几类: EFLAGS Memory-Management Registers Control Registers Debug Registers 接下来我们分别介绍一下这几类寄存器。 ...
  • 问题描述: SysTick和pendSV的中断优先级分别设置为0和15,这样的设置可能会存在一个问题,SysTick优先级太高会抢占用户自己设置的外设的中断。...PendSV优先级设置寄存器地址为0xe000ed22 SysTic...
  • 本节探讨如何让应用程序运行在低优先级而无法执行特权指令进而保护内核免受恶意程序的入侵。
  • 中断优先级寄存器的编程应该在中断使能之前,其通常是在程序开始时完成的。应该避免在中断使能之后改变中断优先级,因为这种情况的结果在ARMv6-M系统结构是不可预知的,并且不被Cortex-M0处理器支持。Cortex...
  • 实现控制和控制分别由特殊功能寄存器区中的中断允许寄存器IE和中断优先级寄存器IP来实现的。下面介绍这两个特殊功能寄存器。 中断允许寄存器IE 的CPU对各中断源的开放或屏蔽,是由片内的中断允许寄存器IE控制的。...
  • 在MCS-中断优先级中由中断优先级寄存器IP来高置的,IP中某位设为1,相应的中断就是高优先级,否则就是低优先级。 - - - PS PT1 PX1 PT0 PX0 I...
  • //设置系统中断优先级分组方式 其中XXXXX代表分组方式,可以在5个宏中选其一,这就是上图中的5种分组方式: 下面看一个给串口中断设置中断优先级的例子: NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;...
  • NVIC中有一个寄存器是“应用程序中断及复位控制寄存器”(内容见表7.5),它里面有一个位段名为“优先级组”。该位段的值对每一个优先级可配置的异常都有影响——把其优先级分为个位段:MSB所在的位段(左边的)对应...
  • 嵌入式FreeRTOS操作系统中断优先级配置(重要)

    万次阅读 多人点赞 2016-09-23 16:49:48
    本章节为大家讲解FreeRTOS中断优先级配置,此章节非常重要,初学者经常在这里犯迷糊。对于初学者来说,本章节务必要整明白。 12.1 NVIC基础知识 12.2 使用FreeRTOS时如何配置外设NVIC 12.3 FreeRTOS配置选项中...
  • 这种分组把每个中断优先级寄存器入口分为两块: 上半区定义了组优先级。 下半区定义了组里的子优先级。 只有组优先级决定了中断异常能否抢占。当处理器正在执行一个中断异常处理程序时,另一个有着一样组优先级的...
  • 51单片机系列--中断系统中断系统的结构TCON寄存器中断允许寄存器IE中断函数中断优先级寄存器IP 中断系统的结构 有5个中断请求源 INT0、T0、INT1、T1、TI/RI ; 中断标志寄存器(TCON) 中断允许寄存器(IE) 全局...
  • ARM中断及相关寄存器

    千次阅读 2010-01-22 16:44:00
    ARM中断寄存器主要包括: ·中断模式寄存器可以设置2个中断源为IRQ或FIQ方式。 ·中断挂起寄存器,当有中断请求产生时,相应的位会被... ·中断优先级寄存器可以设置21个中断源优先级的高低。 ·中断偏移寄存器,中
  • STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作’亚优先级’或’副优先级’,每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级...
  • CM3中 STM32参考教程:
  • SysTick系统定时器(功能框图和优先级配置) SysTick—系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit (2^24)的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们...
  • C51中设置中断优先级,需要对中断寄存器IP进行配置。具体值需要根据用户需要的优先级顺序进行确定,具体的设置方法就是直接写如下C语言语句:IP = 06H;// 如果5个中断同时发生,则响应次序为:定时器0 -> 外中断1...
  • 中断优先级

    千次阅读 2017-03-21 19:49:33
    IP 这个寄存器的每一位,表示对应中断的抢占优先级,每一位的复位值都是 0,当我们把某一位设置为 1 的时候,这一位的优先级就比其它位的优先级高了。比如我们设置了 PT0位为 1 后,当单片机在主循环或者任何其它...
  • 51单片机与中断相关的寄存器

    千次阅读 2020-05-22 15:52:51
    51单片机与中断相关的寄存器简介中断控制寄存器IE中断优先级控制寄存器IP定时器控制寄存器TCON串行口控制寄存器SCON 简介 中断控制寄存器 IE 中断优先级控制寄存器 IP 定时器控制寄存器 TCON 串行口控制寄存器 SCON...
  • 不过,若处理器已经在处理另外一个更高或同优先级的中断,或者中断被某个中断屏蔽寄存器给屏蔽掉了,那么在其他的中观处理结束前或者中断屏蔽被清除前,挂起请求会一直保持。   当中断开始处理中断请求时,中断的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 55,241
精华内容 22,096
关键字:

系统优先级寄存器