FreertOS之臨界區taskENTER_CRITICAL

taskENTER_CRITICAL()        ---lib\include\task.h

#define taskENTER_CRITICAL()		portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()

portENTER_CRITICAL()        --------lib\FreeRTOS\portable\GCC\ARM_CA53_64_BIT \portmacro.h

#define portENTER_CRITICAL()		vPortEnterCritical();
#define portEXIT_CRITICAL()			vPortExitCritical();

 vPortEnterCritical()        --------lib\FreeRTOS\portable\GCC\ARM_CA53_64_BIT\port.c

void vPortEnterCritical( void )
{
	/* Mask interrupts up to the max syscall interrupt priority. */
	uxPortSetInterruptMask();

	/* Now interrupts are disabled ullCriticalNesting can be accessed
	directly.  Increment ullCriticalNesting to keep a count of how many times
	portENTER_CRITICAL() has been called. */
	ullCriticalNesting++;

	/* 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( ullCriticalNesting == 1ULL )
	{
		configASSERT( ullPortInterruptNesting == 0 );
	}
}
/*-----------------------------------------------------------*/

void vPortExitCritical( void )
{
	if( ullCriticalNesting > portNO_CRITICAL_NESTING )
	{
		/* Decrement the nesting count as the critical section is being
		exited. */
		ullCriticalNesting--;

		/* If the nesting level has reached zero then all interrupt
		priorities must be re-enabled. */
		if( ullCriticalNesting == portNO_CRITICAL_NESTING )
		{
			/* Critical nesting has reached zero so all interrupt priorities
			should be unmasked. */
			portCLEAR_INTERRUPT_MASK();
		}
	}
}
/*-----------------------------------------------------------*/

void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
{
	if( uxNewMaskValue == pdFALSE )
	{
		portCLEAR_INTERRUPT_MASK();
	}
}
/*-----------------------------------------------------------*/

UBaseType_t uxPortSetInterruptMask( void )
{
uint32_t ulReturn;

	/* Interrupt in the CPU must be turned off while the ICCPMR is being
	updated. */
	portDISABLE_INTERRUPTS();
	if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
	{
		/* Interrupts were already masked. */
		ulReturn = pdTRUE;
	}
	else
	{
		ulReturn = pdFALSE;
		portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
		__asm volatile (	"dsb sy		\n"
							"isb sy		\n" ::: "memory" );
	}
	portENABLE_INTERRUPTS();

	return ulReturn;
}
/*-----------------------------------------------------------*/

要搞清楚這個寄存器 portICCPMR_PRIORITY_MASK_REGISTER 是幹什麼用的? 

lib\FreeRTOS\portable\GCC\ARM_CA53_64_BIT\portmacro.h

/* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET  						( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET 				( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET 					( 0x10 )
#if defined(GUEST)
#define portICCBPR_BINARY_POINT_OFFSET							( 0x1C )
#else
#define portICCBPR_BINARY_POINT_OFFSET							( 0x08 )
#endif
#define portICCRPR_RUNNING_PRIORITY_OFFSET						( 0x14 )

#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS 		( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER 					( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS 	( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS 		( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS 			( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER 					( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER 				( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )

#define portMEMORY_BARRIER() __asm volatile( "dmb ishst" ::: "memory" )

 從名字看應該是中斷控制器寄存器,查看ARM中斷控制器的文檔,IHI0048B_b_gic_architecture_specification.pdf

ARM® Generic Interrupt Controller
Architecture version 2.0
Architecture Specification
 

從文檔中看, 是屏蔽中斷用的,priority比個值高的中斷纔會被送給CPU。

總結:taskENTER_CRITICAL()    和 taskENTER_CRITICAL_FROM_ISR() 只屏蔽中斷priority比configMAX_API_CALL_INTERRUPT_PRIORITY低的那些中斷,如果一箇中斷priority比configMAX_API_CALL_INTERRUPT_PRIORITY高,那麼這個中斷依舊會被觸發執行。

 

demos\xxxxx\cortex_armv8\a1_a113l_ad4xx_xxx\FreeRTOSConfig.h

#if defined(GUEST)
#define configMAX_API_CALL_INTERRUPT_PRIORITY  10
#define configUNIQUE_INTERRUPT_PRIORITIES              16
#else
#define configMAX_API_CALL_INTERRUPT_PRIORITY  18
#define configUNIQUE_INTERRUPT_PRIORITIES              32
#endif

lib\FreeRTOS\portable\GCC\ARM_CA53_64_BIT\portmacro.h

#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )

發佈了28 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章