ESP32-C3 memory model #57981
Replies: 5 comments 2 replies
-
As I understand it, the ESP32 2nd stage bootloader (e.g. mcuboot or esp-idf bootloader) does not consume any I/DRAM once the application starts. I don't have an ESP32-C3 yet but it seems very similar.
|
Beta Was this translation helpful? Give feedback.
-
Hi @marinjurjevic,
|
Beta Was this translation helpful? Give feedback.
-
From what I can see, the address in the dtsi file is not used anywhere. So the answer is, the dtsi is just wrong but is not used so it doesn't matter. On other platforms, the dts specified address is used as a macro in the linker script. But the esp32c3 linker script hard codes the value.
Yes, I think that's it too. They could use the correct address and adjust some other macros to take that into account. Like this: #define SRAM_IRAM_START 0x4037C000
#define SRAM_DRAM_START 0x3FC80000 /* same address as datasheet now */
#define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */
#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE)
#define SRAM_DRAM_ORG (SRAM_DRAM_START)
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
#define I_D_SRAM_OFFSET (SRAM_IRAM_ORG - SRAM_DRAM_ORG)
#define SRAM_DRAM_END (0x403D0000 - I_D_SRAM_OFFSET) /* 2nd stage bootloader iram_loader_seg start address */ Having done that, the resulting linker script produces the same result as before when it had the incorrect dram start address. Something interesting to me about the dram segment, is that contains in order the sections I see that the division between IRAM and DRAM is aligned to 16 bytes, i.e. in the example it is 0x1_4EC0. But from the ESP32-C3 TRM §14.4.2.2, "Note that the split address must be aligned to 512 bytes, meaning you can only write the integral multiples of 0x200 to the SPLITADDR field." So how does it work when IRAM and DRAM are not being split at a 512 byte aligned boundary? |
Beta Was this translation helpful? Give feedback.
-
From what I can see, Zephyr not aligning the IRAM/DRAM split to 512 bytes is a bug. The esp-idf does align to 512 on the ESP32-C3:
The reason Zephyr runs instead crashing on a invalid I/DBUS access, is that the PMS is never programmed for any of the IRAM or DRAM permissions! Effectively, all of SRAM is accessible from the IRAM region and the DRAM region at the same time. Not just mapped into the virtual address space, which is always how the the ESP32-C3 works, bus accessible and usable as both code and data. There's no protection. It's possible to write data into IRAM with a buffer overflow or to execute code on the stack with return address corruption. The esp-idf has a similar issue to @marinjurjevic 's points 2-4, about the missing 64kB. In esp-idf, there is even a bit more missing SRAM, This is because the ESP-IDF also puts the sections into DRAM in a different order than Zephyr. It uses the order .data, .noinit, .bss, heap. It requires the first three to fit in into On Zephyr, unless I have missed something, the heap is allocated out of space reserved in the noinit section. I tried re-ordering the Zephyr sections and it seems to work fine. So perhaps this is a bug in the Zephyr linker setup for ESP32-C3 and the bss, noinit, and heap could use the bootloader's SRAM. |
Beta Was this translation helpful? Give feedback.
-
@marinjurjevic, @ankayca, can you please rebase your work to use the latest changes? The PR with heap optimization was merged recently and it allows more statical allocation for the user code. |
Beta Was this translation helpful? Give feedback.
-
Hi,
I am evaluating ESP32-C3 for a project which will use WiFi, TLS and MQTT. Since these components tend to use a lot of resources, my first step is understanding ESP32-C3 memory model and try to get a rough estimation of RAM usage.
I have tried getting help on Discord, but the conversation there is moving really fast and the thread got left behind, so I'll try get more coverage here on GH.
As a starting point, I'm using a sample mentioned in one of the previous issues (link).
Environment
Board:
esp32c3_devkitm
Toolchain:
zephyr-sdk-0.16.0 (riscv64-zephyr-elf-gcc)
Zephyr version:
zephyr-v3.3.0-1372-g4939463dc2
Build Report
After building the sample, here's the report I get. One of the first things that confused me is RAM size. Per datasheet, 384KB is available on C3, but here it's reported 320KB - that's a significant difference of 64KB missing.
RAM report
I attached the complete report.
RAM report shows 450728B as 100% which makes no sense since I would expect 320KB (or 384KB). Maybe it's due to IRAM/DRAM overlaps so something gets added twice.
Also, I don't know what
(hidden)
stands for?RAM report
DTS
I then started digging into DTS and found
esp32c3.dtsi
.zephyr/dts/riscv/espressif/esp32c3.dtsi
Lines 55 to 58 in 42d9cf1
Why does DTS state starting address
0x3fc7c000
and size0x50000
(320KB)?Datasheet shows DRAM is mapped from
0x3fc8000
and addresses before are reserved.Only IRAM is mapped to first
0x4000
(16KB) and that's used as cache for external memory.Subtracting these 16KB from 400KB yields 384KB available RAM:
0x3fc80000
-0x3fcdffff
are DRAM addresses0x40380000
-0x403Dffff
are IRAM adressesLinker
Linker script for
esp32c3
is a bit confusing.Just like in dts above, address
0x3FC7C000
is defined as SRAM_DRAM_START. I'm assuming this is to make calculations consistent with two different address spaces regarding offsets (I_D_SRAM_OFFSET
variable is defined as difference of two).Actual addresses used for memory are
SRAM_IRAM_ORG
andSRAM_DRAM_ORG
which are correct.One more important note is the comment on
SRAM_DRAM_END
where it's mentioned that bootloader starts at0x403D0000
, so this could explain 64KB vanishing.zephyr/soc/riscv/esp32c3/linker.ld
Lines 18 to 32 in 42d9cf1
Bootloader
The last thing I checked is bootloader linker script. The
iram_loader_seg
is consistent with application linker script comment and it has size0x6000
(24K), followed bydram_seg
of size0x4000
(16K). This adds up to0xa000
(40K) which leaves 24K unspecified.At last, there is
iram_seg
defined at0x403CE000
. This is0x2000
(8KB) before end of application SRAM_DRAM_END.https://github.com/zephyrproject-rtos/hal_espressif/blob/f18f680fa010cef4a50072a11d418296f467594a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld#L7-L12
At the end of the linker script ROM bootloader memory usage is mentioned. I'm not sure how to interpret this since part of address space is before
0x403D0000
and part is after.https://github.com/zephyrproject-rtos/hal_espressif/blob/f18f680fa010cef4a50072a11d418296f467594a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld#L177-L193
Summary
So that's what I collected for up to this point. I understand ESP32C3 has specific memory model with two different address spaces addressing the same physical memory.
I created a diagram to visualize how are all these things connected and I'd like to make sense of it.
Questions
I have a lot of questions. I'll list most important and number them for easier referencing in discussion.
(hidden)
segment in RAM report and why does ram_report give wrong numbers?esp32c3.dtsi
defined as0x3fc7c000
and its size0x50000
(320KB)?0x3fcd000
-> 64KB before actual end? Is this for bootloader IRAM?iram_seg
located before application RAM end address (SRAM_DRAM_END) ?Beta Was this translation helpful? Give feedback.
All reactions