]> granicus.if.org Git - esp-idf/commitdiff
bootloader: account for load address when mapping cache pages
authorIvan Grokhotkov <ivan@espressif.com>
Mon, 3 Sep 2018 10:15:20 +0000 (18:15 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 23 Jan 2019 09:02:02 +0000 (17:02 +0800)
Bootloader used to calculate the number of cache pages assuming that
load address was aligned, while in reality load address for DROM and
IROM was offset by 0x20 bytes from the start of 64kB page. This
caused the bootloader to map one less page if the size of the image
was 0x4..0x1c less than a multiple of 64kB.

Reported in https://esp32.com/viewtopic.php?f=13&t=6952.

components/bootloader_support/include_bootloader/bootloader_flash.h
components/bootloader_support/src/bootloader_flash.c
components/bootloader_support/src/bootloader_utility.c

index 85a4827819076cf3d3d016fc458ee3aed50bed63..ce867d7573b60314d04a3c8a9c2466b2749d4e3c 100644 (file)
@@ -111,4 +111,21 @@ esp_err_t bootloader_flash_erase_sector(size_t sector);
  */
 esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size);
 
+/* Cache MMU block size */
+#define MMU_BLOCK_SIZE    0x00010000
+
+/* Cache MMU address mask (MMU tables ignore bits which are zero) */
+#define MMU_FLASH_MASK    (~(MMU_BLOCK_SIZE - 1))
+
+/**
+ * @brief Calculate the number of cache pages to map
+ * @param size  size of data to map
+ * @param vaddr  virtual address where data will be mapped
+ * @return number of cache MMU pages required to do the mapping
+ */
+static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vaddr)
+{
+    return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE;
+}
+
 #endif
index 735c21327047b8464f2db16a04aaf7bbca6e5276..dbdf84ee2bab999198826cefe013de4577c6f42b 100644 (file)
@@ -91,8 +91,6 @@ static const char *TAG = "bootloader_flash";
 */
 #define MMU_BLOCK0_VADDR  0x3f400000
 #define MMU_BLOCK50_VADDR 0x3f720000
-#define MMU_FLASH_MASK    0xffff0000
-#define MMU_BLOCK_SIZE    0x00010000
 
 static bool mapped;
 
@@ -112,10 +110,11 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     }
 
     uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
-    uint32_t count = (size + (src_addr - src_addr_aligned) + 0xffff) / MMU_BLOCK_SIZE;
+    uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
     Cache_Read_Disable(0);
     Cache_Flush(0);
-    ESP_LOGD(TAG, "mmu set paddr=%08x count=%d", src_addr_aligned, count );
+    ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
+            src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
     int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
     if (e != 0) {
         ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
index c0dbf04afc89556968adffb9023721a090e925ae..80550b11c551ee58e4f79bac3643295269e9d9fa 100644 (file)
@@ -430,6 +430,7 @@ static void set_cache_and_start_app(
     uint32_t irom_size,
     uint32_t entry_addr)
 {
+    int rc;
     ESP_LOGD(TAG, "configure drom and irom and start");
     Cache_Read_Disable( 0 );
     Cache_Flush( 0 );
@@ -441,20 +442,34 @@ static void set_cache_and_start_app(
         DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
     }
 
-    uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k
-    ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count );
-    int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
-    ESP_LOGV(TAG, "rc=%d", rc );
-    rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
-    ESP_LOGV(TAG, "rc=%d", rc );
-    uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k
-    ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count );
-    rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
-    ESP_LOGV(TAG, "rc=%d", rc );
-    rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
-    ESP_LOGV(TAG, "rc=%d", rc );
-    DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 );
-    DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 );
+    uint32_t drom_load_addr_aligned = drom_load_addr & MMU_FLASH_MASK;
+    uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr);
+    ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d",
+            drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
+    rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
+    ESP_LOGV(TAG, "rc=%d", rc);
+    rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
+    ESP_LOGV(TAG, "rc=%d", rc);
+
+    uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK;
+    uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr);
+    ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d",
+            irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
+    rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
+    ESP_LOGV(TAG, "rc=%d", rc);
+    rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
+    ESP_LOGV(TAG, "rc=%d", rc);
+
+    DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
+            (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
+            (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
+            DPORT_PRO_CACHE_MASK_DRAM1 );
+
+    DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
+            (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
+            (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
+            DPORT_APP_CACHE_MASK_DRAM1 );
+
     Cache_Read_Enable( 0 );
 
     // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)