Browse Source

Sort out mapping of virtual <-> flash addresses.

The irom0_flash.bin file gets written to offset 0x40000 in flash. Said file
has the following layout

  | irom0 | text | data | rodata | chksum |

...so the previous approach of having a _flash_used_end symbol at the end of
the irom0 section no longer gives us an accurate view of how much of the flash
is used.
Johny Mattsson 7 years ago
parent
commit
b3e8eddf14
4 changed files with 44 additions and 8 deletions
  1. 21 2
      app/platform/common.c
  2. 5 2
      app/platform/cpu_esp32.h
  3. 5 3
      app/platform/platform.c
  4. 13 1
      ld/nodemcu32.ld

+ 21 - 2
app/platform/common.c

@@ -13,15 +13,22 @@ void cmn_platform_init(void)
 // ****************************************************************************
 // Internal flash support functions
 
+#if defined(__ESP8266__)
 // This symbol must be exported by the linker command file and must reflect the
 // TOTAL size of flash used by the eLua image (not only the code and constants,
 // but also .data and whatever else ends up in the eLua image). FS will start
 // at the next usable (aligned to a flash sector boundary) address after
 // flash_used_size.
-
-// extern char flash_used_size[];
 extern char _flash_used_end[];
 
+#elif defined(__ESP32__)
+/* This symbol must be exported by the linker command file and contain the
+ * size of all the sections packed into the irom0_flash.bin file, in order
+ * for us to find the end of used flash.
+ */
+extern char _irom0_bin_min_sz[];
+#endif
+
 // Helper function: find the flash sector in which an address resides
 // Return the sector number, as well as the start and end address of the sector
 static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
@@ -69,6 +76,7 @@ uint32_t platform_flash_get_num_sectors(void)
 
 uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
 {
+#if defined(__ESP8266__)
   // Round the total used flash size to the closest flash block address
   uint32_t start, end, sect;
   NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
@@ -83,6 +91,17 @@ uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
       *psect = sect;
     return start;
   }
+#elif defined(__ESP32__)
+  uint32_t flash_offs = IROM0_START_FLASH_ADDR + (uint32_t)_irom0_bin_min_sz;
+  uint32_t sect =
+    (flash_offs + INTERNAL_FLASH_SECTOR_SIZE-1)/INTERNAL_FLASH_SECTOR_SIZE;
+  ++sect; /* compensate for various headers not counted in _irom0_bin_min_sz */
+
+  if (psect)
+    *psect = sect;
+
+  return sect * INTERNAL_FLASH_SECTOR_SIZE;
+#endif
 }
 
 uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )

+ 5 - 2
app/platform/cpu_esp32.h

@@ -55,8 +55,11 @@
 
 #define INTERNAL_FLASH_SIZE             ( (SYS_PARAM_SEC_START) * INTERNAL_FLASH_SECTOR_SIZE )
 
-// TODO: double-check flash mapped address
-#define INTERNAL_FLASH_MAPPED_ADDRESS    0x40084000
+/* Note: technically irom0 starts at +0x10, but that's not a page boundary! */
+#define IROM0_START_MAPPED_ADDR 0x40080000
+#define IROM0_START_FLASH_ADDR     0x40000
+// TODO: might need to revamp all this once cache windows fully understood
+#define INTERNAL_FLASH_MAPPED_ADDRESS   IROM0_START_MAPPED_ADDR
 
 #if defined(FLASH_SAFE_API)
 #define flash_write flash_safe_write

+ 5 - 3
app/platform/platform.c

@@ -853,7 +853,7 @@ int platform_flash_erase_sector( uint32_t sector_id )
 
 uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
 {
-#ifdef __ESP8266__
+#if defined(__ESP8266__)
   uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG);
   if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
     return -1;
@@ -861,8 +861,10 @@ uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
   bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0;
   uint32_t meg = (b1 << 1) | b0;
   return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000;
+#elif defined(__ESP32__)
+  // TODO: need to handle drom0 addresses too?
+  return mapped_addr - IROM0_START_MAPPED_ADDR + IROM0_START_FLASH_ADDR;
 #else
-  // FIXME
-  return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS;
+# error "unknown board"
 #endif
 }

+ 13 - 1
ld/nodemcu32.ld

@@ -278,7 +278,19 @@ SECTIONS
     LONG(0) LONG(0) /* Null-terminate the array */
 
     _irom0_text_end = ABSOLUTE(.);
-    _flash_used_end = ABSOLUTE(.);
+
+    /* Due to the way the gen_appbin.py script packs the bundle that goes into
+     * flash, we don't have a convenient _flash_used_end symbol on the ESP32.
+     * Instead we sum up the three sections we know goes into the
+     * irom0_flash.bin, so we can use that as a starting point to scan for
+     * the next free page. We could presumably be even more specific and
+     * account for the block headers and trailing checksum. Maybe later.
+     */
+    _irom0_bin_min_sz = ABSOLUTE(
+      _irom0_text_end - _irom0_text_start +
+      _text_end - _text_start +
+      _data_end - _data_start);
+
   } >irom0_0_seg :irom0_0_phdr
 
   .lit4 : ALIGN(4)