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 )

猜你喜欢

转载自blog.csdn.net/qingfengjuechen/article/details/103344941