STM32F103移植FreeRTOS必须搞明白的系列知识---1(Cortex-CM3中断优先级)

STM32F103移植FreeRTOS必须搞明白的系列知识---1(Cortex-CM3中断优先级)

STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

STM32F103移植FreeRTOS必须搞明白的系列知识---3(堆栈)

STM32F103移植FreeRTOS必须搞明白的系列知识---4(FreeRTOSConfig.h配置文件)

目录

一、Cortex-CM3中断概念

        对于FreeRTOS比较关注的是三个中断屏蔽寄存器:PRIMASK、FAULTMASK和BASEPRI。

二、中断优先级

       Cortex-CM3中,优先级数值越小,优先级越高。例如:优先级数值0的优先级最高,优先级数值为15的优先级最低。

三、抢占优先级和子优先级

四、优先级分组和抢占优先级和子优先级关系

  Cortex-CM3中,抢占优先级和子优先级的优先级数值越小,优先级越高。

1、优先级组0(NVIC_PriorityGroup_0)

2、优先级组1(NVIC_PriorityGroup_1)

3、优先级组2(NVIC_PriorityGroup_2)

4、优先级组3(NVIC_PriorityGroup_3)

5、优先级组4(NVIC_PriorityGroup_4)

五、STM32F103移植FreeRTOS使用哪种优先级分组

六、后记


一、Cortex-CM3中断概念

        Cortex-M的NVIC最多支持240个IRQ(中断请求)、1个不可屏蔽中断(NMI)、1个Systick(滴答定时器)定时器中断和多个系统异常

        Cortex-M处理器有多个用于管中断和异常的可编程寄存器, 这些寄存器大多数都在 NVIC和系统控制块 (SCB)中, CMSIS将这些寄存器定义为结构体。以 STM32F103为例,打开core_cm3.h,有两个结构体, NVIC_TypeSCB_Type。NVIC和SCB都位于系统控制空间(SCS)内,SCS的地址从0XE000E000开始。

        对于FreeRTOS比较关注的是三个中断屏蔽寄存器:PRIMASKFAULTMASKBASEPRI

二、中断优先级

       Cortex-CM3中,优先级数值越小,优先级越高。例如:优先级数值0的优先级最高,优先级数值为15的优先级最低。

        Cortex-CM3中,优先级数值越小,优先级越高。

                      优先级 

      NVIC 的全称是 Nested vectored interrupt controller,即嵌套向量中断控制器。对于Cortex-M3和M4内核的MCU,每个中断的优先级都是用寄存器中的8位来设置的。8 位的话就可以设置 2^8 = 256 级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。比如 ST的STM32F1xx和F4xx只使用了这个8位中的高四位[7:4],低四位无任何意义,这样 2^4=16,只能表示 16级中断嵌套。

        STM32F103只用了高4位来表达优先级(低4位无任何意义),因此最多支持16级的可编程优先级(0~15),0为最高优先级,15为最低优先级。 

        下面是STM32使用Cortex-M的高四位表示优先级(低4位无任何意义):                                     

                                                         使用4位表达优先级

三、抢占优先级和子优先级

         STM32F103只用了4个位(高4位来表达优先级(注:低4位无意义,一般填写1),因此最多支持16级的可编程优先级(0~15)。0为最高优先级,15为最低优先级。然而这16级可编程优先级并不一定都是抢占优先级,它会被优先级组分成两类:抢占优先级和子优先级

         从上面的表格可以看出,STM32 支持 5 种优先级分组,系统上电复位后,默认使用的是优先级分组0(NVIC_PriorityGroup_0),也就是没有抢占式优先级,只有子优先级。

        1、在KEIL软件编程时,使用库函数void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)设置优先级组,参数必须是以下5个宏定义中一个:

#define NVIC_PriorityGroup_0   ((uint32_t)0x700) /*!< 0 bits 抢占优先级,4 bits 子优先级 */
#define NVIC_PriorityGroup_1   ((uint32_t)0x600) /*!< 1 bits 抢占优先级,3 bits 子优先级 */
#define NVIC_PriorityGroup_2   ((uint32_t)0x500) /*!< 2 bits 抢占优先级,2 bits 子优先级 */
#define NVIC_PriorityGroup_3   ((uint32_t)0x400) /*!< 3 bits 抢占优先级,1 bits 子优先级 */
#define NVIC_PriorityGroup_4   ((uint32_t)0x300) /*!< 4 bits 抢占优先级,0 bits 子优先级 */

例子:设置优先级组4(NVIC_PriorityGroup_4),也就是有0-15级抢占式优先级,没有子优先级。

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

        2、在KEIL软件编程时,中断优先级由抢占优先级和子优先级共同组成NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority表示抢占优先级、NVIC_InitStruct->NVIC_IRQChannelSubPriority表示优子先级。

        3、设置优先级分组+抢占优先级+子优先级的代码:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 

NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

        表示设置优先级组4,表示16级优先级全部为可抢占优先级;那么在设置TIM5中断优先级时,NVIC_IRQChannelSubPriority只能设置为0(没有子优先级),NVIC_IRQChannelPreemptionPriority设置为13表示使用优先级为13的可抢占优先级。

四、优先级分组和抢占优先级和子优先级关系

        关于这个抢占优先级和这个子优先级有几点一定要说清楚

        (1)、具有高抢占式优先级的中断可以在具有低抢占式优先级的中断服务程序执行过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以抢占低抢占式优先级的中断的执行。

        (2)、在抢占式优先级相同的情况下,有几个子优先级不同的中断同时到来,那么高子优先级的中断优先被响应。

        (3)、在抢占式优先级相同的情况下,如果有低子优先级中断正在执行,高子优先级的中断要等待已被响应的低子优先级中断执行结束后才能得到响应,即子优先级不支持中断嵌套。

        (4)、Reset、 NMI、 Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。

        (5)、系统中断(比如:PendSV,SVC,SysTick)是不是一定比外部中断(比如 SPI,USART)要高,答案:不是的,它们是在同一个 NVIC 下面设置的。也就是说,如果你想把SPI设置的跟SysTick的中断优先级一样随你的便,如果你不想把SPI设置的跟SysTick的中断优先级不一样也随你的便,完全由你自己决定。

  Cortex-CM3中,抢占优先级和子优先级的优先级数值越小,优先级越高。

1、优先级组0(NVIC_PriorityGroup_0)

        0 bit 用于抢占优先级,  4 bit用于子优先级。

        没有抢占优先级,有16个子优先级。

        子优先级中断不允许嵌套中断,只有抢占优先级才允许嵌套中断。

例子: 

      (1)、当前没有进入任何中断服务程序,如果此时同时触发子优先级1子优先级2中断,则子优先级1先进入中断服务程序(中断优先级的数值越小,优先级越高)。

      (2)、当前已经进入子优先级10的中断服务程序,如果此时触发子优先级1的中断,则仍然执行子优先级10的中断服务程序,只有退出子优先级10的中断服务程序后,才能响应子优先级1的中断。(注:子优先级不允许嵌套中断)。

2、优先级组1(NVIC_PriorityGroup_1)

        1 bit 用于抢占优先级,  3 bit用于子优先级。

        0-1级抢占优先级,0-7级子优先级。

        抢占优先级允许嵌套中断,子优先级中断不允许嵌套中断。

        警告:相同的抢占优先级中断也不允许嵌套中断。

例子:

      (1)、当前没有进入任何中断服务程序,如果此时同时触发(抢占优先级0,子优先级1)和(抢占优先级0,子优先级2)中断,则(抢占优先级0,子优先级1)先进入中断服务程序(中断优先级的数值越小,优先级越高),退出(抢占优先级0,子优先级1)中断服务程序后,才可以进入(抢占优先级0,子优先级2)断服务程序。   ---> 抢占优先级相同,再比较子优先级

      (2)、当前没有进入任何中断服务程序,如果此时同时触发(抢占优先级0,子优先级5)和(抢占优先级1,子优先级2)中断,则(抢占优先级0,子优先级5)先进入中断服务程序(中断优先级的数值越小,优先级越高),退出(抢占优先级0,子优先级5)中断服务程序后,才可以进入(抢占优先级1,子优先级2)中断服务程序。  ---> 先比较抢占优先级,再比较子优先级。

      (3)、当前已经进入(抢占优先级0,子优先级5)中断服务程序,如果此时触发(抢占优先级0,子优先级0)中断,只有当退出(抢占优先级0,子优先级5)中断服务程序后,才可以进入(抢占优先级0,子优先级0)中断服务程序。  ---> 先比较抢占优先级,再比较子优先级。子优先级中断不允许嵌套中断。

      (4)、当前已经进入(抢占优先级0,子优先级5)中断服务程序,如果此时触发(抢占优先级0,子优先级7)中断,只有当退出(抢占优先级0,子优先级5)中断服务程序后,才可以进入(抢占优先级0,子优先级7)中断服务程序。  ---> 先比较抢占优先级,再比较子优先级。子优先级7的优先级比子优先级5的优先级低,而且子优先级不允许嵌套中断。

      (5)、当前已经进入(抢占优先级1,子优先级0)中断服务程序,如果此时触发(抢占优先级0,子优先级7)中断,则立即进入(抢占优先级0,子优先级7)中断服务程序。当退出(抢占优先级0,子优先级7)中断服务程序后,才可以继续执行(抢占优先级1,子优先级0)中断服务程序剩余程序。  ---> 先比较抢占优先级,再比较子优先级。抢占优先级0比抢占优先级1的优先级高,抢占优先级允许嵌套中断。

3、优先级组2(NVIC_PriorityGroup_2)

        2 bit 用于抢占优先级,  2 bit用于子优先级。

        0-3级抢占优先级,0-3级子优先级。

        抢占优先级允许嵌套中断,子优先级中断不允许嵌套中断。

        警告:相同的抢占优先级中断也不允许嵌套中断。

4、优先级组3(NVIC_PriorityGroup_3)

        3 bit 用于抢占优先级,  1 bit用于子优先级。

        0-7级抢占优先级,0-1级子优先级。

        抢占优先级允许嵌套中断,子优先级中断不允许嵌套中断。

        警告:相同的抢占优先级中断也不允许嵌套中断。

5、优先级组4(NVIC_PriorityGroup_4)

        4 bit 用于抢占优先级,  0 bit用于子优先级。

        0-15级抢占优先级,没有子优先级。

        抢占优先级允许嵌套中断,子优先级中断不允许嵌套中断。

        警告:相同的抢占优先级中断也不允许嵌套中断。

 例子:

      (1)、当前没有进入任何中断服务程序,如果此时同时触发(抢占优先级0和(抢占优先级1断,则(抢占优先级0先进入中断服务程序(中断优先级的数值越小,优先级越高),退出(抢占优先级0中断服务程序后,才可以进入(抢占优先级1断服务程序。   

      (2)、当前已经进入(抢占优先级0中断服务程序,如果此时触发(抢占优先级2)中断,则继续执行(抢占优先级0中断服务程序(中断优先级的数值越小,优先级越高;低优先级的中断不允许打断高优先级的中断),退出(抢占优先级0中断服务程序后,才可以进入(抢占优先级2中断服务程序。  ---> 低抢占优先级的中断不允许打断高抢占优先级的中断。

      (3)、当前已经进入(抢占优先级5中断服务程序,如果此时触发(抢占优先级3)中断,则打断(抢占优先级5中断服务程序(中断优先级的数值越小,优先级越高;高优先级的中断允许打断低优先级的中断),进入(抢占优先级3中断服务程序执行退出(抢占优先级3中断服务程序后,才可以重新进入(抢占优先级5中断服务程序,继续执行剩余的程序。  ---> 高抢占优先级的中断允许打断低抢占优先级的中断。

五、STM32F103移植FreeRTOS使用哪种优先级分组

        官方强烈建议,STM32F103移植FreeRTOS时使用优先级组4(NVIC_PriorityGroup_4)。可以分配16种抢占中断源,中断可以快速响应,优先执行最急迫的中断。

六、后记

        有些读者觉得疑惑了,如此强大的STM32,所有GPIO都能够配置成外部中断,USART、ADC 等外设也有中断,而NVIC 只能配置16 种中断向量,那么在某个工程中使用超过16 个中断怎么办呢?

        注意NVIC 能配置的是16 种中断向量,而不是16 个,当工程中有超过16 个中断向量时,必然有两个以上的中断向量是使用相同的中断种类,而具有相同中断种类的中断向量不能互相嵌套。

        例如:如果工程项目中超过16个中断源,可以将优先级分组定义为优先级组4(NVIC_PriorityGroup_4),USART1的抢占优先级定义为12,USART2的抢占优先级定义为12,SPI1的抢占优先级定义为12。

        如果当前已经进入USART1中断服务程序,这时候SPI1中断触发(警告:相同的抢占优先级中断也不允许嵌套中断。),由于同级抢占优先级中断不能相互嵌套,因此只有等到退出USART1中断服务程序后,才可以进入SPI1中断服务程序。

  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
移植FreeRTOSSTM32F103上需要以下步骤: 1. 下载FreeRTOS的源代码 2. 在STM32F103上创建一个工程 3. 将FreeRTOS的源代码添加到工程中 4. 配置FreeRTOS的内核参数 5. 添加RTOS相关的头文件和源文件 6. 配置STM32F103的硬件参数 7. 编写应用程序 接下来,我将逐步介绍每个步骤。 1. 下载FreeRTOS的源代码 您可以从FreeRTOS官方网站(https://www.freertos.org/)下载最新版本的源代码。 2. 在STM32F103上创建一个工程 在您的编译器中创建一个新的工程,并选择适当的芯片(STM32F103),以便编译器可以正确地设置和编译程序。 3. 将FreeRTOS的源代码添加到工程中 将FreeRTOS的源代码添加到您的工程中。您可以使用FreeRTOS提供的完整源代码,也可以只使用与您的应用程序相关的部分。 4. 配置FreeRTOS的内核参数 在您的应用程序中,您需要配置FreeRTOS的内核参数,例如任务优先级和堆栈大小等。 5. 添加RTOS相关的头文件和源文件 将FreeRTOS相关的头文件和源文件添加到您的应用程序中,以便您可以使用FreeRTOS的API函数。 6. 配置STM32F103的硬件参数 在您的应用程序中,您需要配置STM32F103的硬件参数,例如时钟和外设等。您可以使用STM32F103的手册来获得有关如何配置硬件的更多信息。 7. 编写应用程序 在您的应用程序中,您需要创建和管理FreeRTOS任务,并使用FreeRTOS API函数来实现任务间的通信和同步。 以上是移植FreeRTOSSTM32F103的基本步骤。移植FreeRTOS需要一定的编程经验和对STM32F103硬件的了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值