Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding GIC v2 interrupt group handling to GCC_AARCH64 port. #1135

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions portable/GCC/ARM_AARCH64/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ __attribute__( ( used ) ) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRU
__attribute__( ( used ) ) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__attribute__( ( used ) ) const uint64_t ullICCHPPIR = portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint64_t ullICCAIAR = portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint64_t ullICCAEOIR = portICCAEOIR_ALIASED_END_OF_INTERRUPT_REGISTER_ADDRESS;

/*-----------------------------------------------------------*/

Expand Down
59 changes: 48 additions & 11 deletions portable/GCC/ARM_AARCH64/portASM.S
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,34 @@ FreeRTOS_IRQ_Handler:
/* Maintain the interrupt nesting information across the function call. */
STP X1, X5, [SP, #-0x10]!

/* Read value from the interrupt acknowledge register, which is stored in W0
for future parameter and interrupt clearing use. */
LDR X2, ullICCIARConst
LDR X3, [X2]
LDR W0, [X3] /* ICCIAR in W0 as parameter. */

/* Maintain the ICCIAR value across the function call. */
/* Read value from the HPPI register
* In GIC v2, the HPPI register will contain:
* - 0x3FF on GIC ack or spurious IRQ
* - 0x3FE on pending IRQ within Group 1 (IRQ, non-secure)
* - IRQn on pending IRQ within Group 0 (FIQ, secure)
*
* X0 to contain IRQn
* X1 to contain IRQn Group number
*/
LDR X2, ullICCHPPIRConst
LDR X2, [X2]
LDR W3, [X2]
CMP W3, #0x3FE
B.NE 1f

/* if IRQn Group 1, AIAR contains IRQn */
2: LDR X2, ullICCAIARConst
MOV X1, #1
B 0f

/* if IRQn Group 0, IAR contains IRQn */
1: LDR X2, ullICCIARConst
MOV X1, #0

0: LDR W2, [X2]
LDR W0, [X2]

/* Maintain the IRQn value across the function call. */
STP X0, X1, [SP, #-0x10]!

/* Call the C handler. */
Expand All @@ -324,12 +345,25 @@ FreeRTOS_IRQ_Handler:
DSB SY
ISB SY

/* Restore the ICCIAR value. */
/* Restore the IRqn value. */
LDP X0, X1, [SP], #0x10

/* End IRQ processing by writing ICCIAR to the EOI register. */
LDR X4, ullICCEOIRConst
LDR X4, [X4]
/* End IRQ processing by writing to the EOI register.
* In GIV v2, the EOI register to be used depends on the interrupt group:
* - IRQn Group 0 -> EOI
* - IRQn Group 1 -> AEOI
*/
CMP X1, #1
B.NE 1f

/* if IRQn Group 1, use AEOIR */
2: LDR X4, ullICCAEOIRConst
B 0f

/* if IRQn Group 0, use EOIR */
1: LDR X4, ullICCEOIRConst

0: LDR W4, [X4]
STR W0, [X4]

/* Restore the critical nesting count. */
Expand Down Expand Up @@ -420,6 +454,9 @@ ullPortInterruptNestingConst: .dword ullPortInterruptNesting
ullPortYieldRequiredConst: .dword ullPortYieldRequired
ullICCIARConst: .dword ullICCIAR
ullICCEOIRConst: .dword ullICCEOIR
ullICCHPPIRConst: .dword ullICCHPPIR
ullICCAIARConst: .dword ullICCAIAR
ullICCAEOIRConst: .dword ullICCAEOIR
vApplicationIRQHandlerConst: .word vApplicationIRQHandler


Expand Down
21 changes: 14 additions & 7 deletions portable/GCC/ARM_AARCH64/portmacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,21 @@ void FreeRTOS_Tick_Handler( void );
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_OFFSET ( 0x18 )
#define portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x20 )
#define portICCAEOIR_ALIASED_END_OF_INTERRUPT_OFFSET ( 0x24 )

#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 portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_OFFSET )
#define portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCAEOIR_ALIASED_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCAEOIR_ALIASED_END_OF_INTERRUPT_OFFSET )

#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 ( "" ::: "memory" )

Expand Down