FreeRTOS_中断配置和临界段

文章详细介绍了Cortex-M处理器中断的基本概念,包括中断简介、中断管理、优先级分组、优先级设置以及用于中断屏蔽的特殊寄存器。接着,文章深入阐述了FreeRTOS在STM32平台上中断配置的相关宏定义,如configPRIO_BITS、configKERNEL_INTERRUPT_PRIORITY等,并解析了如何设置PendSV和SysTick的中断优先级。最后,文章讨论了FreeRTOS的临界段代码保护,包括任务级和中断级的临界段代码保护函数及其使用方法,并给出了中断测试实验的设计和分析。

目录

1. Cortex-M 中断

1.1 中断简介

1.2 中断管理简介

1.3 优先级分组定义

1.4 优先级设置

1.5 用于中断屏蔽的特殊寄存器

1.5.1 PRIMASK 和 FAULTMASK 寄存器

1.5.2 BASEPRI 寄存器

2. FreeRTOS 中断配置宏

2.1 configPRIO_BITS

2.2 configLIBRARY_LOWEST_INTERRUPT_PRIORITY

2.3 configKERNEL_INTERRUPT_PRIORITY

2.4 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY

2.5 configMAX_SYSCALL_INTERRUPT_PRIORITY

3. FreeRTOS 的开关中断

4. 临界段代码

4.1 任务级临界段代码保护

4.2 中断级临界段代码保护

5. FreeRTOS 中断测试实验

5.1 实验目的

5.2 实验设计

5.3 实验程序与分析

5.4 完整代码

5.4.1 main.c

5.4.2 Timer.c

5.4.3 Timer.h


        FreeRTOS 的中断配置需要根据所使用的 MCU 来具体配置。这需要结合 MCU 架构中有关中断的知识,本节结合 Cortex-M 的 NVIC 来讲解 STM32 平台下的 FreeRTOS 中断配置;

1. Cortex-M 中断

1.1 中断简介

        中断是微控制器一个很常见的特性,中断由硬件产生,当中断产生以后 CPU 就会中断当前的流程转而去处理中断服务,Cortex-M 内核的 MCU 提供了一个用于中断管理的嵌套向量中断控制器(NVIC)。

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

1.2 中断管理简介

        Cortex-M 处理器有多个用于管理中断和异常的可编程寄存器,这些寄存器大多数都在 NVIC 和系统控制块(SCB)中,CMSIS 将这些寄存器定义为结构体。以 STM32F407 为例,打开core_cm4.h,有两个结构体,NVIC_Type 和 SCB_Type,如下:

typedef struct
{
  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
       uint32_t RESERVED0[24];
  __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
       uint32_t RSERVED1[24];
  __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
       uint32_t RESERVED2[24];
  __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
       uint32_t RESERVED3[24];
  __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
       uint32_t RESERVED4[56];
  __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
       uint32_t RESERVED5[644];
  __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
}  NVIC_Type;

typedef struct
{
  __I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
  __IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
  __IO uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */
  __IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
  __IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
  __IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
  __IO uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */
  __IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
  __IO uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */
  __IO uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */
  __IO uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */
  __IO uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */
  __IO uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */
  __IO uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */
  __I  uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */
  __I  uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */
  __I  uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */
  __I  uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */
  __I  uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */
       uint32_t RESERVED0[5];
  __IO uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
} SCB_Type;

        NVIC 和 SCB 都位于系统控制空间(SCB)内,SCS 的地址从 0XE000E000 开始,SCB 和 NVIC 的地址也在 core_cm4.h 中有定义,如下:

#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ 
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ 
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address 
 
#define SCnSCB ((SCnSCB_Type*) SCS_BASE) /*!< System control Register not in SCB */ 
#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ 
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct *// 

1.3 优先级分组定义

        当多个中断来临的时候处理器应该响应哪一个中断是由中断的优先级来决定的,高优先级的中断(优先级编号小)肯定是首先得到响应,而且高优先级的中断可以抢占低优先级的中断,这个就是中断嵌套Cortex-M 处理器的有些中断是具有固定的优先级的,比如复位、NMI(不可屏蔽中断)、HardFault,这些中断的优先级都是负数,优先级也是最高的

        Cortex-M 处理器有三个固定优先级和 256 个可编程的优先级,最多有 128 个抢占等级,但是实际的优先级数量是由芯片厂商来决定的。在实际设计时,绝大多数的芯片都会精简设计,以致实际上支持的优先级数会更少,如 8级、16级、32级等,比如 STM32 就只有 16 级优先级。在设计芯片的时候会裁掉表达优先级的几个低端有效位,以减少优先级数,所以不管用多少位来表达优先级,都是 MSB 对齐的;

        在图 4.1.3.1 中,Bit0~Bit4 没有实现,所以读它们总是返回零,写它们的话也会忽略写入的值。因此,对于 3 个位的情况,可以使用的优先级就是 8 个0x00(最高优先级)、0x20、0x40、0x60、0x80、0xA0、0xC0 和 0xE0                                                                                                                                                                                                                                        

注意:这个是芯片厂商来决定的!不是我们能决定的,比如说 STM32 就选择了 4 位作为优先级!   

        为了使抢占机能变得更可控,Cortex-M 处理器还把 256 个优先级按位分为高低两段:抢占优先级(分组优先级)和亚优先级(子优先级),NVIC 中有一个寄存器是 "应用程序中断及复位控制寄存器(AIRCR)";AIRCR 寄存器里面有个位段名为 “优先级组”,

        上图中 PRIGROUP 就是优先级分组,他把优先级分为两个位段:MSB 所在的位段(左边的)对应抢占优先级,LSB 所在的位段(右边的)对应亚优先级,也就是子优先级。

        STM32 的优先级分组情况,STM32 使用了 4 位,因此最多有 5 组优先级分组设置,这 5 个分组在 msic.h 中有定义:

#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 
 4 bits for subpriority */ 
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 
 3 bits for subpriority */ 
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值