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

View file

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

View file

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