原创 四、freeRTOS与Cortex - M中断

2020-8-23 16:20 1561 14 14 分类: 汽车电子 文集: FreeRTOS

Cortex - M中断

1 中断简介

中断与异常

可以看到,中断源的个数和优先级的位数,都是由芯片厂商决定的(stm32的中断优先级为高4位)

系统异常清单:

2 NVIC 寄存器设计

手册中关于NVIC的描述:

NVIC寄存器详细说明:

1 中断的使能与除能

对应的寄存器描述:

对应的stm32标准库中的结构体:

中断悬起/解悬寄存器:

中断优先级设置寄存器:

以上是外部中断的优先级,系统异常的优先级设置如下:

中断激活位寄存器:

中断优先级的定义:

抢占优先级与子优先级设置:

应用程序中断及复位控制寄存器描述:

在 HAL 库中,有中断优先级分组的设置:

这个寄存器设置在SCB(系统控制寄存器)中,如下所示:

CM3内核与stm32中断向量的对应关系(中断向量表):

这与下面的ARM-Cortex内核是相对应的:

系统异常是由 ARM 设计的,不能修改。

外部中断是由ST设计的,通过设置IP(中断优先级)寄存器来设置,如下所示:

这个和stm32f10x.h中的设置是一致的;

实际上,stm32也是通过IP寄存器来设置中断优先级的,如下所示:

对于 FreeRTOS 中比较重要的是,PendSV 和 SysTick 这两个中断。

注意这个地址,0XE000_ED20,实际上这里包含 4 个 8位优先级设置寄存器。

在调度器函数源码中,有设置 PendSV 和 SysTick 中断优先级的代码,如下所示:

  1. #ifdef __NVIC_PRIO_BITS
  2. #define configPRIO_BITS __NVIC_PRIO_BITS // 4
  3. #else
  4. #define configPRIO_BITS 4
  5. #endif
  6. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级
  7. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级
  8. // 15 << (8 - 4) 将高4位的中断优先级设置成15,即最低优先级
  9. #define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
  10. #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
  11. #define portNVIC_SYSPRI2_REG (*((volatile uint32_t *)0xe000ed20))
  12. #define portNVIC_PENDSV_PRI (((uint32_t)configKERNEL_INTERRUPT_PRIORITY) << 16UL)
  13. #define portNVIC_SYSTICK_PRI (((uint32_t)configKERNEL_INTERRUPT_PRIORITY) << 24UL)
  14. /*
  15. * See header file for description.
  16. */
  17. BaseType_t xPortStartScheduler(void)
  18. {
  19. /* Make PendSV and SysTick the lowest priority interrupts. */
  20. // 通过绝对地址,将PendSV SysTick中断优先级设置成15
  21. portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
  22. portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
  23. }

中断屏蔽

PRIMASK 与 FAULTMASK

在 UCOS 操作系统中,进入临界段使用的就是 PRIMASK 寄存器,会屏蔽掉几乎所有的寄存器。

而在 FreeRTOS 中,使用的是 BASEPRI 寄存器,实现更加精细的控制,如下所示:

如果设置写入的优先级为5,则 0 ~ 4的优先级无法被屏蔽,5及以上的中断都会被屏蔽。

  1. #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
  2. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 // 中断最低优先级
  3. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 // 系统可管理的最高中断优先级
  4. #define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
  5. // 设置系统调用的中断优先级为5
  6. #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
  7. #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
  8. static portFORCE_INLINE void vPortRaiseBASEPRI(void)
  9. {
  10. uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
  11. __asm
  12. {
  13. /* Set BASEPRI to the max syscall priority to effect a critical
  14. section. */
  15. msr basepri, ulNewBASEPRI // 将设置的中断屏蔽优先级写入到 BASEPRI 寄存器中
  16. dsb
  17. isb
  18. }
  19. }
  20. portDISABLE_INTERRUPTS(); // 关闭中断

进入 / 退出中断的函数(其实就是写0 / 写入 BASEPRI寄存器):

  1. portDISABLE_INTERRUPTS(); // 关闭中断
  2. portENABLE_INTERRUPTS(); // 打开中断

关于 FreeRTOS 与中断屏蔽的说明:

 转载于:https://blog.csdn.net/dingyc_ee/article/details/104054941

文章评论0条评论)

登录后参与讨论
我要评论
0
14
关闭 站长推荐上一条 /2 下一条