From 5351598323a27ac209b68a9b62f84756b2f689dd Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 29 Jul 2013 17:54:56 -0600 Subject: [PATCH] Changes to ARMv7-A boot logic to handle the case where we execute out of NOR FLASH --- arch/arm/src/armv7-a/arm_head.S | 143 ++++++++++++++++----------- arch/arm/src/armv7-a/sctlr.h | 4 +- configs/sama5d3x-ek/Kconfig | 14 ++- configs/sama5d3x-ek/README.txt | 14 +++ configs/sama5d3x-ek/ostest/defconfig | 4 +- configs/sama5d3x-ek/src/Makefile | 4 +- configs/sama5d3x-ek/src/nor_main.c | 26 ++++- 7 files changed, 139 insertions(+), 70 deletions(-) diff --git a/arch/arm/src/armv7-a/arm_head.S b/arch/arm/src/armv7-a/arm_head.S index 8007d6f60f..5eebbdb48a 100644 --- a/arch/arm/src/armv7-a/arm_head.S +++ b/arch/arm/src/armv7-a/arm_head.S @@ -189,22 +189,6 @@ * containing both. */ -/* REVISIT: This works now of the low vector case only because the RAM - * sizes that we have been dealing with are less then 1MB so that both the - * page table and the vector table are in the same 1MB RAM block. But - * this will certainly break later. Hence, the annoying warning. - */ - -#ifdef CONFIG_ARCH_LOWVECTORS -# warning REVISIT -#endif - -//#ifndef CONFIG_ARCH_LOWVECTORS - .macro mksection, section, pgtable - bic \section, \pgtable, #0x000ff000 - .endm -//#endif - /* This macro will modify r0, r1, r2 and r14 */ #ifdef CONFIG_DEBUG @@ -266,9 +250,9 @@ __start: */ #ifndef CONFIG_IDENTITY_TEXTMAP - mksection r0, r4 /* r0=phys. base section */ + ldr r0, .LCptextbase /* r0=phys. base address of .text section */ ldr r1, .LCtextflags /* R1=.text section MMU flags */ - add r3, r1, r0 /* r3=flags + base */ + orr r3, r1, r0 /* r3=flags + base */ str r3, [r4, r0, lsr #18] /* identity mapping */ #endif @@ -313,16 +297,6 @@ __start: #else /* CONFIG_PAGING */ - /* Create identity mapping for first MB of the .text section if we have - * no already done so. - */ - -#ifdef CONFIG_IDENTITY_TEXTMAP - mksection r0, r4 /* r0=phys. base section */ - ldr r1, .LCtextflags /* R1=.text section MMU flags */ - add r3, r1, r0 /* r3=flags + base */ -#endif - /* Create a virtual single section mapping for the first MB of the .text * address space. Now, we have the first 1MB mapping to both physical and * virtual addresses. The rest of the .text mapping will be completed in @@ -332,14 +306,41 @@ __start: * r4 = Address of the base of the L1 table */ - ldr r2, .LCvpgtable /* r2=virt. page table */ - mksection r0, r2 /* r0=virt. base section */ - str r3, [r4, r0, lsr #18] /* identity mapping */ +#ifdef CONFIG_IDENTITY_TEXTMAP + ldr r0, .LCptextbase /* r0=phys. base address of .text section */ + ldr r1, .LCtextflags /* R1=.text section MMU flags */ + orr r3, r1, r0 /* r3=flags + base */ +#endif + + ldr r0, .LCvtextbase /* r0=virtual base address of .text section */ + str r3, [r4, r0, lsr #18] /* Save the L1 entry using vaddress as an index */ /* NOTE: No .data/.bss access should be attempted. This temporary mapping * can only be assumed to cover the initial .text region. */ +#ifdef CONFIG_BOOT_RUNFROMFLASH + /* If we are executing from FLASH, then we will need an additional mapping + * for the page table itself (otherwise, we will crash when we try to modify + * the page table after turning the MMU on. + * + * Here we expect to have: + * r4 = Address of the base of the L1 table + * + * REVISIT: We might need this second mapping under certain conditions + * when executing from RAM too. When the RAM region is larger than 1MB + * and the page table is in the high end of RAM, then the single mapping + * above will not be sufficient. + */ + + ldr r0, .LCprambase /* r0=phys. base address of the primary RAM region */ + ldr r1, .LCramflags /* R1=MMU flags use with the primary RAM region */ + orr r3, r1, r0 /* r3=flags + base */ + + ldr r0, .LCvrambase /* r0=virtual base address of .text section */ + str r3, [r4, r0, lsr #18] /* Save the L1 entry using vaddress as an index */ + +#endif /* CONFIG_BOOT_RUNFROMFLASH */ #endif /* CONFIG_PAGING */ #endif /* CONFIG_ARCH_ROMPGTABLE */ @@ -520,14 +521,30 @@ __start: * PC_Relative Data ****************************************************************************/ - /* Most addresses are virtual address */ - + /* The virtual start address of the second phase boot logic */ + .type .LCvstart, %object .LCvstart: .long .Lvstart .size .LCvstart, . -.LCvstart #ifndef CONFIG_ARCH_ROMPGTABLE + /* The aligned, physical base address of the .text section */ + + .type .LCptextbase, %object +.LCptextbase: + .long NUTTX_TEXT_PADDR & 0xfff00000 + .size .LCptextbase, . -.LCptextbase + + /* The aligned, virtual base address of the .text section */ + + .type .LCvtextbase, %object +.LCvtextbase: + .long NUTTX_TEXT_VADDR & 0xfff00000 + .size .LCvtextbase, . -.LCvtextbase + + /* The MMU flags used with the .text mapping */ + .type .LCtextflags, %object .LCtextflags: #ifdef CONFIG_BOOT_RUNFROMFLASH @@ -536,7 +553,35 @@ __start: .long MMU_MEMFLAGS /* MMU flags for text section in RAM */ #endif .size .LCtextflags, . -.LCtextflags + +#if !defined(CONFIG_PAGING) +#ifdef CONFIG_BOOT_RUNFROMFLASH + /* The physical base address of the primary RAM region */ + + .type .LCprambase, %object +.LCprambase: + .long NUTTX_RAM_PADDR & 0xfff00000 + .size .LCprambase, . -.LCprambase + + /* The virtual base address of the primary RAM region */ + + .type .LCvrambase, %object +.LCvrambase: + .long NUTTX_RAM_VADDR & 0xfff00000 + .size .LCvrambase, . -.LCvrambase + + /* The MMU flags used with the primary RAM region */ + + .type .LCramflags, %object +.LCramflags: + .long MMU_MEMFLAGS /* MMU flags for RAM section */ + .size .LCramflags, . -.LCramflags #endif +#endif + +#endif + + /* The physical base address of the page table */ .type .LCppgtable, %object .LCppgtable: @@ -544,6 +589,8 @@ __start: .size .LCppgtable, . -.LCppgtable #ifndef CONFIG_ARCH_ROMPGTABLE + /* The virtual base address of the page table */ + .type .LCvpgtable, %object .LCvpgtable: .long PGTABLE_BASE_VADDR /* Virtual start of page table */ @@ -609,11 +656,10 @@ __start: #ifndef CONFIG_ARCH_ROMPGTABLE #ifndef CONFIG_IDENTITY_TEXTMAP - ldr r4, .LCvpgtable /* r4=virtual page table */ - ldr r1, .LCppgtable /* r1=phys. page table */ - mksection r3, r1 /* r2=phys. base addr */ + ldr r4, .LCvpgtable /* r4=virtual page table base address */ + ldr r3, .LCvtextbase /* r0=virtual base address of .text section */ mov r0, #0 /* flags + base = 0 */ - str r0, [r4, r3, lsr #18] /* Undo identity mapping */ + str r3, [r4, r3, lsr #18] /* identity mapping */ #endif #if defined(CONFIG_PAGING) @@ -640,7 +686,7 @@ __start: #ifdef CONFIG_IDENTITY_TEXTMAP ldr r4, .LCvpgtable /* r4=virtual page table */ #endif - ldr r3, .LCnuttxptext /* r3=Aligned Nuttx start address (physical) */ + ldr r3, .LCptextbase /* r3=Aligned Nuttx start address (physical) */ /* Now setup the page tables for our normal mapped execution region. * We round NUTTX_TEXT_VADDR down to the nearest megabyte boundary. @@ -676,7 +722,7 @@ __start: /* Get R3 = Value of RAM L1 page table entry */ - ldr r3, .LCnuttxpram /* r3=Aligned Nuttx RAM address (physical) */ + ldr r3, .LCprambase /* r3=Aligned Nuttx RAM address (physical) */ ldr r1, .LCramflags /* R1=.bss/.data section MMU flags */ add r3, r3, r1 /* r3=flags + base */ @@ -759,25 +805,6 @@ __start: .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4 .size .Linitparms, . -.Linitparms -#if !defined(CONFIG_PAGING) - .type .LCnuttxptext, %object -.LCnuttxptext: - .long NUTTX_TEXT_PADDR & 0xfff00000 - .size .LCnuttxptext, . -.LCnuttxptext - -#ifdef CONFIG_BOOT_RUNFROMFLASH - .type .LCramflags, %object -.LCramflags: - .long MMU_MEMFLAGS /* MMU flags for RAM section */ - .size .LCramflags, . -.LCramflags - - .type .LCnuttxpram, %object -.LCnuttxpram: - .long NUTTX_RAM_PADDR & 0xfff00000 - .size .LCnuttxpram, . -.LCnuttxpram -#endif -#endif - #ifdef CONFIG_PAGING .type .Ldataspan, %object diff --git a/arch/arm/src/armv7-a/sctlr.h b/arch/arm/src/armv7-a/sctlr.h index 07959ef45a..c0a53dbb9b 100644 --- a/arch/arm/src/armv7-a/sctlr.h +++ b/arch/arm/src/armv7-a/sctlr.h @@ -285,7 +285,7 @@ static inline unsigned int cp15_rdsctlr(void) unsigned int sctlr; __asm__ __volatile__ ( - "\tmrc p15, 0, %0, c1, c0, 0" + "\tmrc p15, 0, %0, c1, c0, 0\n" : "=r" (sctlr) : : "memory" @@ -298,7 +298,7 @@ static inline void cp15_wrsctlr(unsigned int sctlr) { __asm__ __volatile__ ( - "\tmcr p15, 0, $0, c1, c0, 0\n" + "\tmcr p15, 0, %0, c1, c0, 0\n" "\tnop\n" "\tnop\n" "\tnop\n" diff --git a/configs/sama5d3x-ek/Kconfig b/configs/sama5d3x-ek/Kconfig index 58f94967ea..5f977fe164 100644 --- a/configs/sama5d3x-ek/Kconfig +++ b/configs/sama5d3x-ek/Kconfig @@ -11,6 +11,18 @@ config SAMA5_NOR_MAIN depends on SAMA5_BOOT_ISRAM ---help--- nor_main is a tiny program that runs in ISRAM. nor_main will enable - NOR flash then jump to the program in NOR flash + NOR flash then either (1) jump to the program in NOR flash or (2) + wait for you to break in with GDB to debug the NOR program. + +config SAMA5_NOR_START + bool "Start NOR program" + default n + depends on SAMA5_NOR_MAIN + ---help--- + The default behavior of the NOR boot program is to initialize the + NOR FLASH at CS0, then patiently wait for you to break into the + program with GDB. An alternative behvior is enabled with this + option: If SAMA5_NOR_START is defined, then it will not wait but + will, instead, immediately start the program in NOR FLASH. endif diff --git a/configs/sama5d3x-ek/README.txt b/configs/sama5d3x-ek/README.txt index e20c0b221f..98c716ae94 100644 --- a/configs/sama5d3x-ek/README.txt +++ b/configs/sama5d3x-ek/README.txt @@ -699,6 +699,20 @@ Configurations STATUS: 2013-7-28: This configuration was verified functional. + norboot: + This is a little program to help debug of code in NOR flash. It + does the following: + + - It enables and configures NOR FLASH, then + - Waits for you to break in with GDB. + + At that point, you can set the PC and begin executing from NOR FLASH + under debug control. + + NOTES: + 1. This program derives from the hello configuration. All of the + notes there apply to this configuration as well. + ostest: This configuration directory, performs a simple OS test using examples/ostest. diff --git a/configs/sama5d3x-ek/ostest/defconfig b/configs/sama5d3x-ek/ostest/defconfig index 9290872214..5d1010ad1c 100644 --- a/configs/sama5d3x-ek/ostest/defconfig +++ b/configs/sama5d3x-ek/ostest/defconfig @@ -228,8 +228,8 @@ CONFIG_BOOT_RUNFROMFLASH=y CONFIG_RAM_START=0x00304000 CONFIG_RAM_VSTART=0x00304000 CONFIG_RAM_SIZE=114688 -CONFIG_FLASH_START=0x1000000 -CONFIG_FLASH_VSTART=0x1000000 +CONFIG_FLASH_START=0x10000000 +CONFIG_FLASH_VSTART=0x10000000 CONFIG_FLASH_SIZE=134217728 # diff --git a/configs/sama5d3x-ek/src/Makefile b/configs/sama5d3x-ek/src/Makefile index 940bdbb5c2..1ae5ae4cf4 100644 --- a/configs/sama5d3x-ek/src/Makefile +++ b/configs/sama5d3x-ek/src/Makefile @@ -73,11 +73,11 @@ ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src ifeq ($(WINTOOL),y) CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" - CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/armv7-m}" + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/armv7-a}" else CFLAGS += -I$(ARCH_SRCDIR)/chip CFLAGS += -I$(ARCH_SRCDIR)/common - CFLAGS += -I$(ARCH_SRCDIR)/armv7-m + CFLAGS += -I$(ARCH_SRCDIR)/armv7-a endif all: libboard$(LIBEXT) diff --git a/configs/sama5d3x-ek/src/nor_main.c b/configs/sama5d3x-ek/src/nor_main.c index 3c90b8a770..96d881dfb5 100644 --- a/configs/sama5d3x-ek/src/nor_main.c +++ b/configs/sama5d3x-ek/src/nor_main.c @@ -43,6 +43,7 @@ #include #include "up_arch.h" +#include "sctlr.h" #include "sam_periphclks.h" #include "chip/sam_hsmc.h" @@ -114,18 +115,33 @@ int nor_main(int argc, char *argv) HSMC_MODE_TDFCYCLES(1); putreg32(regval, SAM_HSMC_MODE(HSMC_CS0)); + /* Disable the caches and the MMU. Disabling the MMU should be safe here + * because there is a 1-to-1 identity mapping between the physical and + * virtual addressing. + */ + +#if 0 /* Causes a crash */ + printf("Disabling the caches and the MMU\n"); + regval = cp15_rdsctlr(); + regval &= ~(SCTLR_M | SCTLR_C | SCTLR_I); + cp15_wrsctlr(regval); +#endif + +#ifdef SAMA5_NOR_START /* Then jump into NOR flash */ -#if 1 - printf("Waiting for GDB halt\n"); - fflush(stdout); - for (;;); -#else printf("Jumping to NOR flash on CS0\n"); fflush(stdout); usleep(500*1000); NOR_ENTRY(); +#else + /* Or just wait patiently for the user to break in with GDB. */ + + printf("Waiting for GDB halt\n"); + fflush(stdout); + for (;;); #endif + return 0; /* NOR_ENTRY() should not return */ }