From 16c4ea72eceacd132350c633f95f8fe632c01ff0 Mon Sep 17 00:00:00 2001
From: Gregory Nutt <gnutt@nuttx.org>
Date: Wed, 2 Apr 2014 12:54:15 -0600
Subject: [PATCH] SAMA5:  When running from SRAM, vectors must lie in ISRAM

---
 ChangeLog                                    |  3 +-
 arch/arm/src/sama5/chip/sama5d3x_memorymap.h | 24 +++++--
 arch/arm/src/sama5/sam_boot.c                | 72 ++++++++++++++------
 arch/arm/src/sama5/sam_irq.c                 | 15 ++--
 4 files changed, 84 insertions(+), 30 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3165033ecd..139e4f6041 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7111,4 +7111,5 @@
 	* libc/stdio/lib_sccanf.c:  Use stroul() vs strol() with %u format
 	  otherwise, range of values is restricted because of sign bit
 	  from kfrolov (2014-4-2).
-
+	* arch/arm/src/sama5/sam_boot.c, sam_irq.c, chip/sama5d3x_memorymap.h:
+	  When running from SDRAM, vectors must lie in SRAM (2014-4-2).
diff --git a/arch/arm/src/sama5/chip/sama5d3x_memorymap.h b/arch/arm/src/sama5/chip/sama5d3x_memorymap.h
index 5a8d23fae6..fe2e02672e 100644
--- a/arch/arm/src/sama5/chip/sama5d3x_memorymap.h
+++ b/arch/arm/src/sama5/chip/sama5d3x_memorymap.h
@@ -594,10 +594,10 @@
    * in the way at that position.
    */
 
-#  if defined(CONFIG_BOOT_RUNFROMISRAM) && defined(CONFIG_ARCH_LOWVECTORS)
+#  if defined(CONFIG_SAMA5_BOOT_ISRAM) && defined(CONFIG_ARCH_LOWVECTORS)
 
-  /* In this case, table must lie at the top 16Kb of ISRAM1 (or ISRAM0 if ISRAM1
-   * is not available in this architecture)
+  /* In this case, page table must lie at the top 16Kb of ISRAM1 (or ISRAM0
+   * if ISRAM1 is not available in this architecture)
    *
    * If CONFIG_PAGING is defined, then mmu.h assign the virtual address
    * of the page table.
@@ -620,7 +620,21 @@
 #      error CONFIG_BOOT_SDRAM_DATA not suupported in this configuration
 #    endif
 
-#  else /* CONFIG_BOOT_RUNFROMISRAM && CONFIG_ARCH_LOWVECTORS */
+#  elif defined(CONFIG_SAMA5_BOOT_SDRAM) && defined(CONFIG_ARCH_LOWVECTORS)
+
+  /* In this case, vectors must lie in ISRAM, followed by the page table,*/
+
+#    define PGTABLE_BASE_PADDR    (SAM_ISRAM0_PADDR + 0x00004000)
+#    ifndef CONFIG_PAGING
+#      define PGTABLE_BASE_VADDR  (SAM_ISRAM0_VADDR + 0x00004000)
+#    endif
+#    define PGTABLE_IN_LOWSRAM    1
+
+#    ifdef CONFIG_BOOT_SDRAM_DATA
+#      error CONFIG_BOOT_SDRAM_DATA not suupported in this configuration
+#    endif
+
+#  else /* CONFIG_SAMA5_BOOT_SDRAM && CONFIG_ARCH_LOWVECTORS */
 
   /* Otherwise, the vectors lie at another location (perhaps in NOR FLASH, perhaps
    * elsewhere in internal SRAM).  The page table will then be positioned at
@@ -638,7 +652,7 @@
 #      define IDLE_STACK_VBASE    (PGTABLE_BASE_VADDR + PGTABLE_SIZE)
 #    endif
 
-#  endif /* CONFIG_BOOT_RUNFROMISRAM && CONFIG_ARCH_LOWVECTORS */
+#  endif /* CONFIG_SAMA5_BOOT_ISRAM && CONFIG_ARCH_LOWVECTORS */
 
   /* In either case, the page table lies in ISRAM.  If ISRAM is not the
    * primary RAM region, then we will need to set-up a special mapping for
diff --git a/arch/arm/src/sama5/sam_boot.c b/arch/arm/src/sama5/sam_boot.c
index ff20fb0cd3..239f52725c 100644
--- a/arch/arm/src/sama5/sam_boot.c
+++ b/arch/arm/src/sama5/sam_boot.c
@@ -56,6 +56,7 @@
 #include "up_arch.h"
 
 #include "chip/sam_wdt.h"
+#include "chip/sam_aximx.h"
 #include "sam_clockconfig.h"
 #include "sam_lowputc.h"
 #include "sam_serial.h"
@@ -104,6 +105,19 @@
 #  define NEED_SDRAM_REMAPPING 1
 #endif
 
+/* We need to copy vectors under two conditions:
+ *
+ * 1. If vectors lie in high memory because CONFIG_ARCH_LOWVECTORS=n, or
+ * 2. If vectors lie in low memory and we are executing from SDRAM.
+ */
+
+#undef NEED_VECTOR_COPY
+#if !defined(CONFIG_ARCH_LOWVECTORS)
+#  define NEED_VECTOR_COPY 1
+#elif defined(CONFIG_SAMA5_BOOT_SDRAM)
+#  define NEED_VECTOR_COPY 1
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -130,37 +144,55 @@ static const struct section_mapping_s section_mapping[] =
 
   /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the
    * beginning of the .text region must appear at address zero.  There are
-   * two ways to accomplish this:
+   * three ways to accomplish this:
    *
    *   1. By explicitly mapping the beginning of .text region with a page
    *      table entry so that the virtual address zero maps to the beginning
    *      of the .text region.
+   *
    *   2. A second way is to map the use the AXI MATRIX remap register to
    *      map physical address zero to the beginning of the text region,
    *      either internal SRAM or EBI CS 0.  Then we can set an identity
    *      mapping to map the boot region at 0x0000:0000 to virtual address
    *      0x0000:00000
    *
-   * When executing from NOR FLASH, the first level bootloader is supposed
-   * to provide the AXI MATRIX mapping for us at boot time base on the state
-   * of the BMS pin.  However, I have found that in the test environments
-   * that I use, I cannot always be assured of that physical address mapping.
+   *      This method is used when booting from NORFLASH.  In that case,
+   *      vectors must lie at the beginning of NOFR FLASH.
+   *
+   *   3. Set the AXI MATRIX remap register so that SRAM appears at address
+   *      zero, mapping the boot region to address 0, then copying the
+   *      vectors to address zero.
    *
-   * So we do both here.  If we are executing from FLASH, then we provide
-   * the MMU to map the physical address of FLASH to address 0x0000:0000;
+   *      This is the method used when booting from either SDRAM or
+   *      SRAM.
    *
-   * If we are executing out of ISRAM, then the SAMA5 primary bootloader
-   * probably copied us into ISRAM.  If we are executing from external
-   * SDRAM, then a secondary bootloader must have loaded us into SDRAM. In
-   * either case we trust the bootloader to setup the AXI MATRIX mapping on
-   * our behalf.
+   * - When executing from NOR FLASH, the first level bootloader is supposed
+   *   to provide the AXI MATRIX mapping for us at boot time base on the state
+   *   of the BMS pin.  However, I have found that in the test environments
+   *   that I use, I cannot always be assured of that physical address mapping.
+   *
+   *   So we do both here.  If we are executing from NOR FLASH, then we provide
+   *   the MMU to map the physical address of FLASH to address 0x0000:0000;
+   *
+   * - If we are executing out of ISRAM, then the SAMA5 primary bootloader
+   *   probably copied us into ISRAM and set the AXI REMAP bit for us.
+   *
+   * - If we are executing from external SDRAM, then a secondary bootloader must
+   *   have loaded us into SDRAM.  In this case, we will may the BOOT memory,
+   *   set the AXI matrix to locate the ISRAM in boot memory, and copy the vector
+   *   table ISRAM.
    */
 
-#if defined(CONFIG_ARCH_LOWVECTORS) && !defined(CONFIG_SAMA5_BOOT_ISRAM) && \
-   !defined(CONFIG_SAMA5_BOOT_SDRAM)
-  { CONFIG_FLASH_VSTART,   0x00000000,
+#if defined(CONFIG_ARCH_LOWVECTORS) && !defined(CONFIG_SAMA5_BOOT_ISRAM)
+#  if defined(CONFIG_SAMA5_BOOT_SDRAM)
+  { SAM_ISRAM_PSECTION,    0x00000000,
     MMU_ROMFLAGS,          1
   },
+#  else
+  { CONFIG_FLASH_START,    0x00000000,
+    MMU_ROMFLAGS,          1
+  },
+#  endif
 #else
   { SAM_BOOTMEM_PSECTION,  SAM_BOOTMEM_VSECTION,
     SAM_BOOTMEM_MMUFLAGS,  SAM_BOOTMEM_NSECTIONS
@@ -453,11 +485,12 @@ static void sam_vectormapping(void)
  * Description:
  *   Copy the interrupt block to its final destination.  Vectors are already
  *   positioned at the beginning of the text region and only need to be
- *   copied in the case where we are using high vectors.
+ *   copied in the case where we are using high vectors or where the beginning
+ *   of the text region cannot be remapped to address zero.
  *
  ****************************************************************************/
 
-#ifndef CONFIG_ARCH_LOWVECTORS
+#ifdef NEED_VECTOR_COPY
 static void sam_copyvectorblock(void)
 {
   uint32_t *src;
@@ -465,7 +498,7 @@ static void sam_copyvectorblock(void)
   uint32_t *dest;
 
   /* If we are using re-mapped vectors in an area that has been marked
-   * read only, then temparily mark the mapping write-able (non-buffered).
+   * read only, then temporarily mark the mapping write-able (non-buffered).
    */
 
 #ifdef CONFIG_PAGING
@@ -496,6 +529,7 @@ static void sam_copyvectorblock(void)
   sam_vectorpermissions(MMU_L2_VECTORFLAGS);
 #endif
 }
+
 #else
 /* Don't copy the vectors */
 
@@ -542,7 +576,7 @@ static inline void sam_wdtdisable(void)
  *
  * Boot Sequence
  *
- *   This logic may be executing in ISRAM or in external mmemory: CS0, DDR,
+ *   This logic may be executing in ISRAM or in external memory: CS0, DDR,
  *   CS1, CS2, or CS3.  It may be executing in CS0 or ISRAM through the
  *   action of the SAMA5 "first level bootloader;"  it might be executing in
  *   CS1-3 through the action of some second level bootloader that provides
diff --git a/arch/arm/src/sama5/sam_irq.c b/arch/arm/src/sama5/sam_irq.c
index b92ee62619..afd25bc91b 100644
--- a/arch/arm/src/sama5/sam_irq.c
+++ b/arch/arm/src/sama5/sam_irq.c
@@ -280,16 +280,16 @@ void up_irqinitialize(void)
 
   putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
 
-#if defined(CONFIG_ARCH_LOWVECTORS) && defined(CONFIG_SAMA5_BOOT_ISRAM)
+#if defined(CONFIG_ARCH_LOWVECTORS)
   /* Disable MATRIX write protection */
 
 #if 0 /* Disabled on reset */
   putreg32(MATRIX_WPMR_WPKEY, SAM_MATRIX_WPMR);
 #endif
 
-  /* Set remap state 0 if we are running from internal SRAM.  If we booted
-   * into NOR FLASH, then the first level bootloader should have already
-   * provided this mapping for us.
+  /* Set remap state 0 if we are running from internal SRAM or from SDRAM.
+   * If we booted into NOR FLASH, then the first level bootloader should
+   * have already provided this mapping for us.
    *
    * This is done late in the boot sequence.  Any exceptions taken before
    * this point in time will be handled by the ROM code, not by the NuttX
@@ -306,8 +306,13 @@ void up_irqinitialize(void)
    * address 0x0000:0000 in that case anyway.
    */
 
-  putreg32(MATRIX_MRCR_RCB0, SAM_MATRIX_MRCR);   /* Enable remap */
+#if defined(CONFIG_SAMA5_BOOT_ISRAM) || defined(CONFIG_SAMA5_BOOT_SDRAM)
+  putreg32(MATRIX_MRCR_RCB0, SAM_MATRIX_MRCR);   /* Enable Cortex-A5 remap */
   putreg32(AXIMX_REMAP_REMAP0, SAM_AXIMX_REMAP); /* Remap SRAM */
+#elif defined(CONFIG_SAMA5_BOOT_CS0FLASH)
+  putreg32(MATRIX_MRCR_RCB0, SAM_MATRIX_MRCR);   /* Enable Cortex-A5 remap */
+  putreg32(AXIMX_REMAP_REMAP1, SAM_AXIMX_REMAP); /* Remap NOR FLASH */
+#endif
 
   /* Restore MATRIX write protection */
 
-- 
GitLab