mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
cbb84e8f5e
1. Clarify THREADPTR calculation in FreeRTOS code, explaining where the constant 0x10 offset comes from. 2. On the ESP32-S2, .flash.rodata section had different default alignment (8 bytes instead of 16), which resulted in different offset of the TLS sections. Unfortunately I haven’t found a way to query section alignment from C code, or to use a constant value to define section alignment in the linker script. The linker scripts are modified to force a fixed 16 byte alignment for .flash.rodata on the ESP32 and ESP32-S2beta. Note that the base address of .flash.rodata was already 16 byte aligned, so this has not changed the actual memory layout of the application. Full explanation of the calculation below. Assume we have the TLS template section base address (tls_section_vma), the address of a TLS variable in the template (address), and the final relocation value (offset). The linker calculates: offset = address - tls_section_vma + align_up(TCB_SIZE, alignment). At run time, the TLS section gets copied from _thread_local_start (in .rodata) to task_thread_local_start. Let’s assume that an address of a variable in the runtime TLS section is runtime_address. Access to this address will happen by calculating THREADPTR + offset. So, by a series of substitutions: THREADPTR + offset = runtime_address THREADPTR = runtime_address - offset THREADPTR = runtime_address - (address - tls_section_vma + align_up(TCB_SIZE, alignment)) THREADPTR = (runtime_address - address) + tls_section_vma - align_up(TCB_SIZE, alignment) The difference between runtime_address and address is same as the difference between task_thread_local_start and _thread_local_start. And tls_section_vma is the address of .rodata section, i.e. _rodata_start. So we arrive to THREADPTR = task_thread_local_start - _thread_local_start + _rodata_start - align_up(TCB_SIZE, alignment). The idea with TCB_SIZE being added to the THREADPTR when computing the relocation was to let the OS save TCB pointer in the TREADPTR register. The location of the run-time TLS section was assumed to be immediately after the TCB, aligned to whatever the section alignment was. However in our case the problem is that the run-time TLS section is stored not next to the TCB, but at the top of the stack. Plus, even if it was stored next to the TCB, the size of a FreeRTOS TCB is not equal to 8 bytes (TCB_SIZE hardcoded in the linker). So we have to calculate THREADPTR in a slightly obscure way, to compensate for these differences. Closes IDF-1239 |
||
---|---|---|
.. | ||
include | ||
ld | ||
test | ||
brownout.c | ||
cache_err_int.c | ||
cache_sram_mmu.c | ||
clk.c | ||
CMakeLists.txt | ||
component.mk | ||
cpu_start.c | ||
crosscore_int.c | ||
dport_access.c | ||
dport_panic_highint_hdl.S | ||
esp_clk_internal.h | ||
esp_himem.c | ||
esp_timer_esp32.c | ||
hw_random.c | ||
int_wdt.c | ||
intr_alloc.c | ||
Kconfig | ||
linker.lf | ||
Makefile.projbuild | ||
panic.c | ||
pm_esp32.c | ||
pm_trace.c | ||
project_include.cmake | ||
reset_reason.c | ||
sdkconfig.rename | ||
sleep_modes.c | ||
spiram_psram.c | ||
spiram_psram.h | ||
spiram.c | ||
system_api_esp32.c | ||
task_wdt.c |