00. 目錄
文章目錄
- 00. 目錄
- 01. 概述
- 02. 任務級臨界區代碼保護
- 03.中斷級臨界區代碼保護
- 04. 預留
- 05. 預留
- 06. 附錄
- 07. 參考
01. 概述
臨界段代碼也叫做臨界區,是指那些必須完整運行,不能被打斷的代碼段,比如有的外設的初始化需要嚴格的時序,初始化程序中不能被打斷,FreeRTOS在進入臨界端代碼的時候需要關閉中斷,當處理完臨界段代碼以后再打開中斷,FreeRTOS系統本身就有很多的臨界段代碼,這些代碼都加了臨界段代碼保護,我們在寫自己的用戶程式的時候有些地方也需要添加臨界段代碼保護,
FreeRTOS與臨界段代碼保護有關的函式有4個:
/**
* task. h
*
* Macro to mark the start of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL() portENTER_CRITICAL() //任務級
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() //中斷級
/**
* task. h
*
* Macro to mark the end of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL() portEXIT_CRITICAL() //任務級
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) //中斷級
02. 任務級臨界區代碼保護
taskENTER_CRITICAL()和taskEXIT_CRITICAL()是任務級的臨界區代碼保護,一個是進入臨界區,一個是退出臨界區,這兩個函式一定要成對的使用,
/**
* task. h
*
* Macro to mark the start of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL() portENTER_CRITICAL() //任務級
/**
* task. h
*
* Macro to mark the end of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL() portEXIT_CRITICAL() //任務級
portENTER_CRITICAL()和portEXIT_CRITICAL()也是宏定義,在portmacro.h中有定義,
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
vPortEnterCritical()和vPortExitCritical()函式實作如下:
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */
if( uxCriticalNesting == 1 )
{
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
}
}
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
03.中斷級臨界區代碼保護
taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR()是中斷級別臨界區代碼保護,是用在中斷服務程式中的,而且這個中斷的優先級一定要低于預先設定的值,
/**
* task. h
*
* Macro to mark the start of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() //中斷級
/**
* task. h
*
* Macro to mark the end of a critical code region. Preemptive context
* switches cannot occur when in a critical region.
*
* NOTE: This may alter the stack (depending on the portable implementation)
* so must be used with care!
*
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) //中斷級
在portmacro.h檔案中有如下定義:
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )
ulPortRaiseBASEPRI()和vPortSetBASEPRI()相關實作
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. */
/* *INDENT-OFF* */
msr basepri, ulBASEPRI
/* *INDENT-ON* */
}
}
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. */
/* *INDENT-OFF* */
mrs ulReturn, basepri
msr basepri, ulNewBASEPRI
dsb
isb
/* *INDENT-ON* */
}
return ulReturn;
}
中斷級臨界區代碼應用示例

04. 預留
05. 預留
06. 附錄
6.1 【STM32】STM32系列教程匯總
網址:【STM32】STM32系列教程匯總
07. 參考
《FreeRTOS Reference Manual》
《Using the FreeRTOS Real Time Kernel -A Practical Guide》
《The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors,3rd Edition》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/207777.html
標籤:其他
