在调试FreeRTOS的时候,串口输出错误信息如下:
Error:…\FreeRTOS\port\RVDS\ARM_CM7\r0p1\port.c,754
PS:这种功能真好用,出错误直接定位到文件的行数。 找到对应文件夹中第754行,这是个关于中断服务程序的断言语句。如果一个中断的优先级超过configMAX_SYSCALL_INTERRUPT_PRIORITY这个宏定义,却用了FreeRTOS的API函数,就会出现这句错误。FreeRTOS的API函数只能被优先级低于该宏定义的中断所调用。 检查了一下程序,发现确实这个中断语句使用了带有ISR的API语句。这是一个CAN中断的服务程序 而在CAN的设计当中,我把优先级设置为4.
在FreeRTOSConfig.h文件当中,找到这个宏定义是5,所以不符合使用规则,报错。这里要注意的是文件当中说优先级比这个宏高,对应的数值应该是越小。如果宏定义设置为5,那对应0-4是不可以使用FreeRTOS的API函数,5-32优先级是可以使用的。数字上的优先级和逻辑上的优先级是相反的。接下来把这个宏定义改为1,就可以避免这个问题。
接下来深入探索一下这个FreeRTOS的中断管理机制是如何定义的。进入官网看看原版是怎么说的,大部分是翻译自原文,加入部分自己的理解。 RTOS官网
介绍
数以千计的应用程序在 ARM Cortex-M 内核上运行 FreeRTOS。令人惊讶的是,对于这种 RTOS 和 ARM Cortex CPU 内核组合的技术支持请求如此之少。发生的大多数问题都是由于中断优先级设置不正确造成的。这可能是意料之中的,因为虽然 ARM Cortex-M 内核使用的中断模型功能强大,但对于习惯于更传统中断优先级方案的工程师来说,它也有些笨拙和不直观。 本页旨在描述 ARM Cortex-M 中断优先级机制,并描述它应该如何与 RTOS 内核一起使用。请记住,尽管 ARM Cortex-M3内核强加的优先级方案可能看起来很复杂,但每个官方 FreeRTOS端口都带有一个正确配置的演示应用程序,可以用作参考。此外,FreeRTOS V7.5.0 引入了额外的 configASSERT()调用,专门用于捕获错误配置的 ARM Cortex-M 中断控制器 (NVIC)。请确保在开发过程中定义了 configASSERT()。
可用的优先等级
Coretex-M硬件细节
首先要知道的是,可用优先级的总数是已经定义好的,即由使用 ARM Cortex-M 内核的微控制器的制造商决定。 因此,并非所有 ARM Cortex-M 微控制器都提供相同数量的唯一中断优先级。ARM Cortex-M 架构本身允许最多 256 个不同的优先级(最多有 8 个优先级位,因此优先级 0 到 0xff是可能的),但大多数包含 ARM Cortex-M 内核的微控制器 只允许访问其中的一个子集。 例如,TIStellaris Cortex-M3 和 ARM Cortex-M4 微控制器实现了三个优先级位。 这提供了八个唯一的优先级值。
使用RTOS关联
RTOS 中断嵌套方案将可用中断优先级分为两组 - 一部分可以被 RTOS 屏蔽,一部分不可以被RTOS屏蔽。 FreeRTOSConfig.h 中的 configMAX_SYSCALL_INTERRUPT_PRIORITY设置定义了两个组之间的边界。此设置的最佳值将取决于微控制器中实现的优先级位数。
如图所示的配置,0优先级是不受系统管理的,所以不可以调用RTOS的API函数,而1-15是可以受管理的。
抢占优先级和子优先级
Coretex-M硬件细节
8位优先级寄存器分为抢占优先级和子优先级两部分。 分配给每个部分的位数是可配置的。 抢占优先级定义了一个中断是否可以抢占一个已经在执行的中断。 当两个抢占优先级相同的中断同时发生时,子优先级决定了哪个中断先执行。
使用RTOS关联
建议将所有优先级位分配为抢占优先级位,不留任何优先级位作为子优先级位。 任何其他配置都会使configMAX_SYSCALL_INTERRUPT_PRIORITY 设置与分配给各个外设中断的优先级之间的直接关系复杂化。 大多数系统默认为所需配置,STM32 驱动程序库除外。 如果您将 STM32 与 STM32 驱动程序库一起使用,请确保在 RTOS 启动之前。通过调用 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4) 将所有优先级位分配为抢占优先级位。
在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx(在 H743 中,x=0…109)用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。但是绝大多数 CM7 芯片都会精简设计,以致实际上支持的优先级数减少,在H743 中,只使用了高 4bit,如下所示: 用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。而RTOS官方建议的分组4就是高4位全部用于表示主优先级,这个时候子优先级是不存在且不起作用的。 探究一下工程里哪里把分组设为了4。 main.c文件存在一个BSP_Init函数。 这个函数位于board.c,里面存在一个HAL_Init()文件。 这个函数位于stm32h7xx_hal.c文件,主要用于实现HAL驱动库的初始化。所以这个函数必须要在使用其他HAL函数之前先执行。 它主要完成以下几个功能: 1.配置系统时钟生成中断,因此此时外部时钟还未配置,因此系统以 16 MHz 的频率从内部 HSI 运行; 2.将 NVIC 组优先级设置为 4; 3.调用用户文件中定义的HAL_MspInit()回调函数完成底层硬件初始化;
优先级在数值和逻辑上的相反设定
Coretex-M硬件细节
接下来要知道的是,在 ARM Cortex-M 内核中,数字低优先级值用于指定逻辑上高的中断优先级。例如,分配了数字优先级值 2 的中断的逻辑优先级高于分配了数字优先级 5 的中断的逻辑优先级。换句话说,即使数字 2 较低比数字 5中断优先级 2 高于中断优先级 5。分配数字优先级为 2 的中断可以嵌套进分配数字优先级为 5 的中断,但分配数字优先级为 5 的中断不能嵌套进分配数字优先级的中断优先级 2。 这是 ARM Cortex-M 中断优先级最违反直觉的方面,因为它与大多数非 ARM Cortex-M3 微控制器架构相反。
使用RTOS关联
以“FromISR”结尾的 FreeRTOS 函数是在中断中使用安全的。 但这些函数不能在逻辑优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY 定义的优先级的中断调用。 因此,任何使用 RTOS API 函数的中断服务例程都必须手动将其优先级设置为数值上等于或大于宏定义设置的值。这确保中断的逻辑优先级等于或小于 configMAX_SYSCALL_INTERRUPT_PRIORITY 设置。Cortex-M 中断的优先级值存在0。0是最高优先的值。因此,切勿将使用 RTOS API 的中断的优先级设置为0。
这一段的意思就是如果要在中断中使用RTOS中断,那就必须把优先级的值大于那个宏定义。
重要部分
RTOS 内核使用 ARM Cortex-M 内核的 BASEPRI 寄存器实现临界区。这允许 RTOS内核仅屏蔽一部分中断,因此提供灵活的中断嵌套模型。 RTOS 内核通过将 configMAX_SYSCALL_INTERRUPT_PRIORITY 值写入 ARM Cortex-M BASEPRI 寄存器来创建临界区。 由于无法使用 BASEPRI 屏蔽优先级 0 中断(最高优先级),因此 configMAX_SYSCALL_INTERRUPT_PRIORITY 不得设置为 0。
这就是我修改设置为1的原因,因为它不允许设为0。
|