You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This implementation mirrors how the ESP-IDF implementation of this
feature (which is based on the `Cache_Flash_To_SPIRAM_Copy` rom
function) works except it differs in a few key ways:
The ESP-IDF seems to map `.text` and `.rodata` into the first and second
128 cache pages respectively (although looking at the linker scripts,
I'm not sure how, but a runtime check confirmed this seemed to be the
case). This is reflected in how the `Cache_Count_Flash_Pages`,
`Cache_Flash_To_SPIRAM_Copy` rom functions and the ESP-IDF code
executing them works. The count function can only be made to count flash
pages within the first 256 pages (of which there are 512 on the
ESP32-S3). Likewise, the copy function will only copy flash pages which
are mapped within the first 256 entries (across two calls). As the
esp-hal handles mapping `.text` and `.rodata` differently, these ROM
functions are technically not appropriate if more than 256 pages of
flash (`.text` and `.rodata` combined) are in use by the application.
Additionally, the functions both contain bugs, one of which the IDF
attempts to work around incorrectly, and the other which the IDF does
not appear to be aware of. Details of these bugs can be found on the IDF
issue/PR tracker[0][1].
As a result, this commit contains a heavily modified/adjusted rust
re-write of the reverse engineered ROM code combined with a vague port
of the ESP-IDF code.
There are three additional noteworthy differences from the ESP-IDF version
of the code:
1. The ESP-IDF allows the `.text` and `.rodata` segments to be mapped
independently and separately allowing only one to be mapped. But the
current version of the code does not allow this flexibility. This can
be implemented by checking the address of each page entry against the
segment locations to determine which segment each address belongs to.
2. The ESP-IDF calls
`cache_ll_l1_enable_bus(..., cache_ll_l1_get_bus(..., SOC_EXTRAM_DATA_HIGH, 0));`
(functions from the ESP-IDF) in order to "Enable the most high bus,
which is used for copying FLASH `.text` to PSRAM" but on the ESP32-S3
after careful inspection these calls result in a no-op as the address
passed to cache_ll_l1_get_bus will result in an empty cache bus mask.
It's currently unclear to me if this is a bug in the ESP-IDF code, or
if this code (which from cursory investigation is probably not a
no-op on the -S2) is solely targetting the ESP32-S3.
3. The ESP-IDF calls `Cache_Flash_To_SPIRAM_Copy` with an icache address
when copying `.text` and a dcache address when copying `.rodata`.
This affects which cache the reads will occur through. But the writes
always go through a "spare page" (name I came up with during reverse
engineering) via the dcache. This code performs all reads through the
dcache. I don't know if there's a proper reason to read through the
correct cache when doing the copy and this doesn't appear to have any
negative impact.
[0]: espressif/esp-idf#15262
[1]: espressif/esp-idf#15263
0 commit comments