-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[Feature Request] <Support Cortex-A35> #316
Comments
What are the major differences between the A35 and A55 (64-bit)? |
This web page arm-cortex-a35-in-comparison comparing the Cortex-A35 and Cortex-A53. |
I don't think, there is lot of difference between Cortex-A35 and Cortex-A53 when it comes to CPU instructions, Cortex-A35 is Armv8-A 64-bit processor which is what Cortex-A53 based on. So, I believe any code that runs on Cortex-A53 should work on Cortex-A35. It just you need to figure out what the Memory Map your SBC has , and enable the Devices (GIC and UART to start with). I would like to try this out but unfortunately doesn't have an SBC with Cortex-A35. |
@Atomar25 , Thanks of your comment, according to my experience in Cortex-M23, both of Cortex-M23 and Cortex-M33 are Armv8M, the CPU instructions are similar but still need to divide as ARM_CM23 and ARM_CM33 at portable/GCC If just verify CPU core only, keil Simulator is a good choice. In Keil IDE project options, press "Debug" and check radio button of "Use Simulator". |
@RichardBarry @Atomar25 I would like to revive this request and add a few contributions from my side. I just finished making modifications to the AARCH64 port to get the kernel running on an A35 core. Details below: Target
Host
Expected Behavior Actual Behavior Modifications The STM32MP2xx microprocessor utilizes GIC v2.0 which supports interrupt grouping and security extensions. By implementation, all non-secure IRQs are routed to the GIC as IRQs and all secure IRQs are routed as FIQs. The AARCH64 port currently does not correctly handle the discovery and clearing of IRQs by interrupt group. The AARCH64 port was modified to utilize the ICCHPPIR register, in conjunction with the aliased and non-aliased ICCIAR and ICCEOIR registers, to correctly handle interrupts for this part. Interrupt pending bit clearing is delegated to user Diff portable/GCC/ARM_AARCH64/port.c diff --git a/portable/GCC/ARM_AARCH64/port.c b/portable/GCC/ARM_AARCH64/port.c
index 238874edc..7d2b3e673 100644
--- a/portable/GCC/ARM_AARCH64/port.c
+++ b/portable/GCC/ARM_AARCH64/port.c
@@ -166,9 +166,12 @@ uint64_t ullPortYieldRequired = pdFALSE;
uint64_t ullPortInterruptNesting = 0;
/* Used in the ASM code. */
-__attribute__( ( used ) ) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
-__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 ullICCHPPIR = portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_REGISTER_ADDRESS;
+__attribute__( ( used ) ) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
+__attribute__( ( used ) ) const uint64_t ullICCEOIR = portICCEOIR_END_OF_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;
__attribute__( ( used ) ) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
/*-----------------------------------------------------------*/ portable/GCC/ARM_AARCH64/portASM.S diff --git a/portable/GCC/ARM_AARCH64/portASM.S b/portable/GCC/ARM_AARCH64/portASM.S
index e684755bf..f75d34dd8 100644
--- a/portable/GCC/ARM_AARCH64/portASM.S
+++ b/portable/GCC/ARM_AARCH64/portASM.S
@@ -307,13 +307,32 @@ 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 HPPIR register
+ * This determines which interrupt group the IRQ belongs to.
+ */
+ LDR X2, ullICCHPPIRConst
+ LDR X2, [X2]
+ LDR W3, [X2]
+ CMP W3, #0x3FE
+ B.NE 1f
+
+ /* Interrupt group 1 (IRQ, nonsecure)
+ * Read from aliased register groups to get non-secure IRQ number
+ */
+2: LDR X2, ullICCAIARConst
+ MOV X1, #1
+ B 0f
+
+ /* Interrupt group 0 (FIQ, secure)
+ * Read from non-alised register groups to get secure FIQ number
+ */
+1: LDR X2, ullICCIARConst
+ MOV X1, #0
+
+0: LDR W2, [X2]
+ LDR W0, [X2]
+
+ /* Maintain the ICC(A)IAR values across the function call. */
STP X0, X1, [SP, #-0x10]!
/* Call the C handler. */
@@ -328,8 +347,21 @@ FreeRTOS_IRQ_Handler:
LDP X0, X1, [SP], #0x10
/* End IRQ processing by writing ICCIAR to the EOI register. */
- LDR X4, ullICCEOIRConst
- LDR X4, [X4]
+ CMP X1, #1
+ B.NE 1f
+
+ /* Interrupt group 1 (IRQ, nonsecure)
+ * Write to aliased EOI register.
+ */
+2: LDR X4, ullICCAEOIRConst
+ B 0f
+
+ /* Interrupt group 0 (FIQ, secure)
+ * Write to non-aliased EOI register.
+ */
+1: LDR X4, ullICCEOIRConst
+
+0: LDR W4, [X4]
STR W0, [X4]
/* Restore the critical nesting count. */
@@ -418,8 +450,11 @@ ullICCPMRConst: .dword ullICCPMR
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
ullPortInterruptNestingConst: .dword ullPortInterruptNesting
ullPortYieldRequiredConst: .dword ullPortYieldRequired
+ullICCHPPIRConst: .dword ullICCHPPIR
ullICCIARConst: .dword ullICCIAR
ullICCEOIRConst: .dword ullICCEOIR
+ullICCAIARConst: .dword ullICCAIAR
+ullICCAEOIRConst: .dword ullICCAEOIR
vApplicationIRQHandlerConst: .word vApplicationIRQHandler portable/GCC/ARM_AARCH64/portmacro.h diff --git a/portable/GCC/ARM_AARCH64/portmacro.h b/portable/GCC/ARM_AARCH64/portmacro.h
index e89abb661..b63bf31a1 100644
--- a/portable/GCC/ARM_AARCH64/portmacro.h
+++ b/portable/GCC/ARM_AARCH64/portmacro.h
@@ -200,18 +200,24 @@ void FreeRTOS_Tick_Handler( void );
/* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
+#define portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_OFFSET ( 0x18 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
+#define portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x20 )
+#define portICCAEOIR_ALIASED_END_OF_INTERRUPT_OFFSET ( 0x24 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
-#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + co
nfigINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
-#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_C
ONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
-#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRE
SS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
-#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRE
SS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
-#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRE
SS + portICCPMR_PRIORITY_MASK_OFFSET )
-#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTER
RUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
-#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTER
RUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
+#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRE
SS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
+#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTE
RRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
+#define portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCHPPIR_HIGHEST_PRIORITY_INTERRUPT_OFFSET )
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
+#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
+#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
+#define portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCAIAR_ALIASED_INTERRUPT_ACKNOWLEDGE_OFFSET )
+#define portICCAEOIR_ALIASED_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFAC
E_ADDRESS + portICCAEOIR_ALIASED_END_OF_INTERRUPT_OFFSET )
+#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( po
rtINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
+#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( po
rtINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) Hope this helps. |
Can you submit a PR with your changes? |
Is your feature request related to a problem? Please describe.
So far, the support Cortex-A CPU cores are A9 and A53. I can't find CPU core Cortex-A35 64-bit in the list.
Describe the solution you'd like
I am eager to see Cortex-A35 64-bit in GCC CPU list or RVDS CPU list ,then I could apply FreeRTOS on our Cortex-A35 platform.
Describe alternatives you've considered
None
Additional context
None
The text was updated successfully, but these errors were encountered: