From 9b7e5ede0a15bf50c6cf7090e95eb741a65bb4e6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 3 Aug 2018 15:26:44 -0600 Subject: [PATCH] configs/metro-m4: Add an option to build the Metro M4 image to run out of SRAM. This ought to be a safer and quicker way to do the initial bring-up (having bricked the first Metro M4 due to a bad FLASH image). --- arch/arm/src/samd5e5/sam_start.c | 12 ++- configs/metro-m4/Kconfig | 27 ++++++- configs/metro-m4/README.txt | 48 +++++++++++- configs/metro-m4/scripts/Make.defs | 6 +- configs/metro-m4/scripts/flash.ld | 2 +- configs/metro-m4/scripts/sram.ld | 120 +++++++++++++++++++++++++++++ 6 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 configs/metro-m4/scripts/sram.ld diff --git a/arch/arm/src/samd5e5/sam_start.c b/arch/arm/src/samd5e5/sam_start.c index 070ae20173d..0e707b9b2f8 100644 --- a/arch/arm/src/samd5e5/sam_start.c +++ b/arch/arm/src/samd5e5/sam_start.c @@ -271,7 +271,9 @@ static void go_os_start(void *pv, unsigned int nbytes) void __start(void) { +#if defined(CONFIG_BOOT_RUNFROMFLASH) || defined(CONFIG_ARCH_RAMFUNCS) const uint32_t *src; +#endif uint32_t *dest; #ifdef CONFIG_ARMV7M_STACKCHECK @@ -289,6 +291,7 @@ void __start(void) *dest++ = 0; } +#ifdef CONFIG_BOOT_RUNFROMFLASH /* Move the initialized data section from his temporary holding spot in * FLASH into the correct place in SRAM. The correct place in SRAM is * give by _sdata and _edata. The temporary location is in FLASH at the @@ -299,15 +302,16 @@ void __start(void) { *dest++ = *src++; } +#endif +#ifdef CONFIG_ARCH_RAMFUNCS /* Copy any necessary code sections from FLASH to RAM. The correct - * destination in SRAM is geive by _sramfuncs and _eramfuncs. The - * temporary location is in flash after the data initalization code + * destination in SRAM is given by _sramfuncs and _eramfuncs. The + * temporary location is in flash after the data initialization code * at _framfuncs. This must be done before sam_clockconfig() can be * called (at least for the SAM4L family). */ -#ifdef CONFIG_ARCH_RAMFUNCS for (src = &_framfuncs, dest = &_sramfuncs; dest < &_eramfuncs; ) { *dest++ = *src++; @@ -333,7 +337,7 @@ void __start(void) /* For the case of the separate user-/kernel-space build, perform whatever * platform specific initialization of the user memory is required. * Normally this just means initializing the user space .data and .bss - * segements. + * segments. */ #ifdef CONFIG_BUILD_PROTECTED diff --git a/configs/metro-m4/Kconfig b/configs/metro-m4/Kconfig index b200afb586a..05450060f0f 100644 --- a/configs/metro-m4/Kconfig +++ b/configs/metro-m4/Kconfig @@ -4,4 +4,29 @@ # if ARCH_BOARD_METRO_M4 -endif + +choice + prompt "Execution memory" + default METRO_M4_RUNFROMFLASH + +config METRO_M4_RUNFROMFLASH + bool "Run from FLASH" + select BOOT_RUNFROMFLASH + ---help--- + This is the normal configuration for building METRO M4 code. + +config METRO_M4_RUNFROMSRAM + bool "Run from SRAM" + select BOOT_RUNFROMISRAM + ---help--- + During early bring-up, it is safer to execute entirely from + SRAM until you are confident in the initialization logic. + Then you can safely switch to FLASH. + + REVISIT: This auto-selects CONFIG_BOOT_RUNFROMISRAM but I have + found, with some difficulty, that that choice still defaults to + CONFIG_BOOT_RUNFROMFLASH, causing link-time failures when running + from SRAM. + +endchoice # Execution memory +endif # ARCH_BOARD_METRO_M4 diff --git a/configs/metro-m4/README.txt b/configs/metro-m4/README.txt index 9a3862012ff..f972b39761d 100644 --- a/configs/metro-m4/README.txt +++ b/configs/metro-m4/README.txt @@ -18,6 +18,16 @@ README o Built in crypto engines with AES (256 bit), true RNG, Pubkey controller o 64 QFN +Contents +======== + + o STATUS + o Unlocking FLASH + o Serial Console + o LEDs + o Run from FLASH + o Configurations + STATUS ====== @@ -47,9 +57,13 @@ STATUS This is most likely a consequence of something happening in the NuttX boot-up sequence that interferes with JTAG operation. When I continue - debugging in the future, I will put an infinitel loop, branch-on-self + debugging in the future, I will put an infinite loop, branch-on-self at the code startup up (__start) so that I can attached the debugger and step through the initial configuration. + 2019-08-03: Added a configuration option to run out of SRAM vs FLASH. + This should be a safer way to do the initial board bring-up since + it does not modify the FLASH image nor does it require unlocking + the FLASH pages. Unlocking FLASH =============== @@ -178,6 +192,38 @@ LEDs ------ ----------------- ----------- D13 PA16 GPIO output +Run from FLASH +============== + + I bricked my first Metro M4 board because there were problems in the + bring-up logic. These problems left the chip in a bad state that was + repeated on each reset because the code was written into FLASH and I was + unable to ever connect to it again via SWD. + + To make the bring-up less risky, I added a configuration option to build + the code to execution entirely out of SRAM. By default, the setting + CONFIG_METRO_M4_RUNFROMFLASH=y is used and the code is built to run out of + FLASH. If CONFIG_METRO_M4_RUNFROMSRAM=y is selected instead, then the + code is built to run out of SRAM. + + To use the code in this configuration, the program must be started a + little differently: + + gdb> mon reset + gdb> mon halt + gdb> load nuttx << Load NuttX into SRAM + gdb> file nuttx << Assuming debug symbols are enabled + gdb> mon memu32 0x20000000 << Get the address of initial stack + gdb> mon reg sp 0x200161c4 << Set the initial stack pointer using this address + gdb> mon memu32 0x20000000 << Get the address of __start entry point + gdb> mon reg pc 0x20000264 << Set the PC using this address + gdb> si << Step in just to make sure everything is okay + gdb> [ set breakpoints ] + gdb> c << Then continue until you hit the breakpoint + + Where 0x200161c4 and 0x20000264 are the values of the initial stack and + the __start entry point that I read from SRAM + Configurations ============== diff --git a/configs/metro-m4/scripts/Make.defs b/configs/metro-m4/scripts/Make.defs index 03b81d23587..cddbe4f956e 100644 --- a/configs/metro-m4/scripts/Make.defs +++ b/configs/metro-m4/scripts/Make.defs @@ -37,7 +37,11 @@ include ${TOPDIR}/.config include ${TOPDIR}/tools/Config.mk include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs -LDSCRIPT = flash.ld +ifeq ($(CONFIG_METRO_M4_RUNFROMFLASH),y) + LDSCRIPT = flash.ld +else ifeq ($(CONFIG_METRO_M4_RUNFROMSRAM),y) + LDSCRIPT = sram.ld +endif ifeq ($(WINTOOL),y) # Windows-native toolchains diff --git a/configs/metro-m4/scripts/flash.ld b/configs/metro-m4/scripts/flash.ld index 6c04fb179fa..a162f40be28 100644 --- a/configs/metro-m4/scripts/flash.ld +++ b/configs/metro-m4/scripts/flash.ld @@ -1,5 +1,5 @@ /**************************************************************************** - * configs/metro-m4/scripts/ld.script + * configs/metro-m4/scripts/flash.ld * * Copyright (C) 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/configs/metro-m4/scripts/sram.ld b/configs/metro-m4/scripts/sram.ld new file mode 100644 index 00000000000..46bbbe4c579 --- /dev/null +++ b/configs/metro-m4/scripts/sram.ld @@ -0,0 +1,120 @@ +/**************************************************************************** + * configs/metro-m4/scripts/sram.ld + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The ATSAMD51J19 has 512Kb of FLASH beginning at address 0x0000:0000 and + * 192Kb of SRAM at address 0x2000:0000. Only sram is used by this linker + * script. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x00000000, LENGTH = 512K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 192K +} + +OUTPUT_ARCH(arm) +ENTRY(_stext) +EXTERN(_vectors) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > sram + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > sram + + .ARM.extab : + { + *(.ARM.extab*) + } > sram + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > sram + __exidx_end = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } > sram + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +}