From c168e147d6c16aaf4736dfe936f45dc77edb8714 Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Tue, 4 Feb 2020 10:01:31 +0800 Subject: [PATCH 1/2] M2351: Support GCC 1. Enable GCC support on non-secure targets 2. Disable GCC support on secure targets becasue of GCC bug (as of 9-2019-q4-major): In non-secure entry function, callee-saved registers must be restored, but they are incorrectly cleared at optimization level "Os". --- targets/targets.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/targets/targets.json b/targets/targets.json index bebf612674..3b8ff7fd3e 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -12672,6 +12672,7 @@ "trustzone": true, "supported_toolchains": [ "ARMC6", + "GCC_ARM", "IAR" ], "extra_labels_add": [ @@ -12733,6 +12734,7 @@ "core": "Cortex-M23-NS", "supported_toolchains": [ "ARMC6", + "GCC_ARM", "IAR" ], "tfm.level": 1, From 9faa236dfcde7c2f6e3782a65fa2da8997d37ad6 Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Mon, 3 Feb 2020 17:19:21 +0800 Subject: [PATCH 2/2] M2351: Refactor startup file 1. Re-organize to make clear for all targets/toolchains support in single startup file 2. Inline assembly syntax is limited, esp. on IAR. Try paving the way for accessing external symbols still in inline assembly instead of re-write in assembly. --- .../TARGET_M2351/device/startup_M2351.c | 97 +++++++++++++------ 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/device/startup_M2351.c b/targets/TARGET_NUVOTON/TARGET_M2351/device/startup_M2351.c index 5045697770..ad89beaa76 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/device/startup_M2351.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/device/startup_M2351.c @@ -54,18 +54,33 @@ void FUN(void) __attribute__ ((weak, alias(#FUN_ALIAS))); #endif - /* Initialize segments */ #if defined(__ARMCC_VERSION) #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) extern uint32_t Image$$ARM_LIB_STACK_MSP$$ZI$$Limit; +extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; #else extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; #endif extern void __main(void); #elif defined(__ICCARM__) +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) +extern uint32_t Image$$ARM_LIB_STACK_MSP$$ZI$$Limit; +extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; +extern uint32_t CSTACK_MSP$$Limit; +extern uint32_t CSTACK$$Limit; +#else +extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; +extern uint32_t CSTACK$$Limit; +#endif void __iar_program_start(void); #elif defined(__GNUC__) +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) +extern uint32_t Image$$ARM_LIB_STACK_MSP$$ZI$$Limit; +extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; +#else +extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit; +#endif extern uint32_t __StackTop; extern uint32_t __copy_table_start__; extern uint32_t __copy_table_end__; @@ -195,12 +210,6 @@ WEAK_ALIAS_FUNC(TRNG_IRQHandler, Default_Handler) // 101: __attribute__ ((section("RESET"))) const uint32_t __vector_handlers[] = { #elif defined(__ICCARM__) -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) -extern uint32_t CSTACK_MSP$$Limit; -extern uint32_t CSTACK$$Limit; -#else -extern uint32_t CSTACK$$Limit; -#endif const uint32_t __vector_table[] @ ".intvec" = { #elif defined(__GNUC__) __attribute__ ((section(".vector_table"))) @@ -347,65 +356,91 @@ const uint32_t __vector_handlers[] = { (uint32_t) TRNG_IRQHandler, // 101: }; -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - /* Some reset handler code cannot implement in pure C. Implement it in inline/embedded assembly. * * Reset_Handler: - * For non-secure PSA/non-secure non-PSA/secure non-PSA, do as usual - * For secure PSA, switch from MSP to PSP, then jump to Reset_Handler_1 for usual work + * For non-secure PSA/non-secure non-PSA/secure non-PSA, jump directly to Reset_Handler_1 + * For secure PSA, switch from MSP to PSP, then jump to Reset_Handler_1 * - * Reset_Handler_1 + * Reset_Handler_1: + * Platform initialization * C/C++ runtime initialization */ +/* Forward declaration */ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) +/* Limited by inline assembly syntax, esp. on IAR, we cannot get stack limit + * for PSP just from external symbol. To avoid re-write in assembly, We make up + * a function here to get this value indirectly. */ +uint32_t StackLimit_PSP(void); +#endif void Reset_Handler_1(void); /* Add '__attribute__((naked))' here to make sure compiler does not generate prologue and * epilogue sequences for Reset_Handler. We don't want MSP is updated by compiler-generated - * code during stack switch. */ + * code during stack switch. + * + * Don't allow extended assembly in naked functions: + * The compiler only supports basic __asm statements in __attribute__((naked)) + * functions. Using extended assembly, parameter references or mixing C code with + * __asm statements might not work reliably. + */ __attribute__((naked)) void Reset_Handler(void) { -#if !defined(__ICCARM__) +#if defined(__GNUC__) __asm(".syntax unified \n"); - __asm(".globl Reset_Handler_1 \n"); #endif /* Secure TFM requires PSP as boot stack */ -#if TFM_LVL != 0 +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) + /* Get stack limit for PSP */ #if !defined(__ICCARM__) - __asm(".globl Image$$ARM_LIB_STACK$$ZI$$Limit \n"); - __asm("movw r0, #:lower16:Image$$ARM_LIB_STACK$$ZI$$Limit \n"); // Initialize PSP - __asm("movt r0, #:upper16:Image$$ARM_LIB_STACK$$ZI$$Limit \n"); + __asm("movw r0, #:lower16:StackLimit_PSP \n"); + __asm("movt r0, #:upper16:StackLimit_PSP \n"); #else - __asm(".globl Image$$ARM_LIB_STACK$$ZI$$Limit \n"); - __asm("mov32 r0, Image$$ARM_LIB_STACK$$ZI$$Limit \n"); + __asm("mov32 r0, StackLimit_PSP \n"); #endif + __asm("blx r0 \n"); + + /* Switch from MSP to PSP */ __asm("msr psp, r0 \n"); - __asm("mrs r0, control \n"); // Switch SP to PSP + __asm("mrs r0, control \n"); __asm("movs r1, #2 \n"); __asm("orrs r0, r1 \n"); __asm("msr control, r0 \n"); #endif + /* Jump to Reset_Handler_1 */ #if !defined(__ICCARM__) __asm("movw r0, #:lower16:Reset_Handler_1 \n"); __asm("movt r0, #:upper16:Reset_Handler_1 \n"); #else - __asm("mov32 r0, Reset_Handler_1 \n"); + __asm("mov32 r0, Reset_Handler_1 \n"); #endif __asm("bx r0 \n"); } +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && (TFM_LVL > 0) +/* Return stack limit for PSP */ +uint32_t StackLimit_PSP(void) +{ + uint32_t stacklimit_psp; + + __asm volatile ( +#if defined(__GNUC__) + ".syntax unified \n" +#endif + "mov %[Rd], %[Rn] \n" + : [Rd] "=r" (stacklimit_psp) /* comma-separated list of output operands */ + : [Rn] "r" (&Image$$ARM_LIB_STACK$$ZI$$Limit) /* comma-separated list of input operands */ + : "cc" /* comma-separated list of clobbered resources */ + ); + + return stacklimit_psp; +} +#endif + void Reset_Handler_1(void) - -#else - -void Reset_Handler(void) - -#endif /* defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ - - { #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) /* Disable register write-protection function */