I'm looking into how to dynamically load a binary into an already running ESP32 environment. One thought I had was to compile my binary so that it "thinks" its run-time address is 0x4800 0000. I would then place this binary within flash (perhaps in a partition). I would then use memory mapping to map the instruction data on flash into the ESP32 address space starting at 0x4800 0000.
I then started studying spi_flash_mmap which I felt was heading in the right direction. However, as I read this API, I get the feeling that I can't declare where in the address space of the ESP32 the mapping should target. It seems that I am returned a pointer to where the ESP32 has decided to map my flash data to ... I am not seeing an option to declare where in the address space I want the flash data to be mapped.
Am I wrong in either (or both) of my thinking on using mmap or in my thinking of the end goal of mapping executable code into address space?
[Answered]: flash memory mapping to specific address space
[Answered]: flash memory mapping to specific address space
Last edited by kolban on Mon Feb 26, 2018 3:51 am, edited 1 time in total.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: flash memory mapping to specific address space
Hi Neil,
Neil & I discussed this elsewhere, but I'll summarise the answers here:
- Yes, you can use the MMU to map flash into the instruction address space.
- No, spi_flash_mmap() doesn't let you choose the destination address in memory. It's designed for creating dynamic mappings.
- To reliably reserve a region of the address space for mapping, I recommend modifying the IDF linker script (components/esp32/ld/esp32.ld) to take your desired range of address space out of consideration for the app. Possibly also modify the spi_flash_mmap routine, so it doesn't support dynamically mapping into the full range of available MMU slots. Then write your own mapping routines, very similar to the ones used by the IDF bootloader (esp_image_load() routine, etc.)
Angus
Neil & I discussed this elsewhere, but I'll summarise the answers here:
- Yes, you can use the MMU to map flash into the instruction address space.
- No, spi_flash_mmap() doesn't let you choose the destination address in memory. It's designed for creating dynamic mappings.
- To reliably reserve a region of the address space for mapping, I recommend modifying the IDF linker script (components/esp32/ld/esp32.ld) to take your desired range of address space out of consideration for the app. Possibly also modify the spi_flash_mmap routine, so it doesn't support dynamically mapping into the full range of available MMU slots. Then write your own mapping routines, very similar to the ones used by the IDF bootloader (esp_image_load() routine, etc.)
Angus
Re: [Answered]: flash memory mapping to specific address space
Hey guys - I'd like to revisit this topic, as I too am struggling to understand the docs, as I attempt to access the external flash for storing persistent application data.
The technical reference manual indicates that the 4MB external flash is mapped to starting address 0x3F40_0000. (I assume the underbar is for readability, and is ignored.) At first, I added an entry into my partitions table file like this:
I got an error at build time saying:
I don't see anything there that is using the space below 0x5000. So, do I correctly infer that:
1. the MMU takes whatever offset I give it and adds it to the starting address of 0x3f400000 (in the case of external flash)
2. the first 0x5000 bytes of external flash are reserved
3. the ONLY things currently occupying external flash are the three entries mentioned above(nvs, ota and phy)
Thanks...
The technical reference manual indicates that the 4MB external flash is mapped to starting address 0x3F40_0000. (I assume the underbar is for readability, and is ignored.) At first, I added an entry into my partitions table file like this:
Code: Select all
appdata,data,nvs,0x3f400000,64K
So, I'm guessing the offset is meant to be from the base address 0x3f400000. I then tried an offset of 0, and got this:E (49) flash_parts: partition 6 invalid - offset 0x3f400000 size 0x10000 exceeds flash chip size 0x400000
The other data entries in my file are:Partition offset 0x0 is below 0x5000
Code: Select all
nvs,data,nvs,0x9000,16K,
otadata,data,ota,0xd000,8K,
phy_init,data,phy,0xf000,4K,
1. the MMU takes whatever offset I give it and adds it to the starting address of 0x3f400000 (in the case of external flash)
2. the first 0x5000 bytes of external flash are reserved
3. the ONLY things currently occupying external flash are the three entries mentioned above(nvs, ota and phy)
Thanks...
Re: [Answered]: flash memory mapping to specific address space
Think of 4 megabytes of flash as having a range of 0 to 0x3F FFFF.
This means setting byte 0 is the 1st byte of flash and setting byte 0x3F FFFF is the last byte of flash.
Thus to write into a byte of flash, it is always indexed as an offset starting from 0 from the beginning of flash.
At runtime, the flash memory is "mapped" into the address space of the ESP32 ... for example the first byte of flash (0) appears at address 0x3F40 0000 in the ESP32 address space. At this point the lightbulb is likely going on that there are two address spaces ... offsets into flash and address space in the ESP32 memory address space.
When you configure partition tables, you are defining the offset into flash ... which has nothing to do (during partition table configuration) of where the flash appears in address space.
Further ... you should never have to know where the flash is mapped in address space ... see the APIs called esp_partition_read and esp_partition_write. These should allow you to read and write the partition without hard-coding addresses. Should you need explicit direct addressing to a partition's storage, this is where esp_partition_mmap() would come into play.
This means setting byte 0 is the 1st byte of flash and setting byte 0x3F FFFF is the last byte of flash.
Thus to write into a byte of flash, it is always indexed as an offset starting from 0 from the beginning of flash.
At runtime, the flash memory is "mapped" into the address space of the ESP32 ... for example the first byte of flash (0) appears at address 0x3F40 0000 in the ESP32 address space. At this point the lightbulb is likely going on that there are two address spaces ... offsets into flash and address space in the ESP32 memory address space.
When you configure partition tables, you are defining the offset into flash ... which has nothing to do (during partition table configuration) of where the flash appears in address space.
Further ... you should never have to know where the flash is mapped in address space ... see the APIs called esp_partition_read and esp_partition_write. These should allow you to read and write the partition without hard-coding addresses. Should you need explicit direct addressing to a partition's storage, this is where esp_partition_mmap() would come into play.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: [Answered]: flash memory mapping to specific address space
Thanks, Neil - that helps. I tried playing with the esp_partition_mmap() routine yesterday, but couldn't get it working. Finally I realized that I didn't need it.
So, is there something pre-mapped within the first 0x5000 bytes of the external flash, and is that why I got the error I did when I attempted to put a partition there?
So, is there something pre-mapped within the first 0x5000 bytes of the external flash, and is that why I got the error I did when I attempted to put a partition there?
Re: [Answered]: flash memory mapping to specific address space
When we look at Espressif's map of the partition table we see that the first three entries are pretty much constants:
We also see that app partitions have to be 64K aligned and are recommended to start at 0x10000.
From the above, we can see that we had better be hands-of 0x9000 - 0xffff and that 0x10000 and above are ours to play with. However, none of this says anything about what (if anything) might be south of 0x9000. We do have some clues however ... we find that the partition table itself is fixed in flash at 0x8000. I also believe that the bootloader is fixed at 0x1000. Because of this, I'm going to stick my neck out and say anything south of 0x10000 is hands-off from an application perspective.
See also:
http://esp-idf.readthedocs.io/en/latest ... ables.html
Code: Select all
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
From the above, we can see that we had better be hands-of 0x9000 - 0xffff and that 0x10000 and above are ours to play with. However, none of this says anything about what (if anything) might be south of 0x9000. We do have some clues however ... we find that the partition table itself is fixed in flash at 0x8000. I also believe that the bootloader is fixed at 0x1000. Because of this, I'm going to stick my neck out and say anything south of 0x10000 is hands-off from an application perspective.
See also:
http://esp-idf.readthedocs.io/en/latest ... ables.html
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Who is online
Users browsing this forum: calico, pineapple678 and 130 guests