ARM_CA53: add support for FIQ

FIQ is used in the context of ARM SCP firmware instead of IRQ.
This patch adds FIQ support for this context.

Signed-off-by: Nicolas Royer <nroyer@baylibre.com>
This commit is contained in:
Nicolas Royer 2020-12-21 04:45:33 +01:00 committed by David Chalco
parent ef4c305244
commit b6a112b850
3 changed files with 58 additions and 22 deletions

View file

@ -353,7 +353,11 @@ void vPortEndScheduler( void )
void vPortEnterCritical( void )
{
/* Mask interrupts up to the max syscall interrupt priority. */
uxPortSetInterruptMask();
#if defined( configNO_INTERRUPT_MASK )
portDISABLE_INTERRUPTS();
#else
uxPortSetInterruptMask();
#endif
/* Now interrupts are disabled ullCriticalNesting can be accessed
directly. Increment ullCriticalNesting to keep a count of how many times
@ -386,7 +390,11 @@ void vPortExitCritical( void )
{
/* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */
portCLEAR_INTERRUPT_MASK();
#if defined( configNO_INTERRUPT_MASK )
portENABLE_INTERRUPTS();
#else
portCLEAR_INTERRUPT_MASK();
#endif
}
}
}
@ -411,14 +419,18 @@ void FreeRTOS_Tick_Handler( void )
}
#endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" );
#if !defined( configNO_INTERRUPT_MASK )
{
/* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" );
}
#endif /* configNO_INTERRUPT_MASK */
/* Ok to enable interrupts after the interrupt source has been cleared. */
configCLEAR_TICK_INTERRUPT();

View file

@ -140,6 +140,7 @@
/* Set the PMR register to be correct for the current critical nesting
depth. */
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
#if !defined( configNO_INTERRUPT_MASK )
MOV X1, #255 /* X1 holds the unmask value. */
LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
CMP X3, #0
@ -151,6 +152,7 @@
STR W1, [X5] /* Write the mask value to ICCPMR. */
DSB SY /* _RB_Barriers probably not required here. */
ISB SY
#endif
STR X3, [X0] /* Restore the task's critical nesting count. */
/* Restore the FPU context indicator. */
@ -232,7 +234,7 @@ FreeRTOS_SWI_Handler:
LSR X1, X0, #26
#if defined( GUEST )
#if defined( GUEST ) || defined( configUSE_SVC )
CMP X1, #0x15 /* 0x15 = SVC instruction. */
#else
CMP X1, #0x17 /* 0x17 = SMC instruction. */
@ -306,6 +308,7 @@ FreeRTOS_IRQ_Handler:
/* Maintain the interrupt nesting information across the function call. */
STP X1, X5, [SP, #-0x10]!
#if !defined( configUSE_FIQ )
/* Read value from the interrupt acknowledge register, which is stored in W0
for future parameter and interrupt clearing use. */
LDR X2, ullICCIARConst
@ -314,15 +317,21 @@ FreeRTOS_IRQ_Handler:
/* Maintain the ICCIAR value across the function call. */
STP X0, X1, [SP, #-0x10]!
#endif
/* Call the C handler. */
BL vApplicationIRQHandler
/* Disable interrupts. */
#if defined( configUSE_FIQ )
MSR DAIFSET, #1
#else
MSR DAIFSET, #2
#endif
DSB SY
ISB SY
#if !defined( configUSE_FIQ )
/* Restore the ICCIAR value. */
LDP X0, X1, [SP], #0x10
@ -330,6 +339,7 @@ FreeRTOS_IRQ_Handler:
LDR X4, ullICCEOIRConst
LDR X4, [X4]
STR W0, [X4]
#endif
/* Restore the critical nesting count. */
LDP X1, X5, [SP], #0x10
@ -416,6 +426,7 @@ ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
ullICCPMRConst: .dword ullICCPMR
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
.word 0
ullPortInterruptNestingConst: .dword ullPortInterruptNesting
ullPortYieldRequiredConst: .dword ullPortYieldRequired
ullICCIARConst: .dword ullICCIAR

View file

@ -86,7 +86,7 @@ extern uint64_t ullPortYieldRequired; \
}
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#if defined( GUEST )
#if defined( GUEST ) || defined( configUSE_SVC )
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
#else
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
@ -101,23 +101,36 @@ extern UBaseType_t uxPortSetInterruptMask( void );
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void );
#define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#if defined( configUSE_FIQ )
#define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #1" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #1" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#else
#define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" );
#endif
/* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical();
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
#ifndef configNO_INTERRUPT_MASK
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
#endif
/*-----------------------------------------------------------*/