HPM知识库
本栏目是先楫 MCU 开发的「一站式技术参考库」! 每周上新,为HPM开发者提供全维度的技术文档、问题解决方案、开发指南与实战教程,了解更多,请访问https://kb.hpmicro.com/
FreeRTOS在RISCV MCU上运行时,大多数的临界段保护是通过开关MSTATUS.MIE来实现的。这种实现方式的好处是简单、通用。所有的RISCV处理器都可以使用这种方式,因为这是RISCV的标准实现。
但是这种实现方式也存在一定的局限性,临界段的管理过于粗放,所有中断的响应都会被影响。在不支持中断嵌套/抢占的处理器上,这种实现没有问题,但是在支持中断嵌套/抢占和中断优先级的处理器上,这种处理方式就过于粗放了。
HPMicro的MCU的PLIC中断管理器支持中断优先级和中断抢占功能,那么有没有可能使实时性要求高的中断不受FreeRTOS的临界段保护影响呢?本文介绍一种FreeRTOS临界段保护的实现方式,可以实现此功能。
首先根据中断是否由FreeRTOS管理,将中断分为受RTOS管理的和不受RTOS管理的中断,此外由于中断和异常的入口函数相同,还需要考虑不可屏蔽的异常:
如上图显示的,当中断的优先级高于RTOS管理的优先级时,其中断处理不会被内核的任何操作所延迟,但是其中不可以调用任何FreeRTOS的API接口。
低优先级的中断处理函数中可以调用FreeRTOS的中断版本的API。
如下讨论的情况,均基于非向量模式下,开启中断嵌套/抢占的情形。
屏蔽低优先级PLIC中断,可以通过修改PLIC的THRESHOLD寄存器完成。假设想要屏蔽优先级小于等于X的中断,那么将THRESHOLD寄存器配置为X即可。优先级>X的中断不会被屏蔽。
intc_m_set_threshold(uxSavedStatusValue);
屏蔽Machine Timer中断,修改CSR寄存器MIE.MTIE即可。
__asm volatile( "csrc mie, %0" :: "r"(0x80) );
屏蔽软中断,修改CSR寄存器MIE.MSIE即可。
__asm volatile( "csrc mie, %0" :: "r"(0x08) );
对于设计目标(使高优先级PLIC中断不受RTOS临界段影响)来说,RTOS进入临界段时,需要将所有受RTOS管理的中断全部屏蔽掉。对于没有使用Machine Timer和软中断的情况来说,响应的步骤可以省略。
在中断中进入临界段时,还需要记录当前plic的threshold的值,在退出中断临界段时需要恢复
在退出临界段时,需要考虑如下的情况:
对于线程临界段来说,考虑以下两种情况:
我们解决了在线程中进入和退出临界段时的处理,现在我们来看一下在中断中退出临界段的实现:
由于tickless模式会使mcu进入低功耗模式,低功耗模式下,中断可以将mcu从低功耗模式下唤醒。在进入低功耗模式前,有一些代码需要执行;同时在退出低功耗后,有一些操作也需要执行,然后才可以去处理中断。在之前的实现中,在进入低功耗前关闭MSTATUS.MIE,保持MIE中的各中断使能位,此时发生中断时,cpu会从wfi的下一句开始执行,直到打开MSTATUS.MIE后才会跳转到中断中去处理。在此期间我们可以做一些恢复正常模式的一些准备工作。
如果低功耗期间保持MSTATUS.MIE打开的话,发生中断后,mcu会直接跳转到中断处理函数中,此时退出低功耗时需要执行的代码得不到执行,可能会导致程序执行出错。
所以进入低功耗和退出低功耗的操作代码是严格意义上的临界段代码,此时无论受RTOS管理的中断还是不受RTOS管理的中断,都不应该去响应。所以在MCU低功耗模式时,是保持MSTATUS.MIE总中断响应关闭,MIE中保持正常运行时的状态,PLIC的threashold保持为默认状态。
在HPM_SDKv1.8.0中,支持了上述的优先级管理功能,想要使用此功能,需要在工程的CMakeLists.txt中添加sdk_compile_definitions(-DUSE_SYSCALL_INTERRUPT_PRIORITY=1);然后需要在FreeRTOSConfig.h中定义configMAX_SYSCALL_INTERRUPT_PRIORITY为RTOS管理的最大优先级的值,即优先级大于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断不会被RTOS管理。
全部0条评论
快来发表一下你的评论吧 !