diff --git a/arch/arm/src/armv7-r/arm.h b/arch/arm/src/armv7-r/arm.h index 1c0155e4a31..a2d64dc50fc 100644 --- a/arch/arm/src/armv7-r/arm.h +++ b/arch/arm/src/armv7-r/arm.h @@ -46,6 +46,10 @@ * Included Files ****************************************************************************/ +#ifndef __ASSEMBLY__ +# include +#endif /* __ASSEMBLY__ */ + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -109,6 +113,33 @@ extern "C" #define EXTERN extern #endif +/**************************************************************************** + * Name: arm_boot + * + * Description: + * Complete boot operations started in arm_head.S + * + * Boot Sequence + * + * 1. The __start entry point in armv7-r/arm_head.S is invoked upon power- + * on reset. + * 2. __start prepares CPU for code execution. + * 3a. If CONFIG_ARMV7R_MEMINIT is not defined, then __start will prepare + * memory resources by calling arm_data_initialize() and will then + * branch to this function. + * 3b. Otherwise, this function will be called without having initialized + * memory resources! We need to be very careful in this case. This + * function will perform MCU- and board-specific initialization which, + * among other things, must initialize memories. After initializatino + ( of the memories, this function will call arm_data_initialize() to + * initialize the memory resources + * 4. This function will then branch to os_start() to start the operating + * system. + * + ****************************************************************************/ + +void arm_boot(void) noreturn_function; + /**************************************************************************** * Name: arm_data_initialize * diff --git a/arch/arm/src/armv7-r/arm_head.S b/arch/arm/src/armv7-r/arm_head.S index 755c700f9b0..688ffebcd92 100644 --- a/arch/arm/src/armv7-r/arm_head.S +++ b/arch/arm/src/armv7-r/arm_head.S @@ -117,9 +117,7 @@ /* Imported symbols */ - .global arm_boot /* Called just before os_start */ - .global os_start /* Start the operating system */ - .global arm_data_initialize /* Perform C data initialization */ + .global arm_boot /* Branch to continue initialization in C */ .global _sbss /* Start of .bss in RAM */ .global _ebss /* End+1 of .bss in RAM */ @@ -137,7 +135,8 @@ /* Exported symbols */ .global __start /* Power-up/Reset entry point */ - .globl g_idle_topstack /* Top of the initial/IDLE stack */ + .global arm_data_initialize /* Perform C data initialization */ + .global g_idle_topstack /* Top of the initial/IDLE stack */ #ifdef CONFIG_ARCH_FPU .cpu cortex-r4 @@ -373,7 +372,8 @@ __start: /* Initialize .bss and .data ONLY if .bss and .data lie in RAM that is * ready to use. Other memory, such as SDRAM, must be initialized before * it can be used. arm_boot() will perform that memory initialization and - * .bss and .data can be initialized after arm_boot() returns. + * .bss and .data can be initialized by arm_boot() by calling this + * arm_data_initialize() later. */ bl arm_data_initialize @@ -382,43 +382,17 @@ __start: /* Perform early C-level, platform-specific initialization. Logic * within arm_boot() must configure SDRAM and call arm_data_initialize() * if CONFIG_ARMV7R_MEMINIT=y. + * + * This function does not return. It must give control to os_start() + * at the completion of its initialization. */ - bl arm_boot - -#ifdef CONFIG_STACK_COLORATION - /* Write a known value to the IDLE thread stack to support stack - * monitoring logic - */ - - adr r3, .Lstkinit - ldmia r3, {r0, r1, r2} /* R0 = start of IDLE stack; R1 = Size of tack; R2 = coloration */ - -2: /* Top of the loop */ - sub r1, r1, #1 /* R1 = Number of words remaining */ - cmp r1, #0 /* Check (nwords == 0) */ - str r2, [r0], #4 /* Save stack color word, increment stack address */ - bne 2b /* Bottom of the loop */ - -#endif - - /* Finally branch to the OS entry point */ - - mov lr, #0 /* LR = return address (none) */ - b os_start /* Branch to os_start */ + b arm_boot /* .text Data */ .Lstackpointer: .long IDLE_STACK_TOP - -#ifdef CONFIG_STACK_COLORATION - .type .Lstkinit, %object -.Lstkinit: - .long IDLE_STACK_BASE /* Beginning of the IDLE stack, then words of IDLE stack */ - .long (CONFIG_IDLETHREAD_STACKSIZE >> 2) - .long STACK_COLOR /* Stack coloration word */ -#endif .size __start, .-__start /*************************************************************************** diff --git a/arch/arm/src/tms570/tms570_boot.c b/arch/arm/src/tms570/tms570_boot.c index 489613745fb..3b3390f247b 100644 --- a/arch/arm/src/tms570/tms570_boot.c +++ b/arch/arm/src/tms570/tms570_boot.c @@ -60,6 +60,8 @@ #include "up_internal.h" #include "up_arch.h" +#include + #include "chip/tms570_sys.h" #include "chip/tms570_esm.h" #include "chip/tms570_pbist.h" @@ -143,7 +145,12 @@ static inline void tms570_check_reset(void) * do that. */ +#if 0 ASSERT((regval & SYS_ESR_FAILALL) == 0); +#else + UNUSED(regval); +#endif + #else /* Clear all reset status flags */ @@ -197,6 +204,49 @@ static void tms570_memory_initialize(uint32_t ramset) putreg32(SYS_MINITGCR_DISABLE, TMS570_SYS_MINITGCR); } +/**************************************************************************** + * Name: go_os_start + * + * Description: + * Set the IDLE stack to the + * + ****************************************************************************/ + +#ifdef CONFIG_STACK_COLORATION +static void go_os_start(void *pv, unsigned int nbytes) + naked_function noreturn_function; + +static void go_os_start(void *pv, unsigned int nbytes) +{ + /* Set the IDLE stack to the stack coloration value then jump to + * os_start(). We take extreme care here because were currently + * executing on this stack. + * + * We want to avoid sneak stack access generated by the compiler. + */ + + __asm__ __volatile__ + ( + "\tmovs r1, r1, lsr #2\n" /* R1 = nwords = nbytes >> 2 */ + "\tbeq 2f\n" /* (should not happen) */ + + "\tbic r0, r0, #3\n" /* R0 = Aligned stackptr */ + "\tmovw r2, #0xbeef\n" /* R2 = STACK_COLOR = 0xdeadbeef */ + "\tmovt r2, #0xdead\n" + + "1:\n" /* Top of the loop */ + "\tsub r1, r1, #1\n" /* R1 nwords-- */ + "\tcmp r1, #0\n" /* Check (nwords == 0) */ + "\tstr r2, [r0], #4\n" /* Save stack color word, increment stackptr */ + "\tbne 1b\n" /* Bottom of the loop */ + + "2:\n" + "\tmov r14, #0\n" /* LR = return address (none) */ + "\tb os_start\n" /* Branch to os_start */ + ); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -214,15 +264,15 @@ static void tms570_memory_initialize(uint32_t ramset) * 2. __start prepares CPU for code execution. * 3a. If CONFIG_ARMV7R_MEMINIT is not defined, then __start will prepare * memory resources by calling arm_data_initialize() and will then - * call this function. + * branch this function. * 3b. Otherwise, this function will be called without having initialized * memory resources! We need to be very careful in this case. Here, * this function will call tms570_boardinitialize() which, among other - * things, much initialize SDRAM memory. Upon return, this function - * will call arm_data_initialize() to initialize the memory resources - * 4. This function will initialize all TMS570-specific resources and - * return to __start. - * 4. _start will then branch to os_start() to start the operating system. + * things, must initialize SDRAM memory. After initializatino of the + * memories, this function will call arm_data_initialize() to + * initialize the memory resources + * 4. This function will then branch to os_start() to start the operating + * system. * ****************************************************************************/ @@ -259,7 +309,12 @@ void arm_boot(void) tms570_clockconfig(); #ifdef CONFIG_TMS570_SELFTEST - /* Run a diagnostic check on the memory self-test controller. */ + /* Run a diagnostic check on the memory self-test controller. + * + * REVISIT: This is a destructive test. It will most likely clobber the + * current stack content and result in a failure if this function were to + * attempt to return. + */ tms570_memtest_selftest(); @@ -382,4 +437,20 @@ void arm_boot(void) /* Perform common, low-level chip initialization (might do nothing) */ tms570_lowsetup(); + + /* Then start NuttX */ + +#ifdef CONFIG_STACK_COLORATION + /* Set the IDLE stack to the coloration value and jump into os_start() */ + + go_os_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE); +#else + /* Call os_start() */ + + os_start(); + + /* Shouldn't get here */ + + for (; ; ); +#endif }