FreeRTOS专题四:临界段的保护

临界段用一句话概括就是一段在执行的时候不能被中断的代码段。

在 FreeRTOS 里面,这个临界段最常出现的就是对全局变量的操作。那么什么情况下临界段会被打断?一个是系统调度,还有一个就是外部中断。在FreeRTOS,系统调度,最终也是产生PendSV 中断,在 PendSV Handler 里面实现任务的切换,所以还是可以归结为中断。既然这样,FreeRTOS 对临界段的保护最终还是回到对中断的开和关的控制

如果我们先关掉中断,然后执行一段程序,此时即使有中断产生,系统也不会响应,则这段程序被保护起来,灯带执行完毕再开启中断,这就是临界段保护的原理。

在 FreeRTOS 中,对中断的开和关是通过操作 BASEPRI 寄存器来实现的,即大于等于 BASEPRI 的值的中断会被屏蔽,小于 BASEPRI 的值的中断则不会被屏蔽,不受FreeRTOS 管理。用户可以设置 BASEPRI 的值来选择性的给一些非常紧急的中断留一条后路。

FreeRTOS专题四:临界段的保护_第1张图片

1 关中断。分为两种:不带返回值和带返回值。

不带返回值:

#define portDISABLE_INTERRUPTS()				vPortRaiseBASEPRI()

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
	}
}

不带返回值的意思是:在往 BASEPRI 写入新的值的时候,不用先将 BASEPRI 的值保存起来,即不用管当前的中断状态是怎么样的,既然不用管当前的中断状态,也就意味着这样的函数不能在中断里面调用。

带返回值:

基本类似,但是会先保存当前的BASEEPRI值

static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

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

	return ulReturn;
}

 

开中断:一样的,分为不带传入参数和带传入参数的两种。

不带参数:

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

带参数:

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
	}
}

临界段的应用:

FreeRTOS专题四:临界段的保护_第2张图片

 

你可能感兴趣的:(FreeRTOS专题四:临界段的保护)