FreeRTOS常见知识点
1、临界段代码
临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如某些外设的初始化需要严格的时序,且不能被打断。FreeRTOS提供的解决方案是在进入临界区时关闭中断,在离开时恢复中断,这就是临界段代码保护。
FreeRTOS提供了四个API来实现临界段代码保护:taskENTER_CRITICAL()、taskEXIT_CRITICAL()、taskENTER_CRITICAL_FROM_ISR()、taskEXIT_CRITICAL_FROM_ISR()。可以从名字上看出这四个API成两对,前两个是任务级的临界段代码保护,后两个是中断级的临界段代码保护。他们都在task.h中定义,且都是宏定义。
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
1.1 任务级临界段代码保护
portENTER_CRITICAL()、portEXIT_CRITICAL()代码定义在portmacro.h中,代码如下;
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
API实现在prot.c中,代码如下:
extern void disableSYSIRQ(void);
extern void enablesysIRQ(void);
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
disableSYSIRQ();
uxCriticalNesting++;
}
void vPortExitCritical( void )
{
if(uxCriticalNesting>0)
uxCriticalNesting--;
if(uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
enablesysIRQ();
}
}
API相对简单,重点关注的嵌套处理,即uxCriticalNesting的处理。
1.2 中断级临界段代码保护
同样,API接口portSET_INTERRUPT_MASK_FROM_ISR() 、portCLEAR_INTERRUPT_MASK_FROM_ISR(x)定义在portmacro.h中。
备注:代码的实现和所用到的开发板有关,具体代码有差异。本文是基于Cotex-M核开发板编写的,请注意。
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
实现在prot.c中。根据读者使用的开发板决定如何是实现。
__asm unsigned long ulPortSetInterruptMask( void )
{
PRESERVE8
mrs r0, basepri
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14
}
__asm void vPortClearInterruptMask( unsigned long ulNewMask )
{
PRESERVE8
msr basepri, r0
bx r14
}
在Cotex-M中BASESPI寄存器定义了被屏蔽中断的阈值。当它被设置成某个值时,所有优先级大于等于该值的中断都将被关闭(优先级值越大,优先级越低),但若被设成0,则不关闭任何中断,0也是缺省值。#configMAX_SYSCALL_INTERRUPT_PRIORITY 该配置就是FreeRTOS中开发人员确定的阈值,该配置在FreeRTOSConfig.h中定义。
作者知识有限,如有错误,欢迎指正!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)