Changes to ARMv7-A boot logic to handle the case where we execute out of NOR FLASH

This commit is contained in:
Gregory Nutt 2013-07-29 17:54:56 -06:00
parent 1728594259
commit 5351598323
7 changed files with 139 additions and 70 deletions

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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.

View File

@ -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
#

View File

@ -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)

View File

@ -43,6 +43,7 @@
#include <debug.h>
#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 */
}