FreeRTOS(五)——中断

FreeRTOS中断配置宏

描述
configPRIO_BITS 设置MCU使用几位优先级,在STM32中使用4位
configLIBRARY_LOWEST_INTERRUPT_PRIORITY 设置最低优先级
configKERNEL_INTERRUPT_PRIORITY 设置内核中断优先级
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 设置FreeRTOS系统可管理的最大优先级
configMAX_SYSCALL_INTERRUPT_PRIORITY 见下方

configMAX_SYSCALL_INTERRUPT_PRIORITY 是宏configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY左移4位而来的,此宏设置好之后,低于此优先级的中断可以安全的调用FreeRTOS的API函数,高于此优先级的中断FreeRTOS是不能禁止的,中断服务函数也不能调用FreeRTOS的API函数。

以STM32为例,有16个优先级,0为最高优先级,15为最低优先级,配置如下:

  • #define configMAX_SYSCALL_INTERRUPT_PRIORITY 5
  • #define configKERNEL_INTERRUPT_PRIORITY 15

FreeRTOS开关中断

FreeRTOS开关中断函数为portENABLE_INTERRUPTS()portDISABLE_INTERRUPTS(),这两个函数实际上都是宏,
在portmacro.h中,定义如下:

#define  portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define  portENABLE_INTERRUPTS()  vPortSetBASEPRI(0)

函数如下:

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

	__asm
	{
		/* Set BASEPRI to the max syscall priority to effect a critical
		section. */
		msr basepri, ulNewBASEPRI
		dsb
		isb
	}
}

/*-----------------------------------------------------------*/

static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
	__asm
	{
		/* Barrier instructions are not used as this function is only used to
		lower the BASEPRI value. */
		msr basepri, ulBASEPRI
	}
}

函数vPortSetBASEPRI是向寄存器BASEPRI写入一个值,此值作为参数传递进来,传0进来就是开中断。
函数vPortRaiseBASEPRI是向寄存器BASEPRI写入宏configMAX_SYSCALL_INTERRUPT_PRIORITY,那么优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断就会被屏蔽。


临界段代码

临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如有外设的初始化需要严格的时序,初始化过程中不能被打断。FreeRTOS在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。FreeRTOS本身就有很多临界段代码,这些代码都加了临界段代码保护,我们在写自己的用户程序的时候有些地方也需要添加临界段代码保护。

任务级临界段代码保护

#define  taskENTER_CRITICAL() portENTER_CRITICAL()
#define  taskEXIT_CRITICAL()  portEXIT_CRITICAL()
#define  portENTER_CRITICAL() vPortEnterCritical()
#define  portEXIT_CRITICAL()  vPortExitCritical()

具体实现在源码文件port.c

中断级临界段代码保护

#define  taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
#define  taskEXIT_CRITICAL_FROM_ISR(x)  portCLEAR_INTERRUPT_MASK_FROM_ISR(x)
#define  portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define  portCLEAR_INTERRUPT_MASK_FROM_ISR(x)  vPortSetBASEPRI(x)

任务级临界段代码保护使用方法如下

void taskcritical_test(void)
{
	while(1)
	{
		taskENTER_CRITICAL();                    //(1)
		total_num++printf(" total_num is %d \n",total_num);
		taskEXIT_CRITICAL();            //(2)
		vTaskDelay(1000);
	}
}

(1) 进入临界区
(2) 退出临界区
注意:(1)(2)中间的代码就是临界区代码,注意临界区代码一定要精简!因为进入临界区会临时关闭中断,这样会导致优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断得不到及时的相应!

你可能感兴趣的:(FreeRTOS)