Sfoglia il codice sorgente

add api get valid mmu table pages number

Tian Zhong Xing 7 anni fa
parent
commit
7555031553

+ 3 - 2
components/bootloader_support/src/bootloader_flash.c

@@ -23,7 +23,7 @@
  */
 static const char *TAG = "bootloader_mmap";
 
-static spi_flash_mmap_memory_t map;
+static spi_flash_mmap_handle_t map;
 
 const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
 {
@@ -36,7 +36,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     size += (src_addr - src_page);
     esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
     if (err != ESP_OK) {
-        result = NULL;
+        ESP_LOGE(TAG, "spi_flash_mmap failed: 0x%x", err);
+        return NULL;
     }
     return (void *)((intptr_t)result + (src_addr - src_page));
 }

+ 31 - 6
components/bootloader_support/src/esp_image_format.c

@@ -19,6 +19,7 @@
 #include <esp_image_format.h>
 #include <esp_secure_boot.h>
 #include <esp_log.h>
+#include <esp_spi_flash.h>
 #include <bootloader_flash.h>
 #include <bootloader_random.h>
 #include <bootloader_sha.h>
@@ -48,6 +49,9 @@ static bool should_map(uint32_t load_addr);
 /* Load or verify a segment */
 static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum);
 
+/* split segment and verify if data_len is too long */
+static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum);
+
 /* Verify the main image header */
 static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent);
 
@@ -291,7 +295,34 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
             }
         }
     }
+#ifndef BOOTLOADER_BUILD
+    uint32_t page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
+    ESP_LOGI(TAG, "free data page_count 0x%08x",page_count);
+    while (data_len >= page_count * SPI_FLASH_MMU_PAGE_SIZE) {
+        err = process_segment_data(load_addr, data_addr, page_count * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum);
+        if (err != ESP_OK) {
+            return err;
+        }
+        data_addr += page_count * SPI_FLASH_MMU_PAGE_SIZE;
+        data_len -= page_count * SPI_FLASH_MMU_PAGE_SIZE;
+    }
+#endif
+    err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
+    if (err != ESP_OK) {
+        return err;
+    }
+    return ESP_OK;
 
+err:
+    if (err == ESP_OK) {
+        err = ESP_ERR_IMAGE_INVALID;
+    }
+
+    return err;
+}
+
+static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
+{
     const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len);
     if(!data) {
         ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed",
@@ -332,12 +363,6 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
     bootloader_munmap(data);
 
     return ESP_OK;
-
- err:
-    if (err == ESP_OK) {
-        err = ESP_ERR_IMAGE_INVALID;
-    }
-    return err;
 }
 
 static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent)

+ 40 - 13
components/spi_flash/flash_mmap.c

@@ -100,6 +100,21 @@ static void IRAM_ATTR spi_flash_mmap_init()
     DPORT_STALL_OTHER_CPU_END();
 }
 
+static void IRAM_ATTR get_mmu_region(spi_flash_mmap_memory_t memory, int* out_begin, int* out_size,uint32_t* region_addr)
+{
+    if (memory == SPI_FLASH_MMAP_DATA) {
+        // Vaddr0
+        *out_begin = 0;
+        *out_size = 64;
+        *region_addr = VADDR0_START_ADDR;
+    } else {
+        // only part of VAddr1 is usable, so adjust for that
+        *out_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
+        *out_size = 3 * 64 - *out_begin;
+        *region_addr = VADDR1_FIRST_USABLE_ADDR;
+    }
+}
+
 esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
                          const void** out_ptr, spi_flash_mmap_handle_t* out_handle)
 {
@@ -157,17 +172,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
     int region_begin;   // first page to check
     int region_size;    // number of pages to check
     uint32_t region_addr;  // base address of memory region
-    if (memory == SPI_FLASH_MMAP_DATA) {
-        // Vaddr0
-        region_begin = 0;
-        region_size = 64;
-        region_addr = VADDR0_START_ADDR;
-    } else {
-        // only part of VAddr1 is usable, so adjust for that
-        region_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
-        region_size = 3 * 64 - region_begin;
-        region_addr = VADDR1_FIRST_USABLE_ADDR;
-    }
+    get_mmu_region(memory,&region_begin,&region_size,&region_addr);
     if (region_size < page_count) {
         return ESP_ERR_NO_MEM;
     }
@@ -176,7 +181,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
     // entries are treated as wildcards.
     int start;
     int end = region_begin + region_size - page_count;
-    for (start = region_begin; start < end; ++start) {
+    for (start = region_begin; start <= end; ++start) {
         int pageno = 0;
         int pos;
         DPORT_STALL_OTHER_CPU_START();
@@ -194,7 +199,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
         }
     }
     // checked all the region(s) and haven't found anything?
-    if (start == end) {
+    if (start > end) {
         *out_handle = 0;
         *out_ptr = NULL;
         ret = ESP_ERR_NO_MEM;
@@ -292,6 +297,28 @@ void spi_flash_mmap_dump()
     }
 }
 
+uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
+{
+    spi_flash_mmap_init();
+    int count = 0;
+    int region_begin;   // first page to check
+    int region_size;    // number of pages to check
+    uint32_t region_addr;  // base address of memory region
+    get_mmu_region(memory,&region_begin,&region_size,&region_addr);
+    DPORT_STALL_OTHER_CPU_START();
+    for (int i = region_begin; i < region_begin + region_size; ++i) {
+        if (s_mmap_page_refcnt[i] == 0 && DPORT_PRO_FLASH_MMU_TABLE[i] == INVALID_ENTRY_VAL) {
+            count++;
+        }
+    }
+    DPORT_STALL_OTHER_CPU_END();
+    if(count >= 1) {
+        return count - 1; //don't sure mmap src_addr,if src_addr not align 64K bytes,max need one more pages
+    } else {
+        return 0;
+    }
+}
+
 /* 256-bit (up to 16MB of 64KB pages) bitset of all flash pages
    that have been written to since last cache flush.
 

+ 15 - 0
components/spi_flash/include/esp_spi_flash.h

@@ -236,6 +236,21 @@ void spi_flash_munmap(spi_flash_mmap_handle_t handle);
  */
 void spi_flash_mmap_dump();
 
+/**
+ * @brief get free pages number which can be mmap
+ *
+ * @note This function will return free page number of the mmu table which can mmap,
+ * when you want to call spi_flash_mmap to mmap an ranger of flash data to Dcache or Icache
+ * memmory region, maybe the size of  MMU table will exceed,so if you are not sure the
+ * size need mmap is ok, can call the interface and watch how many MMU table page can be
+ * mmaped.
+ *
+ * @param memory  memmory type of MMU table free page
+ *
+ * @return  number of free pages which can be mmaped
+ */
+uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
+
 
 #define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */