diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 51ef321ac6..c65020595b 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -34,6 +34,9 @@ static const char *TAG = "esp_image"; /* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */ #define STACK_LOAD_HEADROOM 32768 +/* Mmap source address mask */ +#define MMAP_ALIGNED_MASK 0x0000FFFF + #ifdef BOOTLOADER_BUILD /* 64 bits of random data to obfuscate loaded RAM with, until verification is complete (Means loaded code isn't executable until after the secure boot check.) @@ -296,15 +299,17 @@ 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); + uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count); + uint32_t offset_page = 0; + while (data_len >= free_page_count * SPI_FLASH_MMU_PAGE_SIZE) { + offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0)?1:0; + err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * 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; + data_addr += (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE; + data_len -= (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE; } #endif err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum); diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index de0a41f110..91e213d4d8 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -180,8 +180,10 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas // Algorithm is essentially naïve strstr algorithm, except that unused MMU // entries are treated as wildcards. int start; - int end = region_begin + region_size - page_count; - for (start = region_begin; start <= end; ++start) { + // the " + 1" is a fix when loop the MMU table pages, because the last MMU page + // is valid as well if it have not been used + int end = region_begin + region_size - page_count + 1; + for (start = region_begin; start < end; ++start) { int pageno = 0; int pos; DPORT_STALL_OTHER_CPU_START(); @@ -199,7 +201,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; @@ -312,11 +314,7 @@ uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory) } } 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; - } + return count; } /* 256-bit (up to 16MB of 64KB pages) bitset of all flash pages diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index b8c5fdc132..9caa47e408 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -239,7 +239,7 @@ 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, + * 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 diff --git a/components/spi_flash/test/test_mmap.c b/components/spi_flash/test/test_mmap.c index 30e1ddfc8a..8d1b689046 100644 --- a/components/spi_flash/test/test_mmap.c +++ b/components/spi_flash/test/test_mmap.c @@ -276,6 +276,51 @@ TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash]") handle1 = 0; } +TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash]") +{ + //this test case should make flash size >= 4MB, because max size of Dcache can mapped is 4MB + setup_mmap_tests(); + + printf("Mapping %x (+%x)\n", start, end - start); + const void *ptr1; + ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) ); + printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1); + + spi_flash_mmap_dump(); + + srand(0); + const uint32_t *data = (const uint32_t *) ptr1; + for (int block = 0; block < (end - start) / 0x10000; ++block) { + printf("block %d\n", block); + for (int sector = 0; sector < 16; ++sector) { + printf("sector %d\n", sector); + for (uint32_t word = 0; word < 1024; ++word) { + TEST_ASSERT_EQUAL_HEX32(rand(), data[(block * 16 + sector) * 1024 + word]); + } + } + } + uint32_t free_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + printf("Mapping %x (+%x)\n", 0, free_pages * SPI_FLASH_MMU_PAGE_SIZE); + const void *ptr2; + ESP_ERROR_CHECK( spi_flash_mmap(0, free_pages * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) ); + printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2); + + spi_flash_mmap_dump(); + + + printf("Unmapping handle1\n"); + spi_flash_munmap(handle1); + handle1 = 0; + spi_flash_mmap_dump(); + + printf("Unmapping handle2\n"); + spi_flash_munmap(handle2); + handle2 = 0; + spi_flash_mmap_dump(); + + TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(start, SPI_FLASH_MMAP_DATA)); +} + TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash]") { uint8_t buf[64];