|
|
@@ -164,7 +164,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
|
|
#endif
|
|
|
uint32_t *threadptr;
|
|
|
void *task_thread_local_start;
|
|
|
- extern int _thread_local_start, _thread_local_end, _rodata_start;
|
|
|
+ extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align;
|
|
|
// TODO: check that TLS area fits the stack
|
|
|
uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start;
|
|
|
|
|
|
@@ -223,24 +223,62 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
|
|
frame->vpri = 0xFFFFFFFF;
|
|
|
#endif
|
|
|
|
|
|
- /* Init threadptr reg and TLS vars */
|
|
|
+ /* Init threadptr register and set up TLS run-time area.
|
|
|
+ * The following diagram illustrates the layout of link-time and run-time
|
|
|
+ * TLS sections.
|
|
|
+ *
|
|
|
+ * +-------------+
|
|
|
+ * |Section: | Linker symbols:
|
|
|
+ * |.flash.rodata| ---------------
|
|
|
+ * 0x0+-------------+ <-- _flash_rodata_start
|
|
|
+ * ^ | |
|
|
|
+ * | | Other data |
|
|
|
+ * | | ... |
|
|
|
+ * | +-------------+ <-- _thread_local_start
|
|
|
+ * | |.tbss | ^
|
|
|
+ * v | | |
|
|
|
+ * 0xNNNN|int example; | | (thread_local_size)
|
|
|
+ * |.tdata | v
|
|
|
+ * +-------------+ <-- _thread_local_end
|
|
|
+ * | Other data |
|
|
|
+ * | ... |
|
|
|
+ * | |
|
|
|
+ * +-------------+
|
|
|
+ *
|
|
|
+ * Local variables of
|
|
|
+ * pxPortInitialiseStack
|
|
|
+ * -----------------------
|
|
|
+ * +-------------+ <-- pxTopOfStack
|
|
|
+ * |.tdata (*) | ^
|
|
|
+ * ^ |int example; | |(thread_local_size
|
|
|
+ * | | | |
|
|
|
+ * | |.tbss (*) | v
|
|
|
+ * | +-------------+ <-- task_thread_local_start
|
|
|
+ * 0xNNNN | | | ^
|
|
|
+ * | | | |
|
|
|
+ * | | | |_thread_local_start - _rodata_start
|
|
|
+ * | | | |
|
|
|
+ * | | | v
|
|
|
+ * v +-------------+ <-- threadptr
|
|
|
+ *
|
|
|
+ * (*) The stack grows downward!
|
|
|
+ */
|
|
|
task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf);
|
|
|
memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz);
|
|
|
threadptr = (uint32_t *)(sp + XT_STK_EXTRA);
|
|
|
- /* Calculate THREADPTR value:
|
|
|
+ /* Calculate THREADPTR value.
|
|
|
* The generated code will add THREADPTR value to a constant value determined at link time,
|
|
|
* to get the address of the TLS variable.
|
|
|
* The constant value is calculated by the linker as follows
|
|
|
* (search for 'tpoff' in elf32-xtensa.c in BFD):
|
|
|
* offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)
|
|
|
- * where TCB_SIZE is hardcoded to 8. There doesn't seem to be a way to propagate
|
|
|
- * the section alignment value from the ld script into the code, so it is hardcoded
|
|
|
- * in both places.
|
|
|
+ * where TCB_SIZE is hardcoded to 8.
|
|
|
+ * Note this is slightly different compared to the RISC-V port, where offset = address - tls_section_vma.
|
|
|
*/
|
|
|
- const uint32_t tls_section_alignment = 0x10; /* has to be in sync with ALIGN value of .flash.rodata section */
|
|
|
+ const uint32_t tls_section_alignment = (uint32_t) &_flash_rodata_align; /* ALIGN value of .flash.rodata section */
|
|
|
const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */
|
|
|
const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1));
|
|
|
- *threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_rodata_start) - base;
|
|
|
+ *threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base;
|
|
|
|
|
|
#if XCHAL_CP_NUM > 0
|
|
|
/* Init the coprocessor save area (see xtensa_context.h) */
|
|
|
@@ -385,7 +423,7 @@ uint32_t xPortGetTickRateHz(void) {
|
|
|
void __attribute__((optimize("-O3"))) vPortEnterCritical(portMUX_TYPE *mux)
|
|
|
{
|
|
|
BaseType_t oldInterruptLevel = portENTER_CRITICAL_NESTED();
|
|
|
- /* Interrupts may already be disabled (because we're doing this recursively)
|
|
|
+ /* Interrupts may already be disabled (because we're doing this recursively)
|
|
|
* but we can't get the interrupt level after
|
|
|
* vPortCPUAquireMutex, because it also may mess with interrupts.
|
|
|
* Get it here first, then later figure out if we're nesting
|
|
|
@@ -434,4 +472,4 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
|
|
|
dest = strcat(dest, str[i]);
|
|
|
}
|
|
|
esp_system_abort(buf);
|
|
|
-}
|
|
|
+}
|