|
|
@@ -227,9 +227,20 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
|
|
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);
|
|
|
- /* shift threadptr by the offset of _thread_local_start from DROM start;
|
|
|
- need to take into account extra 16 bytes offset */
|
|
|
- *threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_rodata_start) - 0x10;
|
|
|
+ /* 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.
|
|
|
+ */
|
|
|
+ const uint32_t tls_section_alignment = 0x10; /* has to be in sync with 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;
|
|
|
|
|
|
#if XCHAL_CP_NUM > 0
|
|
|
/* Init the coprocessor save area (see xtensa_context.h) */
|