diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d6188f775..1af1b8556f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,11 +74,22 @@ else() list(APPEND cxx_compile_options "-fno-exceptions") endif() -if(CONFIG_COMPILER_CXX_RTTI) - list(APPEND cxx_compile_options "-frtti") -else() - list(APPEND cxx_compile_options "-fno-rtti") - list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking +if(CONFIG_IDF_TOOLCHAIN_GCC) + if(CONFIG_COMPILER_CXX_RTTI) + idf_toolchain_remove_flags(CXX_COMPILE_OPTIONS "-fno-rtti" + LINK_OPTIONS "-fno-rtti") + else() + idf_toolchain_add_flags(CXX_COMPILE_OPTIONS "-fno-rtti" + LINK_OPTIONS "-fno-rtti") + endif() + idf_toolchain_rerun_abi_detection() +else() # TODO IDF-14338 + if(CONFIG_COMPILER_CXX_RTTI) + list(APPEND cxx_compile_options "-frtti") + else() + list(APPEND cxx_compile_options "-fno-rtti") + list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking + endif() endif() if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS) diff --git a/Kconfig b/Kconfig index 8fa992054e..3fa8988472 100644 --- a/Kconfig +++ b/Kconfig @@ -706,4 +706,3 @@ mainmenu "Espressif IoT Development Framework Configuration" - CONFIG_ESP_WIFI_EAP_TLS1_3 - CONFIG_ESP_WIFI_ENABLE_ROAMING_APP - CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS - - CONFIG_LIBC_PICOLIBC diff --git a/components/bt/common/osi/include/osi/pkt_queue.h b/components/bt/common/osi/include/osi/pkt_queue.h index 96277c3e18..38eff71ffa 100644 --- a/components/bt/common/osi/include/osi/pkt_queue.h +++ b/components/bt/common/osi/include/osi/pkt_queue.h @@ -10,6 +10,7 @@ #include "sys/queue.h" #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/components/bt/common/tinycrypt/src/ecc.c b/components/bt/common/tinycrypt/src/ecc.c index 1027c9a293..5e8495d31a 100644 --- a/components/bt/common/tinycrypt/src/ecc.c +++ b/components/bt/common/tinycrypt/src/ecc.c @@ -58,6 +58,7 @@ #include #include +#include #include #include diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index cbecbafff6..391c17db1a 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -224,6 +224,37 @@ FORCE_INLINE_ATTR __attribute__((pure)) void *esp_cpu_pc_to_addr(uint32_t pc) #endif } +/** + * @brief Set the current CPU core's thread pointer + * + * Sets the thread pointer register to the given value. + * + * @param threadptr Pointer to the thread-local storage area + */ +FORCE_INLINE_ATTR void esp_cpu_set_threadptr(void * threadptr) +{ +#ifdef __XTENSA__ + xt_utils_set_threadptr(threadptr); +#else + rv_utils_set_threadptr(threadptr); +#endif +} + +/** + * @brief Get the current CPU core's thread pointer + * + * @return thread pointer register value + */ +FORCE_INLINE_ATTR void *esp_cpu_get_threadptr(void) +{ +#ifdef __XTENSA__ + return xt_utils_get_threadptr(); +#else + return rv_utils_get_threadptr(); +#endif +} + + /* ------------------------------------------------- CPU Interrupts ---------------------------------------------------- * * ------------------------------------------------------------------------------------------------------------------ */ diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index e2c1801928..8faf53431a 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -144,7 +144,7 @@ endif() if(ESP_TEE_BUILD) rom_linker_script("heap") - if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) + if(CONFIG_LIBC_NEWLIB AND CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) rom_linker_script("newlib-nano") endif() endif() diff --git a/components/esp_rom/esp32/ld/esp32.rom.libc-funcs.ld b/components/esp_rom/esp32/ld/esp32.rom.libc-funcs.ld index 506c0f7753..662c7a0db5 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.libc-funcs.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.libc-funcs.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,18 +22,12 @@ bzero = 0x4000c1f4; div = 0x40056348; __dummy_lock = 0x4000c728; __dummy_lock_try = 0x4000c730; -isalnum = 0x40000f04; -isalpha = 0x40000f18; isascii = 0x4000c20c; isblank = 0x40000f2c; iscntrl = 0x40000f50; -isdigit = 0x40000f64; isgraph = 0x40000f94; -islower = 0x40000f78; isprint = 0x40000fa8; ispunct = 0x40000fc0; -isspace = 0x40000fd4; -isupper = 0x40000fe8; __itoa = 0x40056678; itoa = 0x400566b4; labs = 0x40056370; @@ -49,19 +43,15 @@ memset = 0x4000c44c; qsort = 0x40056424; __sccl = 0x4000c498; setjmp = 0x40056268; -strcasecmp = 0x400011cc; strcasestr = 0x40001210; strcat = 0x4000c518; strchr = 0x4000c53c; strcmp = 0x40001274; -strcoll = 0x40001398; strcpy = 0x400013ac; strcspn = 0x4000c558; strlcat = 0x40001470; strlcpy = 0x4000c584; strlen = 0x400014c0; -strlwr = 0x40001524; -strncasecmp = 0x40001550; strncat = 0x4000c5c4; strncmp = 0x4000c5f4; strncpy = 0x400015d4; @@ -70,10 +60,7 @@ strrchr = 0x40001708; strsep = 0x40001734; strspn = 0x4000c648; strstr = 0x4000c674; -strupr = 0x4000174c; __submore = 0x40058f3c; toascii = 0x4000c720; -tolower = 0x40001868; -toupper = 0x40001884; __utoa = 0x400561f0; utoa = 0x40056258; diff --git a/components/esp_rom/esp32/ld/esp32.rom.newlib-reent-funcs.ld b/components/esp_rom/esp32/ld/esp32.rom.newlib-reent-funcs.ld index 49c49b19b2..aa4f48f359 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.newlib-reent-funcs.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.newlib-reent-funcs.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,3 +59,16 @@ __sinit_lock_release = 0x40001e2c; __env_lock = 0x40001fd4; __env_unlock = 0x40001fe0; _getenv_r = 0x40001fbc; +tolower = 0x40001868; +toupper = 0x40001884; +isalnum = 0x40000f04; +isalpha = 0x40000f18; +isdigit = 0x40000f64; +islower = 0x40000f78; +isspace = 0x40000fd4; +isupper = 0x40000fe8; +strcasecmp = 0x400011cc; +strcoll = 0x40001398; +strlwr = 0x40001524; +strncasecmp = 0x40001550; +strupr = 0x4000174c; diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.libc.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.libc.ld index 920da09982..7d90b649ce 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.libc.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x400004a8; strstr = 0x400004ac; bzero = 0x400004b0; sbrk = 0x400004b8; -isalnum = 0x400004bc; -isalpha = 0x400004c0; isascii = 0x400004c4; isblank = 0x400004c8; iscntrl = 0x400004cc; -isdigit = 0x400004d0; -islower = 0x400004d4; isgraph = 0x400004d8; isprint = 0x400004dc; ispunct = 0x400004e0; -isspace = 0x400004e4; -isupper = 0x400004e8; -toupper = 0x400004ec; -tolower = 0x400004f0; toascii = 0x400004f4; memccpy = 0x400004f8; memchr = 0x400004fc; memrchr = 0x40000500; -strcasecmp = 0x40000504; strcasestr = 0x40000508; strcat = 0x4000050c; strchr = 0x40000514; strcspn = 0x40000518; -strcoll = 0x4000051c; strlcat = 0x40000520; strlcpy = 0x40000524; -strlwr = 0x40000528; -strncasecmp = 0x4000052c; strncat = 0x40000530; strnlen = 0x40000538; strrchr = 0x4000053c; strsep = 0x40000540; strspn = 0x40000544; strtok_r = 0x40000548; -strupr = 0x4000054c; longjmp = 0x40000550; setjmp = 0x40000554; abs = 0x40000558; diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.newlib.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.newlib.ld index a6963f86d0..f9eda11b4a 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.newlib.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,3 +63,16 @@ puts = 0x4000065c; putc = 0x40000660; putchar = 0x40000664; __errno = 0x40000670; +toupper = 0x400004ec; +tolower = 0x400004f0; +isalnum = 0x400004bc; +isalpha = 0x400004c0; +isdigit = 0x400004d0; +islower = 0x400004d4; +isspace = 0x400004e4; +isupper = 0x400004e8; +strcasecmp = 0x40000504; +strcoll = 0x4000051c; +strlwr = 0x40000528; +strncasecmp = 0x4000052c; +strupr = 0x4000054c; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.libc.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.libc.ld index a7476cac1d..f206243491 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.libc.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x40000374; strstr = 0x40000378; bzero = 0x4000037c; sbrk = 0x40000384; -isalnum = 0x40000388; -isalpha = 0x4000038c; isascii = 0x40000390; isblank = 0x40000394; iscntrl = 0x40000398; -isdigit = 0x4000039c; -islower = 0x400003a0; isgraph = 0x400003a4; isprint = 0x400003a8; ispunct = 0x400003ac; -isspace = 0x400003b0; -isupper = 0x400003b4; -toupper = 0x400003b8; -tolower = 0x400003bc; toascii = 0x400003c0; memccpy = 0x400003c4; memchr = 0x400003c8; memrchr = 0x400003cc; -strcasecmp = 0x400003d0; strcasestr = 0x400003d4; strcat = 0x400003d8; strchr = 0x400003e0; strcspn = 0x400003e4; -strcoll = 0x400003e8; strlcat = 0x400003ec; strlcpy = 0x400003f0; -strlwr = 0x400003f4; -strncasecmp = 0x400003f8; strncat = 0x400003fc; strnlen = 0x40000404; strrchr = 0x40000408; strsep = 0x4000040c; strspn = 0x40000410; strtok_r = 0x40000414; -strupr = 0x40000418; longjmp = 0x4000041c; setjmp = 0x40000420; abs = 0x40000424; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.newlib.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.newlib.ld index 69e93fccd9..2f3662e60c 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.newlib.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,3 +35,16 @@ PROVIDE( _fwalk = 0x40000464 ); PROVIDE( _fwalk_reent = 0x40000468 ); PROVIDE( __swbuf_r = 0x40000474 ); __swbuf = 0x40000478; +toupper = 0x400003b8; +tolower = 0x400003bc; +isalnum = 0x40000388; +isalpha = 0x4000038c; +isdigit = 0x4000039c; +islower = 0x400003a0; +isspace = 0x400003b0; +isupper = 0x400003b4; +strcasecmp = 0x400003d0; +strcoll = 0x400003e8; +strlwr = 0x400003f4; +strncasecmp = 0x400003f8; +strupr = 0x40000418; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.libc.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.libc.ld index a7b1e8b03c..ecdbff4f3a 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.libc.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.libc.ld @@ -24,41 +24,28 @@ strlen = 0x400004d8; strstr = 0x400004dc; bzero = 0x400004e0; sbrk = 0x400004e8; -isalnum = 0x400004ec; -isalpha = 0x400004f0; isascii = 0x400004f4; isblank = 0x400004f8; iscntrl = 0x400004fc; -isdigit = 0x40000500; -islower = 0x40000504; isgraph = 0x40000508; isprint = 0x4000050c; ispunct = 0x40000510; -isspace = 0x40000514; -isupper = 0x40000518; -toupper = 0x4000051c; -tolower = 0x40000520; toascii = 0x40000524; memccpy = 0x40000528; memchr = 0x4000052c; memrchr = 0x40000530; -strcasecmp = 0x40000534; strcasestr = 0x40000538; strcat = 0x4000053c; strchr = 0x40000544; strcspn = 0x40000548; -strcoll = 0x4000054c; strlcat = 0x40000550; strlcpy = 0x40000554; -strlwr = 0x40000558; -strncasecmp = 0x4000055c; strncat = 0x40000560; strnlen = 0x40000568; strrchr = 0x4000056c; strsep = 0x40000570; strspn = 0x40000574; strtok_r = 0x40000578; -strupr = 0x4000057c; longjmp = 0x40000580; setjmp = 0x40000584; abs = 0x40000588; diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.newlib.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.newlib.ld index 0a970172a7..24806f1995 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.newlib.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.newlib.ld @@ -37,3 +37,16 @@ __swhatbuf_r = 0x400005d4; __swbuf_r = 0x400005d8; __swbuf = 0x400005dc; __swsetup_r = 0x400005e0; +toupper = 0x4000051c; +tolower = 0x40000520; +isalnum = 0x400004ec; +isalpha = 0x400004f0; +isdigit = 0x40000500; +islower = 0x40000504; +isspace = 0x40000514; +isupper = 0x40000518; +strcasecmp = 0x40000534; +strcoll = 0x4000054c; +strlwr = 0x40000558; +strncasecmp = 0x4000055c; +strupr = 0x4000057c; diff --git a/components/esp_rom/esp32c6/ld/esp32c6.rom.libc.ld b/components/esp_rom/esp32c6/ld/esp32c6.rom.libc.ld index 16c5b60710..4f3356731f 100644 --- a/components/esp_rom/esp32c6/ld/esp32c6.rom.libc.ld +++ b/components/esp_rom/esp32c6/ld/esp32c6.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x400004c8; strstr = 0x400004cc; bzero = 0x400004d0; sbrk = 0x400004d8; -isalnum = 0x400004dc; -isalpha = 0x400004e0; isascii = 0x400004e4; isblank = 0x400004e8; iscntrl = 0x400004ec; -isdigit = 0x400004f0; -islower = 0x400004f4; isgraph = 0x400004f8; isprint = 0x400004fc; ispunct = 0x40000500; -isspace = 0x40000504; -isupper = 0x40000508; -toupper = 0x4000050c; -tolower = 0x40000510; toascii = 0x40000514; memccpy = 0x40000518; memchr = 0x4000051c; memrchr = 0x40000520; -strcasecmp = 0x40000524; strcasestr = 0x40000528; strcat = 0x4000052c; strchr = 0x40000534; strcspn = 0x40000538; -strcoll = 0x4000053c; strlcat = 0x40000540; strlcpy = 0x40000544; -strlwr = 0x40000548; -strncasecmp = 0x4000054c; strncat = 0x40000550; strnlen = 0x40000558; strrchr = 0x4000055c; strsep = 0x40000560; strspn = 0x40000564; strtok_r = 0x40000568; -strupr = 0x4000056c; longjmp = 0x40000570; setjmp = 0x40000574; abs = 0x40000578; diff --git a/components/esp_rom/esp32c6/ld/esp32c6.rom.newlib.ld b/components/esp_rom/esp32c6/ld/esp32c6.rom.newlib.ld index 2bae479247..454a1779ab 100644 --- a/components/esp_rom/esp32c6/ld/esp32c6.rom.newlib.ld +++ b/components/esp_rom/esp32c6/ld/esp32c6.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,3 +39,16 @@ __swhatbuf_r = 0x400005c4; __swbuf_r = 0x400005c8; __swbuf = 0x400005cc; __swsetup_r = 0x400005d0; +toupper = 0x4000050c; +tolower = 0x40000510; +isalnum = 0x400004dc; +isalpha = 0x400004e0; +isdigit = 0x400004f0; +islower = 0x400004f4; +isspace = 0x40000504; +isupper = 0x40000508; +strcasecmp = 0x40000524; +strcoll = 0x4000053c; +strlwr = 0x40000548; +strncasecmp = 0x4000054c; +strupr = 0x4000056c; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.libc.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.libc.ld index 771fa2f084..676cfcdf2c 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.libc.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x400004d8; strstr = 0x400004dc; bzero = 0x400004e0; sbrk = 0x400004e8; -isalnum = 0x400004ec; -isalpha = 0x400004f0; isascii = 0x400004f4; isblank = 0x400004f8; iscntrl = 0x400004fc; -isdigit = 0x40000500; -islower = 0x40000504; isgraph = 0x40000508; isprint = 0x4000050c; ispunct = 0x40000510; -isspace = 0x40000514; -isupper = 0x40000518; -toupper = 0x4000051c; -tolower = 0x40000520; toascii = 0x40000524; memccpy = 0x40000528; memchr = 0x4000052c; memrchr = 0x40000530; -strcasecmp = 0x40000534; strcasestr = 0x40000538; strcat = 0x4000053c; strchr = 0x40000544; strcspn = 0x40000548; -strcoll = 0x4000054c; strlcat = 0x40000550; strlcpy = 0x40000554; -strlwr = 0x40000558; -strncasecmp = 0x4000055c; strncat = 0x40000560; strnlen = 0x40000568; strrchr = 0x4000056c; strsep = 0x40000570; strspn = 0x40000574; strtok_r = 0x40000578; -strupr = 0x4000057c; longjmp = 0x40000580; setjmp = 0x40000584; abs = 0x40000588; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.newlib.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.newlib.ld index 0e6df59a28..80a4717173 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.newlib.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,3 +39,16 @@ __swhatbuf_r = 0x400005d4; __swbuf_r = 0x400005d8; __swbuf = 0x400005dc; __swsetup_r = 0x400005e0; +toupper = 0x4000051c; +tolower = 0x40000520; +isalnum = 0x400004ec; +isalpha = 0x400004f0; +isdigit = 0x40000500; +islower = 0x40000504; +isspace = 0x40000514; +isupper = 0x40000518; +strcasecmp = 0x40000534; +strcoll = 0x4000054c; +strlwr = 0x40000558; +strncasecmp = 0x4000055c; +strupr = 0x4000057c; diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.libc.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.libc.ld index d6680a5d7f..2ad368242c 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.libc.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x400004c0; strstr = 0x400004c4; bzero = 0x400004c8; sbrk = 0x400004d0; -isalnum = 0x400004d4; -isalpha = 0x400004d8; isascii = 0x400004dc; isblank = 0x400004e0; iscntrl = 0x400004e4; -isdigit = 0x400004e8; -islower = 0x400004ec; isgraph = 0x400004f0; isprint = 0x400004f4; ispunct = 0x400004f8; -isspace = 0x400004fc; -isupper = 0x40000500; -toupper = 0x40000504; -tolower = 0x40000508; toascii = 0x4000050c; memccpy = 0x40000510; memchr = 0x40000514; memrchr = 0x40000518; -strcasecmp = 0x4000051c; strcasestr = 0x40000520; strcat = 0x40000524; strchr = 0x4000052c; strcspn = 0x40000530; -strcoll = 0x40000534; strlcat = 0x40000538; strlcpy = 0x4000053c; -strlwr = 0x40000540; -strncasecmp = 0x40000544; strncat = 0x40000548; strnlen = 0x40000550; strrchr = 0x40000554; strsep = 0x40000558; strspn = 0x4000055c; strtok_r = 0x40000560; -strupr = 0x40000564; longjmp = 0x40000568; setjmp = 0x4000056c; abs = 0x40000570; diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.newlib.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.newlib.ld index 770211f2c3..2392259836 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.newlib.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,3 +39,16 @@ __swhatbuf_r = 0x400005bc; __swbuf_r = 0x400005c0; __swbuf = 0x400005c4; __swsetup_r = 0x400005c8; +toupper = 0x40000504; +tolower = 0x40000508; +isalnum = 0x400004d4; +isalpha = 0x400004d8; +isdigit = 0x400004e8; +islower = 0x400004ec; +isspace = 0x400004fc; +isupper = 0x40000500; +strcasecmp = 0x4000051c; +strcoll = 0x40000534; +strlwr = 0x40000540; +strncasecmp = 0x40000544; +strupr = 0x40000564; diff --git a/components/esp_rom/esp32h21/ld/esp32h21.rom.libc.ld b/components/esp_rom/esp32h21/ld/esp32h21.rom.libc.ld index 18a91402e1..830b2e454a 100644 --- a/components/esp_rom/esp32h21/ld/esp32h21.rom.libc.ld +++ b/components/esp_rom/esp32h21/ld/esp32h21.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x400004b8; strstr = 0x400004bc; bzero = 0x400004c0; sbrk = 0x400004c8; -isalnum = 0x400004cc; -isalpha = 0x400004d0; isascii = 0x400004d4; isblank = 0x400004d8; iscntrl = 0x400004dc; -isdigit = 0x400004e0; -islower = 0x400004e4; isgraph = 0x400004e8; isprint = 0x400004ec; ispunct = 0x400004f0; -isspace = 0x400004f4; -isupper = 0x400004f8; -toupper = 0x400004fc; -tolower = 0x40000500; toascii = 0x40000504; memccpy = 0x40000508; memchr = 0x4000050c; memrchr = 0x40000510; -strcasecmp = 0x40000514; strcasestr = 0x40000518; strcat = 0x4000051c; strchr = 0x40000524; strcspn = 0x40000528; -strcoll = 0x4000052c; strlcat = 0x40000530; strlcpy = 0x40000534; -strlwr = 0x40000538; -strncasecmp = 0x4000053c; strncat = 0x40000540; strnlen = 0x40000548; strrchr = 0x4000054c; strsep = 0x40000550; strspn = 0x40000554; strtok_r = 0x40000558; -strupr = 0x4000055c; longjmp = 0x40000560; setjmp = 0x40000564; abs = 0x40000568; diff --git a/components/esp_rom/esp32h21/ld/esp32h21.rom.newlib.ld b/components/esp_rom/esp32h21/ld/esp32h21.rom.newlib.ld index 1f79078a48..0d1ca97329 100644 --- a/components/esp_rom/esp32h21/ld/esp32h21.rom.newlib.ld +++ b/components/esp_rom/esp32h21/ld/esp32h21.rom.newlib.ld @@ -39,3 +39,16 @@ __swhatbuf_r = 0x400005b4; __swbuf_r = 0x400005b8; __swbuf = 0x400005bc; __swsetup_r = 0x400005c0; +toupper = 0x400004fc; +tolower = 0x40000500; +isalnum = 0x400004cc; +isalpha = 0x400004d0; +isdigit = 0x400004e0; +islower = 0x400004e4; +isspace = 0x400004f4; +isupper = 0x400004f8; +strcasecmp = 0x40000514; +strcoll = 0x4000052c; +strlwr = 0x40000538; +strncasecmp = 0x4000053c; +strupr = 0x4000055c; diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.libc.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.libc.ld index 65d90e205f..f38b60c22f 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.libc.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.libc.ld @@ -9,41 +9,28 @@ strlen = 0x4fc00288; strstr = 0x4fc0028c; bzero = 0x4fc00290; sbrk = 0x4fc00298; -isalnum = 0x4fc0029c; -isalpha = 0x4fc002a0; isascii = 0x4fc002a4; isblank = 0x4fc002a8; iscntrl = 0x4fc002ac; -isdigit = 0x4fc002b0; -islower = 0x4fc002b4; isgraph = 0x4fc002b8; isprint = 0x4fc002bc; ispunct = 0x4fc002c0; -isspace = 0x4fc002c4; -isupper = 0x4fc002c8; -toupper = 0x4fc002cc; -tolower = 0x4fc002d0; toascii = 0x4fc002d4; memccpy = 0x4fc002d8; memchr = 0x4fc002dc; memrchr = 0x4fc002e0; -strcasecmp = 0x4fc002e4; strcasestr = 0x4fc002e8; strcat = 0x4fc002ec; strchr = 0x4fc002f4; strcspn = 0x4fc002f8; -strcoll = 0x4fc002fc; strlcat = 0x4fc00300; strlcpy = 0x4fc00304; -strlwr = 0x4fc00308; -strncasecmp = 0x4fc0030c; strncat = 0x4fc00310; strnlen = 0x4fc00318; strrchr = 0x4fc0031c; strsep = 0x4fc00320; strspn = 0x4fc00324; strtok_r = 0x4fc00328; -strupr = 0x4fc0032c; longjmp = 0x4fc00330; setjmp = 0x4fc00334; abs = 0x4fc00338; diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.newlib.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.newlib.ld index 2929b424ff..369d1c01fe 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.newlib.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.newlib.ld @@ -39,3 +39,16 @@ __swhatbuf_r = 0x4fc00384; __swbuf_r = 0x4fc00388; __swbuf = 0x4fc0038c; __swsetup_r = 0x4fc00390; +toupper = 0x4fc002cc; +tolower = 0x4fc002d0; +isalnum = 0x4fc0029c; +isalpha = 0x4fc002a0; +isdigit = 0x4fc002b0; +islower = 0x4fc002b4; +isspace = 0x4fc002c4; +isupper = 0x4fc002c8; +strcasecmp = 0x4fc002e4; +strcoll = 0x4fc002fc; +strlwr = 0x4fc00308; +strncasecmp = 0x4fc0030c; +strupr = 0x4fc0032c; diff --git a/components/esp_rom/esp32s2/ld/esp32s2.rom.libc-funcs.ld b/components/esp_rom/esp32s2/ld/esp32s2.rom.libc-funcs.ld index ae5bc633bf..863508a4f0 100644 --- a/components/esp_rom/esp32s2/ld/esp32s2.rom.libc-funcs.ld +++ b/components/esp_rom/esp32s2/ld/esp32s2.rom.libc-funcs.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,18 +17,12 @@ PROVIDE ( __assert = 0x4001a430 ); PROVIDE ( __assert_func = 0x4001a408 ); bzero = 0x400078c8; div = 0x40000620; -isalnum = 0x400078d8; -isalpha = 0x400078e8; isascii = 0x4001aaec; isblank = 0x400078f8; iscntrl = 0x40007918; -isdigit = 0x40007930; isgraph = 0x40007968; -islower = 0x40007948; isprint = 0x40007980; ispunct = 0x40007994; -isspace = 0x400079ac; -isupper = 0x400079c4; labs = 0x40000648; ldiv = 0x40000650; longjmp = 0x400005a4; @@ -44,14 +38,11 @@ setjmp = 0x40000540; strcat = 0x4001ad90; strchr = 0x4001adb0; strcmp = 0x40007be4; -strcoll = 0x40007ce8; strcpy = 0x40007cfc; strcspn = 0x4001adcc; strlcat = 0x40007db8; strlcpy = 0x4001adf8; strlen = 0x40007e08; -strlwr = 0x40007e68; -strncasecmp = 0x40007e94; strncat = 0x4001ae34; strncmp = 0x4001ae64; strncpy = 0x40007f20; @@ -62,7 +53,4 @@ strspn = 0x4001aebc; strstr = 0x4001aee8; __strtok_r = 0x4001af18; strtok_r = 0x4001af7c; -strupr = 0x40008084; toascii = 0x4001af90; -tolower = 0x40008158; -toupper = 0x40008174; diff --git a/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-reent-funcs.ld b/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-reent-funcs.ld index 4b8aa9c26c..dc4ef563ab 100644 --- a/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-reent-funcs.ld +++ b/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-reent-funcs.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,3 +50,15 @@ __locale_ctype_ptr_l = 0x40001c24; __locale_mb_cur_max = 0x40001c0c; strcasecmp = 0x40007b38; strcasestr = 0x40007b7c; +tolower = 0x40008158; +toupper = 0x40008174; +isalnum = 0x400078d8; +isalpha = 0x400078e8; +isdigit = 0x40007930; +islower = 0x40007948; +isspace = 0x400079ac; +isupper = 0x400079c4; +strcoll = 0x40007ce8; +strlwr = 0x40007e68; +strncasecmp = 0x40007e94; +strupr = 0x40008084; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld index cf3f350174..73a3ac5e83 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,41 +16,28 @@ strlen = 0x40001248; strstr = 0x40001254; bzero = 0x40001260; sbrk = 0x40001278; -isalnum = 0x40001284; -isalpha = 0x40001290; isascii = 0x4000129c; isblank = 0x400012a8; iscntrl = 0x400012b4; -isdigit = 0x400012c0; -islower = 0x400012cc; isgraph = 0x400012d8; isprint = 0x400012e4; ispunct = 0x400012f0; -isspace = 0x400012fc; -isupper = 0x40001308; -toupper = 0x40001314; -tolower = 0x40001320; toascii = 0x4000132c; memccpy = 0x40001338; memchr = 0x40001344; memrchr = 0x40001350; -strcasecmp = 0x4000135c; strcasestr = 0x40001368; strcat = 0x40001374; strchr = 0x4000138c; strcspn = 0x40001398; -strcoll = 0x400013a4; strlcat = 0x400013b0; strlcpy = 0x400013bc; -strlwr = 0x400013c8; -strncasecmp = 0x400013d4; strncat = 0x400013e0; strnlen = 0x400013f8; strrchr = 0x40001404; strsep = 0x40001410; strspn = 0x4000141c; strtok_r = 0x40001428; -strupr = 0x40001434; longjmp = 0x40001440; setjmp = 0x4000144c; abs = 0x40001458; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld index b0957aac2a..f964e305f8 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,3 +29,16 @@ PROVIDE( _fwalk = 0x40001518 ); PROVIDE( _fwalk_reent = 0x40001524 ); PROVIDE( __swbuf_r = 0x40001548 ); __swbuf = 0x40001554; +toupper = 0x40001314; +tolower = 0x40001320; +isalnum = 0x40001284; +isalpha = 0x40001290; +isdigit = 0x400012c0; +islower = 0x400012cc; +isspace = 0x400012fc; +isupper = 0x40001308; +strcasecmp = 0x4000135c; +strcoll = 0x400013a4; +strlwr = 0x400013c8; +strncasecmp = 0x400013d4; +strupr = 0x40001434; diff --git a/components/esp_system/ld/elf_misc.ld.in b/components/esp_system/ld/elf_misc.ld.in index d9891a34e8..ce56428853 100644 --- a/components/esp_system/ld/elf_misc.ld.in +++ b/components/esp_system/ld/elf_misc.ld.in @@ -66,7 +66,9 @@ * And so forth... */ *(.rela.*) +#if CONFIG_LIBC_NEWLIB *(.got .got.plt) /* TODO: GCC-382 */ +#endif #if !EH_FRAME_LINKING_ENABLED *(.eh_frame_hdr) *(.eh_frame) diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index 930e1b4cda..fd13d6afd8 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -384,12 +384,24 @@ SECTIONS /* TLS data. */ ALIGNED_SYMBOL(4, _thread_local_start) +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT_PICOLIBC_REENT_STUB() _flash_rodata_align = ALIGNOF(.flash.rodata); diff --git a/components/esp_system/ld/esp32c2/sections.ld.in b/components/esp_system/ld/esp32c2/sections.ld.in index 8986e49940..4db9c8e5fc 100644 --- a/components/esp_system/ld/esp32c2/sections.ld.in +++ b/components/esp_system/ld/esp32c2/sections.ld.in @@ -188,6 +188,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -262,24 +265,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -292,7 +312,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 5c84d3cd5a..2bd4bcfa1e 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -310,6 +310,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -384,24 +387,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -414,7 +434,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32c5/sections.ld.in b/components/esp_system/ld/esp32c5/sections.ld.in index 7bb97c4d92..b865acd4e0 100644 --- a/components/esp_system/ld/esp32c5/sections.ld.in +++ b/components/esp_system/ld/esp32c5/sections.ld.in @@ -359,6 +359,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -433,32 +436,41 @@ SECTIONS .flash.tdata : { - _thread_local_data_start = ABSOLUTE(.); - - *(.tdata .tdata.* .gnu.linkonce.td.*) - - . = ALIGN(ALIGNOF(.flash.tbss)); - -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -466,12 +478,18 @@ SECTIONS */ .flash.rodata_noload (NOLOAD) : { +#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /* Align the end of flash rodata region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION /** * This symbol marks the end of flash.rodata. It can be utilized by the MMU * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index f2b2df7926..ed1841e2a7 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -355,6 +355,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -429,24 +432,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -459,7 +479,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32c61/sections.ld.in b/components/esp_system/ld/esp32c61/sections.ld.in index e6c48b5452..40b7d82740 100644 --- a/components/esp_system/ld/esp32c61/sections.ld.in +++ b/components/esp_system/ld/esp32c61/sections.ld.in @@ -204,6 +204,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -278,32 +281,41 @@ SECTIONS .flash.tdata : { - _thread_local_data_start = ABSOLUTE(.); - - *(.tdata .tdata.* .gnu.linkonce.td.*) - - . = ALIGN(ALIGNOF(.flash.tbss)); - -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -311,12 +323,18 @@ SECTIONS */ .flash.rodata_noload (NOLOAD) : { +#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /* Align the end of flash rodata region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION /** * This symbol marks the end of flash.rodata. It can be utilized by the MMU * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index be973ed63c..09dd47ed2e 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -357,6 +357,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -431,24 +434,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -461,7 +481,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32h21/sections.ld.in b/components/esp_system/ld/esp32h21/sections.ld.in index dc628feeff..cb7b93517c 100644 --- a/components/esp_system/ld/esp32h21/sections.ld.in +++ b/components/esp_system/ld/esp32h21/sections.ld.in @@ -346,6 +346,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -420,24 +423,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -450,7 +470,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32h4/sections.ld.in b/components/esp_system/ld/esp32h4/sections.ld.in index 9e5761b2c1..3dbf9aa964 100644 --- a/components/esp_system/ld/esp32h4/sections.ld.in +++ b/components/esp_system/ld/esp32h4/sections.ld.in @@ -191,6 +191,9 @@ SECTIONS mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -265,24 +268,41 @@ SECTIONS .flash.tdata : { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ _thread_local_data_start = ABSOLUTE(.); - +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -295,7 +315,7 @@ SECTIONS * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; mapping[rodata_noload] } > default_rodata_seg diff --git a/components/esp_system/ld/esp32p4/sections.ld.in b/components/esp_system/ld/esp32p4/sections.ld.in index b062587f7c..d3a97e8124 100644 --- a/components/esp_system/ld/esp32p4/sections.ld.in +++ b/components/esp_system/ld/esp32p4/sections.ld.in @@ -362,6 +362,9 @@ SECTIONS arrays[flash_rodata] mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -442,32 +445,41 @@ SECTIONS .flash.tdata : { - _thread_local_data_start = ABSOLUTE(.); - - *(.tdata .tdata.* .gnu.linkonce.td.*) - - . = ALIGN(ALIGNOF(.flash.tbss)); - -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > rodata_seg_low ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > rodata_seg_low + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -475,12 +487,18 @@ SECTIONS */ .flash.rodata_noload (NOLOAD) : { +#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /* Align the end of flash rodata region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION /** * This symbol marks the end of flash.rodata. It can be utilized by the MMU * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; arrays[rodata_noload] mapping[rodata_noload] diff --git a/components/esp_system/ld/esp32p4/sections.rev3.ld.in b/components/esp_system/ld/esp32p4/sections.rev3.ld.in index d8cbd25729..3ff1254a5b 100644 --- a/components/esp_system/ld/esp32p4/sections.rev3.ld.in +++ b/components/esp_system/ld/esp32p4/sections.rev3.ld.in @@ -388,6 +388,9 @@ SECTIONS arrays[flash_rodata] mapping[flash_rodata] +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -405,6 +408,7 @@ SECTIONS * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. */ ALIGNED_SYMBOL(4, __preinit_array_start) + ALIGNED_SYMBOL(4, __bothinit_array_start) KEEP (*(.preinit_array)) __preinit_array_end = ABSOLUTE(.); @@ -417,6 +421,7 @@ SECTIONS ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); + __bothinit_array_end = ABSOLUTE(.); /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) @@ -466,32 +471,41 @@ SECTIONS .flash.tdata : { - _thread_local_data_start = ABSOLUTE(.); - - *(.tdata .tdata.* .gnu.linkonce.td.*) - - . = ALIGN(ALIGNOF(.flash.tbss)); - -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(ALIGNOF(.flash.tbss)); _thread_local_data_end = ABSOLUTE(.); } > rodata_seg_low ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() .flash.tbss (NOLOAD) : { + /* tbss sections */ _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); } > rodata_seg_low + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -499,12 +513,18 @@ SECTIONS */ .flash.rodata_noload (NOLOAD) : { +#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /* Align the end of flash rodata region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION /** * This symbol marks the end of flash.rodata. It can be utilized by the MMU * driver to maintain the virtual address. * NOLOAD rodata may not be included in this section. */ - _rodata_reserved_end = ADDR(.flash.tbss); + _rodata_reserved_end = .; arrays[rodata_noload] mapping[rodata_noload] diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index f0df70ac03..f73da10233 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -387,12 +387,24 @@ SECTIONS /* TLS data. */ ALIGNED_SYMBOL(4, _thread_local_start) +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT_PICOLIBC_REENT_STUB() _flash_rodata_align = ALIGNOF(.flash.rodata); diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index f293976428..bf71a95412 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -399,12 +399,24 @@ SECTIONS /* TLS data. */ ALIGNED_SYMBOL(4, _thread_local_start) +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent. */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); } > default_rodata_seg + ASSERT_PICOLIBC_REENT_STUB() _flash_rodata_align = ALIGNOF(.flash.rodata); diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index 2af596f33e..f2e2570ef7 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -109,3 +109,14 @@ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ #else #define SECTION_AFTER_FLASH_RODATA .flash.tdata #endif + +#if CONFIG_LIBC_PICOLIBC +# if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +# define PICOLIBC_REENT_STUB 16 +# else +# define PICOLIBC_REENT_STUB 4 +# endif +#define ASSERT_PICOLIBC_REENT_STUB() ASSERT((_picolibc_reent_stub_end - _picolibc_reent_stub_start) == PICOLIBC_REENT_STUB, "Newlib _reent stub have wrong size") +#else +#define ASSERT_PICOLIBC_REENT_STUB() +#endif diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index f77b172e31..63f0c8659e 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -194,6 +194,21 @@ static void core_intr_matrix_clear(void) #endif // SOC_INT_CLIC_SUPPORTED } +#if CONFIG_LIBC_PICOLIBC +FORCE_INLINE_ATTR IRAM_ATTR void init_pre_rtos_tls_area(int cpu_num) +{ + /** + * Initialize the TLS area before RTOS starts, in case any code tries to access + * TLS variables. + * + * TODO IDF-14914: Currently, we only initialize errno, which is the first TLS + * variable as guaranteed by the linker script. + */ + static int s_errno_array[SOC_CPU_CORES_NUM]; + esp_cpu_set_threadptr(&s_errno_array[cpu_num]); +} +#endif + #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE void startup_resume_other_cores(void) { @@ -214,6 +229,10 @@ void ESP_SYSTEM_IRAM_ATTR call_start_cpu1(void) ); #endif //#ifdef __riscv +#if CONFIG_LIBC_PICOLIBC + init_pre_rtos_tls_area(1); +#endif + #if SOC_BRANCH_PREDICTOR_SUPPORTED esp_cpu_branch_prediction_enable(); #endif //#if SOC_BRANCH_PREDICTOR_SUPPORTED @@ -935,6 +954,10 @@ void IRAM_ATTR call_start_cpu0(void) // Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this. init_bss(rst_reas); +#if CONFIG_LIBC_PICOLIBC + init_pre_rtos_tls_area(0); +#endif + // When the APP is loaded into ram for execution, some hardware initialization steps used to be executed in the // bootloader are done here. #if CONFIG_APP_BUILD_TYPE_RAM diff --git a/components/hal/platform_port/include/hal/assert.h b/components/hal/platform_port/include/hal/assert.h index 48e5c3ba65..c8db9b4c87 100644 --- a/components/hal/platform_port/include/hal/assert.h +++ b/components/hal/platform_port/include/hal/assert.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +11,20 @@ extern "C" { #endif -extern void __assert_func(const char *file, int line, const char *func, const char *expr); -extern void abort(void); +#if CONFIG_LIBC_PICOLIBC +#if defined(__cplusplus) && __cplusplus >= 201103L +#define __noreturn [[noreturn]] +#elif __has_attribute(__noreturn__) +#define __noreturn __attribute__((__noreturn__)) +#else +#define __noreturn +#endif +#else +#define __noreturn +#endif + +__noreturn void __assert_func(const char *file, int line, const char *func, const char *expr); +__noreturn void abort(void); #ifndef __ASSERT_FUNC #ifdef __ASSERT_FUNCTION diff --git a/components/heap/test_apps/heap_tests/main/test_heap_trace.c b/components/heap/test_apps/heap_tests/main/test_heap_trace.c index f50b7e02a0..9df51df288 100644 --- a/components/heap/test_apps/heap_tests/main/test_heap_trace.c +++ b/components/heap/test_apps/heap_tests/main/test_heap_trace.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -128,13 +128,21 @@ TEST_CASE("heap trace wrapped buffer check", "[heap-trace]") heap_trace_stop(); } -static void print_floats_task(void *ignore) +static void trace_libc_allocs_task(void *ignore) { heap_trace_start(HEAP_TRACE_ALL); + +#if CONFIG_LIBC_NEWLIB char buf[16] = { }; volatile float f = 12.3456; sprintf(buf, "%.4f", f); TEST_ASSERT_EQUAL_STRING("12.3456", buf); +#endif +#if CONFIG_LIBC_PICOLIBC + FILE* f = fdopen(100, "r"); + fclose(f); +#endif + heap_trace_stop(); vTaskDelete(NULL); @@ -158,11 +166,10 @@ TEST_CASE("can trace allocations made by newlib", "[heap-trace]") - We also do the tracing in the task so we only capture things directly related to it. */ - xTaskCreate(print_floats_task, "print_float", 4096, NULL, 5, NULL); + xTaskCreate(trace_libc_allocs_task, "trace_libc_allocs_task", 4096, NULL, 5, NULL); vTaskDelay(10); - /* has to be at least a few as newlib allocates via multiple different function calls */ - TEST_ASSERT(heap_trace_get_count() > 3); + TEST_ASSERT(heap_trace_get_count() > 0); } TEST_CASE("can stop recording allocs but continue recording frees", "[heap-trace]") diff --git a/components/lwip/port/esp32xx/include/arch/cc.h b/components/lwip/port/esp32xx/include/arch/cc.h index 486e2782bd..656a82ae0f 100644 --- a/components/lwip/port/esp32xx/include/arch/cc.h +++ b/components/lwip/port/esp32xx/include/arch/cc.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-3-Clause * - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD */ #ifndef __ARCH_CC_H__ #define __ARCH_CC_H__ @@ -25,10 +25,18 @@ extern "C" { #endif // BYTE_ORDER #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#ifndef htons #define htons(x) __builtin_bswap16(x) +#endif +#ifndef ntohs #define ntohs(x) __builtin_bswap16(x) +#endif +#ifndef htonl #define htonl(x) __builtin_bswap32(x) +#endif +#ifndef ntohl #define ntohl(x) __builtin_bswap32(x) +#endif #ifndef CONFIG_LWIP_ESP_LWIP_ASSERT #define LWIP_NOASSERT 1 diff --git a/components/lwip/test_apps/main/lwip_test.c b/components/lwip/test_apps/main/lwip_test.c index 187f5abd91..4611648e9c 100644 --- a/components/lwip/test_apps/main/lwip_test.c +++ b/components/lwip/test_apps/main/lwip_test.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include "freertos/FreeRTOS.h" diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index d7c0a0bf88..29363db53e 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -63,7 +63,11 @@ else() list(APPEND srcs "src/picolibc/picolibc_init.c" "src/picolibc/rand.c" - "src/picolibc/open_memstream.c") + "src/picolibc/open_memstream.c" + "src/picolibc/errno.c") + if(CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY) + list(APPEND srcs "src/picolibc/getreent.c") + endif() endif() list(APPEND ldfragments "src/newlib.lf" "src/system_libs.lf") diff --git a/components/newlib/Kconfig b/components/newlib/Kconfig index 9a30784c21..17e9d38358 100644 --- a/components/newlib/Kconfig +++ b/components/newlib/Kconfig @@ -7,10 +7,40 @@ menu "LibC" config LIBC_NEWLIB bool "NewLib" config LIBC_PICOLIBC - bool "Picolibc (EXPERIMENTAL)" - depends on !IDF_TOOLCHAIN_CLANG && IDF_EXPERIMENTAL_FEATURES + bool "Picolibc" + depends on !IDF_TOOLCHAIN_CLANG endchoice + config LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + bool "Provides limited interoperability with libraries built using Newlib headers" + default y + depends on LIBC_PICOLIBC + help + This option provides limited compatibility with libraries built using Newlib headers by: + + Enabling hidden system-header inclusions that exist in Newlib. + Adding tls_stdio, tls_stdout, and tls_stderr variables to Thread Local Storage + to allow prebuilt libraries to access them via getreent(). + Providing an implementation of getreent() that returns the value of the thread-pointer register. + + Limitations: + + 1. If your application or an external prebuilt library accesses Newlib "struct _reent" implicitly, + this may cause memory corruption on the task stack. You have two options: + + - Use libc API calls instead of directly accessing "struct _reent" fields. + - Switch ESP-IDF to use the Newlib implementation by setting CONFIG_LIBC_NEWLIB=y in sdkconfig. + + 2. If your application uses a prebuilt library built with Newlib headers, you may encounter + unexpected behavior when overriding stdin, stdout, and stderr. External prebuilt libraries + can only read these streams, so overriding them will not affect as it was for Newlib. + You have two options to fix this: + + - Rebuild the library with Picolibc headers that follow POSIX-standardized stdin, stdout, + and stderr declarations. + - Switch ESP-IDF to use the Newlib implementation by setting CONFIG_LIBC_NEWLIB=y in sdkconfig. + + config LIBC_MISC_IN_IRAM bool "Place misc libc functions (abort/assert/stdatomics) in IRAM" if SPI_FLASH_AUTO_SUSPEND default y @@ -18,7 +48,6 @@ menu "LibC" config LIBC_LOCKS_PLACE_IN_IRAM bool "Place lock API in IRAM" default y - depends on LIBC_NEWLIB help Enable this option to include be able to call the lock API from code that runs while cache is disabled, e.g. IRAM interrupts. diff --git a/components/newlib/platform_include/stdio.h b/components/newlib/platform_include/stdio.h index 282bc2319c..2322f9a8dd 100644 --- a/components/newlib/platform_include/stdio.h +++ b/components/newlib/platform_include/stdio.h @@ -1,16 +1,24 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include_next #include "sdkconfig.h" -#include_next +#ifdef __cplusplus +extern "C" { +#endif -#if CONFIG_LIBC_PICOLIBC +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +#include void flockfile(FILE *); void funlockfile(FILE *); FILE *open_memstream(char **, size_t *); #endif + +#ifdef __cplusplus +} +#endif diff --git a/components/newlib/platform_include/stdio_ext.h b/components/newlib/platform_include/stdio_ext.h index 8c49947ff3..0ac12ebe12 100644 --- a/components/newlib/platform_include/stdio_ext.h +++ b/components/newlib/platform_include/stdio_ext.h @@ -9,6 +9,8 @@ #if CONFIG_LIBC_NEWLIB #include_next -#else +#endif + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY #include #endif diff --git a/components/newlib/platform_include/sys/cdefs.h b/components/newlib/platform_include/sys/cdefs.h new file mode 100644 index 0000000000..d87dbd85aa --- /dev/null +++ b/components/newlib/platform_include/sys/cdefs.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include_next +#include "sdkconfig.h" + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +#include +#include +#endif diff --git a/components/newlib/platform_include/sys/fcntl.h b/components/newlib/platform_include/sys/fcntl.h new file mode 100644 index 0000000000..93c9cb458c --- /dev/null +++ b/components/newlib/platform_include/sys/fcntl.h @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" + +#include_next + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +#include +#include +#endif diff --git a/components/newlib/platform_include/sys/time.h b/components/newlib/platform_include/sys/time.h index 7901acca33..88ca7867aa 100644 --- a/components/newlib/platform_include/sys/time.h +++ b/components/newlib/platform_include/sys/time.h @@ -1,9 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once + +#include "sdkconfig.h" + +#if CONFIG_LIBC_NEWLIB /* Newlib sys/time.h defines timerisset, timerclear, timercmp, timeradd, timersub macros for __CYGWIN__ and __rtems__. We want to define these macros in IDF as well. Since we wish to use un-modified newlib headers until a patched newlib version is @@ -20,3 +24,10 @@ #define __rtems__ #include_next #undef __rtems__ +#else // CONFIG_LIBC_NEWLIB +#include_next +#endif // CONFIG_LIBC_NEWLIB + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +#include +#endif diff --git a/components/newlib/platform_include/sys/unistd.h b/components/newlib/platform_include/sys/unistd.h index 483fd3cca8..d6b152f7b1 100644 --- a/components/newlib/platform_include/sys/unistd.h +++ b/components/newlib/platform_include/sys/unistd.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,11 @@ #pragma once #include +#include "sdkconfig.h" + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +#include +#endif #include_next diff --git a/components/newlib/project_include.cmake b/components/newlib/project_include.cmake index e365170283..193f166f2c 100644 --- a/components/newlib/project_include.cmake +++ b/components/newlib/project_include.cmake @@ -16,6 +16,8 @@ if(CONFIG_IDF_TOOLCHAIN_GCC) else() idf_toolchain_remove_flags(LINK_OPTIONS "--specs=nano.specs") endif() + + idf_toolchain_rerun_abi_detection() else() # TODO IDF-14338 if(CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND) idf_build_set_property(COMPILE_OPTIONS "-mdisable-hardware-atomics" APPEND) diff --git a/components/newlib/sbom.yml b/components/newlib/sbom.yml index 496cb10c30..6c88c6fa0c 100644 --- a/components/newlib/sbom.yml +++ b/components/newlib/sbom.yml @@ -1,9 +1,7 @@ -name: 'newlib' -version: '4.3.0' -cpe: cpe:2.3:a:newlib_project:newlib:{}:*:*:*:*:*:*:* +name: 'esp_libc' supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' -originator: 'Organization: Red Hat Incorporated' +originator: 'Organization: Espressif Systems (Shanghai) CO LTD' description: An open-source C standard library implementation with additional features and patches from Espressif. -cve-exclude-list: - - cve: CVE-2024-30949 - reason: A vulnerability was discovered in the gettimeofday system call implementation within the RISC-V libgloss component of Newlib. ESP-IDF does not link against libgloss for RISC-V, hence the issue is not directly applicable. Still, the relevant fix has been patched through https://github.com/espressif/newlib-esp32/commit/047ba47013c2656a1e7838dc86cbc75aeeaa67a7 +virtpackages: + - sbom_newlibc.yml + - sbom_picolibc.yml== diff --git a/components/newlib/sbom_newlibc.yml b/components/newlib/sbom_newlibc.yml new file mode 100644 index 0000000000..1a4e9db989 --- /dev/null +++ b/components/newlib/sbom_newlibc.yml @@ -0,0 +1,10 @@ +if: 'LIBC_NEWLIB' +name: 'newlib' +version: '4.3.0' +cpe: cpe:2.3:a:newlib_project:newlib:{}:*:*:*:*:*:*:* +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Organization: Red Hat Incorporated' +description: Newlib is a small C standard library for embedded systems +cve-exclude-list: + - cve: CVE-2024-30949 + reason: A vulnerability was discovered in the gettimeofday system call implementation within the RISC-V libgloss component of Newlib. ESP-IDF does not link against libgloss for RISC-V, hence the issue is not directly applicable. Still, the relevant fix has been patched through https://github.com/espressif/newlib-esp32/commit/047ba47013c2656a1e7838dc86cbc75aeeaa67a7 diff --git a/components/newlib/sbom_picolibc.yml b/components/newlib/sbom_picolibc.yml new file mode 100644 index 0000000000..4056cc4221 --- /dev/null +++ b/components/newlib/sbom_picolibc.yml @@ -0,0 +1,6 @@ +if: 'LIBC_PICOLIBC' +name: 'picolib' +version: '1.8.10' +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Organization: keithp.com/picolibc' +description: C Libraries for Smaller Embedded Systems diff --git a/components/newlib/src/locks.c b/components/newlib/src/locks.c index 582256dc3d..580f7b0e7e 100644 --- a/components/newlib/src/locks.c +++ b/components/newlib/src/locks.c @@ -17,9 +17,9 @@ #include "sdkconfig.h" #if CONFIG_LIBC_LOCKS_PLACE_IN_IRAM -#define NEWLIB_LOCKS_IRAM_ATTR IRAM_ATTR +#define LIBC_LOCKS_IRAM_ATTR IRAM_ATTR #else -#define NEWLIB_LOCKS_IRAM_ATTR +#define LIBC_LOCKS_IRAM_ATTR #endif /* Notes on our newlib lock implementation: @@ -50,7 +50,7 @@ static portMUX_TYPE lock_init_spinlock = portMUX_INITIALIZER_UNLOCKED; Called by _lock_init*, also called by _lock_acquire* to lazily initialize locks that might have been initialised (to zero only) before the RTOS scheduler started. */ -static void NEWLIB_LOCKS_IRAM_ATTR lock_init_generic(_lock_t *lock, uint8_t mutex_type) +static void LIBC_LOCKS_IRAM_ATTR lock_init_generic(_lock_t *lock, uint8_t mutex_type) { portENTER_CRITICAL(&lock_init_spinlock); if (*lock) { @@ -81,13 +81,13 @@ static void NEWLIB_LOCKS_IRAM_ATTR lock_init_generic(_lock_t *lock, uint8_t mute portEXIT_CRITICAL(&lock_init_spinlock); } -void NEWLIB_LOCKS_IRAM_ATTR _lock_init(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_init(_lock_t *lock) { *lock = 0; // In case lock's memory is uninitialized lock_init_generic(lock, queueQUEUE_TYPE_MUTEX); } -void NEWLIB_LOCKS_IRAM_ATTR _lock_init_recursive(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_init_recursive(_lock_t *lock) { *lock = 0; // In case lock's memory is uninitialized lock_init_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX); @@ -103,7 +103,7 @@ void NEWLIB_LOCKS_IRAM_ATTR _lock_init_recursive(_lock_t *lock) re-initialised if it is used again. Caller has to avoid doing this! */ -void NEWLIB_LOCKS_IRAM_ATTR _lock_close(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_close(_lock_t *lock) { portENTER_CRITICAL(&lock_init_spinlock); if (*lock) { @@ -122,7 +122,7 @@ void _lock_close_recursive(_lock_t *lock) __attribute__((alias("_lock_close"))); /* Acquire the mutex semaphore for lock. wait up to delay ticks. mutex_type is queueQUEUE_TYPE_RECURSIVE_MUTEX or queueQUEUE_TYPE_MUTEX */ -static int NEWLIB_LOCKS_IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_type) +static int LIBC_LOCKS_IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_type) { SemaphoreHandle_t h = (SemaphoreHandle_t)(*lock); if (!h) { @@ -164,22 +164,22 @@ static int NEWLIB_LOCKS_IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t d return (success == pdTRUE) ? 0 : -1; } -void NEWLIB_LOCKS_IRAM_ATTR _lock_acquire(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_acquire(_lock_t *lock) { lock_acquire_generic(lock, portMAX_DELAY, queueQUEUE_TYPE_MUTEX); } -void NEWLIB_LOCKS_IRAM_ATTR _lock_acquire_recursive(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_acquire_recursive(_lock_t *lock) { lock_acquire_generic(lock, portMAX_DELAY, queueQUEUE_TYPE_RECURSIVE_MUTEX); } -int NEWLIB_LOCKS_IRAM_ATTR _lock_try_acquire(_lock_t *lock) +int LIBC_LOCKS_IRAM_ATTR _lock_try_acquire(_lock_t *lock) { return lock_acquire_generic(lock, 0, queueQUEUE_TYPE_MUTEX); } -int NEWLIB_LOCKS_IRAM_ATTR _lock_try_acquire_recursive(_lock_t *lock) +int LIBC_LOCKS_IRAM_ATTR _lock_try_acquire_recursive(_lock_t *lock) { return lock_acquire_generic(lock, 0, queueQUEUE_TYPE_RECURSIVE_MUTEX); } @@ -187,7 +187,7 @@ int NEWLIB_LOCKS_IRAM_ATTR _lock_try_acquire_recursive(_lock_t *lock) /* Release the mutex semaphore for lock. mutex_type is queueQUEUE_TYPE_RECURSIVE_MUTEX or queueQUEUE_TYPE_MUTEX */ -static void NEWLIB_LOCKS_IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) +static void LIBC_LOCKS_IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) { if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { return; /* locking is a no-op before scheduler is up */ @@ -213,12 +213,12 @@ static void NEWLIB_LOCKS_IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t m } } -void NEWLIB_LOCKS_IRAM_ATTR _lock_release(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_release(_lock_t *lock) { lock_release_generic(lock, queueQUEUE_TYPE_MUTEX); } -void NEWLIB_LOCKS_IRAM_ATTR _lock_release_recursive(_lock_t *lock) +void LIBC_LOCKS_IRAM_ATTR _lock_release_recursive(_lock_t *lock) { lock_release_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX); } @@ -291,69 +291,69 @@ static StaticSemaphore_t s_common_recursive_mutex; #define MAYBE_OVERRIDE_LOCK(_lock, _lock_to_use_instead) #endif // ROM_NEEDS_MUTEX_OVERRIDE -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_init(_LOCK_T *lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_init(_LOCK_T *lock) { *lock = NULL; /* In case lock's memory is uninitialized */ lock_init_generic(lock, queueQUEUE_TYPE_MUTEX); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_init_recursive(_LOCK_T *lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_init_recursive(_LOCK_T *lock) { *lock = NULL; /* In case lock's memory is uninitialized */ lock_init_generic(lock, queueQUEUE_TYPE_RECURSIVE_MUTEX); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_close(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_close(_LOCK_T lock) { _lock_close(&lock); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_close_recursive(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_close_recursive(_LOCK_T lock) { _lock_close_recursive(&lock); } /* Separate function, to prevent generating multiple assert strings */ -static void NEWLIB_LOCKS_IRAM_ATTR check_lock_nonzero(_LOCK_T lock) +static void LIBC_LOCKS_IRAM_ATTR check_lock_nonzero(_LOCK_T lock) { assert(lock != NULL && "Uninitialized lock used"); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_acquire(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_acquire(_LOCK_T lock) { check_lock_nonzero(lock); MAYBE_OVERRIDE_LOCK(lock, &s_common_mutex); _lock_acquire(&lock); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_acquire_recursive(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_acquire_recursive(_LOCK_T lock) { check_lock_nonzero(lock); MAYBE_OVERRIDE_LOCK(lock, &s_common_recursive_mutex); _lock_acquire_recursive(&lock); } -int NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_try_acquire(_LOCK_T lock) +int LIBC_LOCKS_IRAM_ATTR __retarget_lock_try_acquire(_LOCK_T lock) { check_lock_nonzero(lock); MAYBE_OVERRIDE_LOCK(lock, &s_common_mutex); return _lock_try_acquire(&lock); } -int NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_try_acquire_recursive(_LOCK_T lock) +int LIBC_LOCKS_IRAM_ATTR __retarget_lock_try_acquire_recursive(_LOCK_T lock) { check_lock_nonzero(lock); MAYBE_OVERRIDE_LOCK(lock, &s_common_recursive_mutex); return _lock_try_acquire_recursive(&lock); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_release(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_release(_LOCK_T lock) { check_lock_nonzero(lock); _lock_release(&lock); } -void NEWLIB_LOCKS_IRAM_ATTR __retarget_lock_release_recursive(_LOCK_T lock) +void LIBC_LOCKS_IRAM_ATTR __retarget_lock_release_recursive(_LOCK_T lock) { check_lock_nonzero(lock); _lock_release_recursive(&lock); diff --git a/components/newlib/src/picolibc/errno.c b/components/newlib/src/picolibc/errno.c new file mode 100644 index 0000000000..67479c0ed7 --- /dev/null +++ b/components/newlib/src/picolibc/errno.c @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/* + * Picolibc does not initialize 'errno' and places it in the TBSS section. + * + * To allow convenient initialization and support interoperability with Newlib, + * 'errno' is defined in the TDATA section. The linker script ensures that + * it is positioned at the beginning of the TDATA segment. + */ +__thread int errno __attribute__((section(".tdata.errno"))) = 0; + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +int *__errno(void) +{ + return &errno; +} +#endif diff --git a/components/newlib/src/picolibc/getreent.c b/components/newlib/src/picolibc/getreent.c new file mode 100644 index 0000000000..b494d52ee5 --- /dev/null +++ b/components/newlib/src/picolibc/getreent.c @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_cpu.h" + +void *__getreent(void) +{ + /* + * The linker script provides the basic _reent fields + * used to access errno and stdin/stdout/stderr. + * + * Note: if code accesses other fields in struct _reent + * that are not intended to be "public," data corruption may occur. + */ + return esp_cpu_get_threadptr(); +} diff --git a/components/newlib/src/picolibc/picolibc_init.c b/components/newlib/src/picolibc/picolibc_init.c index 2e0fc30f14..7bd52667cb 100644 --- a/components/newlib/src/picolibc/picolibc_init.c +++ b/components/newlib/src/picolibc/picolibc_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,17 +33,8 @@ static void esp_cleanup_r(struct _reent *rptr) #endif #if ESP_ROM_HAS_RETARGETABLE_LOCKING -static int __retarget_lock_try_acquire(struct __lock * p) -{ - __retarget_lock_acquire(p); - return 0; -} - -static int __retarget_lock_try_acquire_recursive(struct __lock *p) -{ - __retarget_lock_acquire_recursive(p); - return 0; -} +int __retarget_lock_try_acquire(struct __lock * p); +int __retarget_lock_try_acquire_recursive(struct __lock *p); #endif static struct syscall_stub_table s_stub_table = { @@ -143,20 +134,10 @@ void esp_reent_cleanup(void) return; } -#if CONFIG_VFS_SUPPORT_IO -FILE *stdin; -FILE *stdout; -FILE *stderr; -void esp_libc_init_global_stdio(const char *stdio_dev) -{ - stdin = fopen(stdio_dev, "r"); - stdout = fopen(stdio_dev, "w"); - assert(stdin); - assert(stdout); - setlinebuf(stdout); - stderr = stdout; -} -#else /* CONFIG_VFS_SUPPORT_IO */ +/* + * Initialize stdin, stdout, and stderr using static memory allocation. + * Creating them with fopen() would call malloc() internally. + */ static char write_buf[BUFSIZ]; static char read_buf[BUFSIZ]; @@ -166,10 +147,28 @@ static struct __file_bufio __stdout = FDEV_SETUP_BUFIO(1, write_buf, BUFSIZ, rea FILE *stdin = &__stdin.xfile.cfile.file; FILE *stdout = &__stdout.xfile.cfile.file; FILE *stderr = &__stdout.xfile.cfile.file; + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY +__thread FILE* tls_stdin = &__stdin.xfile.cfile.file; +__thread FILE* tls_stdout = &__stdout.xfile.cfile.file; +__thread FILE* tls_stderr = &__stdout.xfile.cfile.file; +#endif + +#if CONFIG_VFS_SUPPORT_IO +void esp_libc_init_global_stdio(const char *stdio_dev) +{ + int stdin_fd = open(stdio_dev, O_RDONLY); + assert(stdin_fd > 0); + __stdin.ptr = (void *)(intptr_t)(stdin_fd); + + int stdout_fd = open(stdio_dev, O_WRONLY); + assert(stdout_fd > 0); + __stdout.ptr = (void *)(intptr_t)(stdout_fd); +} +#else /* CONFIG_VFS_SUPPORT_IO */ void esp_libc_init_global_stdio(void) { - __lock_init_recursive(stdin->lock); - __lock_init_recursive(stdout->lock); + /* Nothing to do. */ } #endif /* CONFIG_VFS_SUPPORT_IO */ diff --git a/components/newlib/src/syscalls.c b/components/newlib/src/syscalls.c index 0a15125fc3..d9dbe9e85a 100644 --- a/components/newlib/src/syscalls.c +++ b/components/newlib/src/syscalls.c @@ -105,6 +105,10 @@ int fcntl(int fd, int cmd, ...) return _fcntl_r(__getreent(), fd, cmd, arg); } +int getpid() +{ + return _getpid_r(__getreent()); +} #endif // CONFIG_LIBC_PICOLIBC void _exit(int __status) diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index af3dff5fc2..7cbc43e99e 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -131,6 +131,18 @@ FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(u #endif } +FORCE_INLINE_ATTR void rv_utils_set_threadptr(void *ptr) +{ + asm volatile("mv tp, %0" :: "r"(ptr)); +} + +FORCE_INLINE_ATTR void *rv_utils_get_threadptr(void) +{ + void *thread_ptr; + asm volatile("mv %0, tp" : "=r"(thread_ptr)); + return thread_ptr; +} + /* ------------------------------------------------- CPU Interrupts ---------------------------------------------------- * * ------------------------------------------------------------------------------------------------------------------ */ diff --git a/components/sdmmc/include/sd_protocol_defs.h b/components/sdmmc/include/sd_protocol_defs.h index f943789dc8..ba0c32f8c5 100644 --- a/components/sdmmc/include/sd_protocol_defs.h +++ b/components/sdmmc/include/sd_protocol_defs.h @@ -25,6 +25,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32p4/register/hw_ver3/soc/pmu_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/pmu_struct.h index 676f27357a..abc5f66321 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/pmu_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/pmu_struct.h @@ -7,6 +7,7 @@ #include #include +#include #include "pmu_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/project_include.cmake b/components/soc/project_include.cmake index bbc288c281..ad2c6b6bc4 100644 --- a/components/soc/project_include.cmake +++ b/components/soc/project_include.cmake @@ -36,14 +36,15 @@ if(CONFIG_IDF_TOOLCHAIN_GCC) # Clean compile options that were added by previous configurations and may be outdated idf_toolchain_remove_flags(COMPILE_OPTIONS "-march=") - if(CONFIG_SOC_CPU_HAS_HWLOOP) - set(_march "${_march}_xesploop") - endif() + if(CONFIG_ESP32P4_SELECTS_REV_LESS_V3) + set(_march "${_march}_xesppie") + else() + if(CONFIG_SOC_CPU_HAS_HWLOOP) + set(_march "${_march}_xesploop") + endif() - if(CONFIG_SOC_CPU_HAS_PIE) - set(_march "${_march}_xespv") - if(CONFIG_ESP32P4_SELECTS_REV_LESS_V3) - set(_march "${_march}2p1") + if(CONFIG_SOC_CPU_HAS_PIE) + set(_march "${_march}_xespv") endif() endif() @@ -60,30 +61,8 @@ if(CONFIG_IDF_TOOLCHAIN_GCC) if(NOT CONFIG_SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE) idf_toolchain_add_flags(COMPILE_OPTIONS "-mtune=esp-base") endif() + idf_toolchain_rerun_abi_detection() else() message(FATAL_ERROR "Unknown Espressif architecture: ${CONFIG_IDF_TARGET_ARCH}") endif() - - # Workaround: Re-run CMake compiler ABI detection after ABI flags are set. - # - # Problem: CMake performs compiler checks at an early stage during - # toolchain.cmake processing. At this early stage, response files are not yet - # ready, which causes CMake paths (e.g., CMAKE__IMPLICIT_LINK_DIRECTORIES) - # to be incorrectly determined. - # - # Solution: Re-run the ABI detection after ABI flags are present to correctly - # determine these paths. - # - # Note: If the CMake API changes, this solution may need to be revised. - set(lang_ext_pairs "C|c" "CXX|cpp") - include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) - foreach(lang_ext ${lang_ext_pairs}) - string(REPLACE "|" ";" lang_ext_parts ${lang_ext}) - list(GET lang_ext_parts 0 lang) - list(GET lang_ext_parts 1 ext) - if(DEFINED CMAKE_${lang}_ABI_COMPILED) - unset(CMAKE_${lang}_ABI_COMPILED) - cmake_determine_compiler_abi(${lang} ${CMAKE_ROOT}/Modules/CMake${lang}CompilerABI.${ext}) - endif() - endforeach() endif() diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index c8399d5cfe..a4cfc2b37d 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "esp_tls.h" #include "esp_log.h" diff --git a/components/ulp/esp32ulp_mapgen.py b/components/ulp/esp32ulp_mapgen.py index 972d8fd3e2..f841c436e9 100755 --- a/components/ulp/esp32ulp_mapgen.py +++ b/components/ulp/esp32ulp_mapgen.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # # esp32ulp_mapgen utility converts a symbol list provided by nm into an export script @@ -16,50 +16,61 @@ UTIL = os.path.basename(__file__) def name_mangling(name: str) -> str: # Simple and dumb name mangling for namespaced name following GCC algorithm ns, n = name.split('::') - return '_ZN{0}{1}{2}{3}E'.format(len(ns), ns, len(n), n) + return f'_ZN{len(ns)}{ns}{len(n)}{n}E' -def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int, prefix: str) -> None: - f_ld.write(textwrap.dedent( - f""" +def gen_ld_h_from_sym( + f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.TextIO, base_addr: int, prefix: str +) -> None: + f_ld.write( + textwrap.dedent( + f""" /* ULP variable definitions for the linker. * This file is generated automatically by {UTIL} utility. */ """ # noqa: E222 - )) + ) + ) cpp_mode = False var_prefix = prefix namespace = '' if '::' in prefix: # C++ mode, let's avoid the extern "C" type and instead use namespace - f_h.write(textwrap.dedent( - f""" + f_h.write( + textwrap.dedent( + f""" /* ULP variable definitions for the compiler. * This file is generated automatically by {UTIL} utility. */ #pragma once """ # noqa: E222 - )) + ) + ) tmp = prefix.split('::') namespace = tmp[0] var_prefix = '_'.join(tmp[1:]) # Limit to a single namespace here to avoid complex mangling rules f_h.write(f'namespace {namespace} {{\n') cpp_mode = True else: - f_h.write(textwrap.dedent( - f""" + f_h.write( + textwrap.dedent( + f""" /* ULP variable definitions for the compiler. * This file is generated automatically by {UTIL} utility. */ #pragma once + #include #ifdef __cplusplus extern "C" {{ #endif\n """ # noqa: E222 - )) + ) + ) # Format the regular expression to match the readelf output - expr = re.compile(r'^.*(?P
[a-f0-9]{8})\s+(?P\d+) (OBJECT|NOTYPE)\s+GLOBAL\s+DEFAULT\s+[^ ]+ (?P.*)$') + expr = re.compile( + r'^.*(?P
[a-f0-9]{8})\s+(?P\d+) (OBJECT|NOTYPE)\s+GLOBAL\s+DEFAULT\s+[^ ]+ (?P.*)$' + ) for line in f_sym: # readelf format output has the following structure: # Num: Value Size Type Bind Vis Ndx Name @@ -90,23 +101,31 @@ def gen_ld_h_from_sym(f_sym: typing.TextIO, f_ld: typing.TextIO, f_h: typing.Tex if cpp_mode: f_h.write('}\n') else: - f_h.write(textwrap.dedent( - """ + f_h.write( + textwrap.dedent( + """ #ifdef __cplusplus } #endif """ - )) + ) + ) def main() -> None: - description = ('This application generates .h and .ld files for symbols defined in input file. ' - 'The input symbols file can be generated using readelf utility like this: ' - 'readelf -sW > ') + description = ( + 'This application generates .h and .ld files for symbols defined in input file. ' + 'The input symbols file can be generated using readelf utility like this: ' + 'readelf -sW > ' + ) parser = argparse.ArgumentParser(description=description) - parser.add_argument('-s', '--symfile', required=True, help='symbols file name', metavar='SYMFILE', type=argparse.FileType('r')) - parser.add_argument('-o', '--outputfile', required=True, help='destination .h and .ld files name prefix', metavar='OUTFILE') + parser.add_argument( + '-s', '--symfile', required=True, help='symbols file name', metavar='SYMFILE', type=argparse.FileType('r') + ) + parser.add_argument( + '-o', '--outputfile', required=True, help='destination .h and .ld files name prefix', metavar='OUTFILE' + ) parser.add_argument('--base-addr', required=True, help='base address of the ULP memory, to be added to each symbol') parser.add_argument('-p', '--prefix', required=False, help='prefix for generated header file', default='ulp_') diff --git a/components/vfs/test_apps/main/test_vfs_fd.c b/components/vfs/test_apps/main/test_vfs_fd.c index 94814539cd..353701cdca 100644 --- a/components/vfs/test_apps/main/test_vfs_fd.c +++ b/components/vfs/test_apps/main/test_vfs_fd.c @@ -7,6 +7,7 @@ #include "sdkconfig.h" #include #include +#include #include #include #include diff --git a/components/vfs/test_apps/main/test_vfs_lwip.c b/components/vfs/test_apps/main/test_vfs_lwip.c index e9cf3870ab..d496648d83 100644 --- a/components/vfs/test_apps/main/test_vfs_lwip.c +++ b/components/vfs/test_apps/main/test_vfs_lwip.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "unity.h" #include "test_utils.h" diff --git a/components/vfs/test_apps/main/test_vfs_select.c b/components/vfs/test_apps/main/test_vfs_select.c index 80f7720cca..538c5e3817 100644 --- a/components/vfs/test_apps/main/test_vfs_select.c +++ b/components/vfs/test_apps/main/test_vfs_select.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "unity.h" #include "freertos/FreeRTOS.h" #include "driver/uart.h" diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index bcd5efa3d5..1a0518f3cf 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" diff --git a/components/xtensa/include/xt_utils.h b/components/xtensa/include/xt_utils.h index d4678002d9..afe5cb135b 100644 --- a/components/xtensa/include/xt_utils.h +++ b/components/xtensa/include/xt_utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -82,6 +82,18 @@ FORCE_INLINE_ATTR void xt_utils_wait_for_intr(void) asm volatile ("waiti 0\n"); } +FORCE_INLINE_ATTR void xt_utils_set_threadptr(void *ptr) +{ + asm volatile ("wur.threadptr %0" :: "r"(ptr)); +} + +FORCE_INLINE_ATTR void *xt_utils_get_threadptr(void) +{ + void *thread_ptr; + asm volatile ("rur.threadptr %0" : "=r"(thread_ptr)); + return thread_ptr; +} + /* ------------------------------------------------- CPU Interrupts ---------------------------------------------------- * * ------------------------------------------------------------------------------------------------------------------ */ diff --git a/docs/en/api-guides/stdio.rst b/docs/en/api-guides/stdio.rst index f0b10cfaed..ccb1598dc9 100644 --- a/docs/en/api-guides/stdio.rst +++ b/docs/en/api-guides/stdio.rst @@ -58,13 +58,26 @@ Enabling one of these option will cause the corresponding VFS driver to be built Standard Streams and FreeRTOS Tasks ----------------------------------- +ESP-IDF provides two different implementations of standard I/O streams based on the selected LibC implementation defined by :ref:`CONFIG_LIBC`. The behavior of ``stdin``, ``stdout``, and ``stderr`` streams differs between these implementations, particularly regarding how they are shared across FreeRTOS tasks. + +Common to both implementations, each stream (``stdin``, ``stdout``, ``stderr``) has a mutex associated with it to protect the stream from concurrent access by multiple tasks. For example, if two tasks are writing to ``stdout`` at the same time, the mutex ensures that the outputs from each task are not mixed together. + +Newlib +^^^^^^ + In ESP-IDF, to save RAM, ``FILE`` objects for ``stdin``, ``stdout``, and ``stderr`` are shared between all FreeRTOS tasks, but the pointers to these objects are unique for every task. This means that: - It is possible to change ``stdin``, ``stdout``, and ``stderr`` for any given task without affecting other tasks, e.g., by doing ``stdin = fopen("/dev/uart/1", "r")``. - To change the default ``stdin``, ``stdout``, ``stderr`` streams for new tasks, modify ``_GLOBAL_REENT->_stdin`` (``_stdout``, ``_stderr``) before creating the task. - Closing default ``stdin``, ``stdout``, or ``stderr`` using ``fclose`` closes the ``FILE`` stream object, which will affect all other tasks. -Each stream (``stdin``, ``stdout``, ``stderr``) has a mutex associated with it. This mutex is used to protect the stream from concurrent access by multiple tasks. For example, if two tasks are writing to ``stdout`` at the same time, the mutex will ensure that the outputs from each task are not mixed together. +Picolibc +^^^^^^^^ + +According to the POSIX standard, all default ``stdin``, ``stdout``, and ``stderr`` streams are global and shared between all FreeRTOS tasks. This means that: + +- Modifying ``stdin``, ``stdout``, or ``stderr`` will affect all other tasks. It is not possible to change standard I/O streams for specific tasks. +- If a thread-local stream is needed, it should be implemented in the application code by opening a file stream and using it within tasks, e.g., ``fscanf()``, ``fprintf()``, etc. Blocking and non-blocking I/O ----------------------------- diff --git a/examples/network/simple_sniffer/main/cmd_sniffer.c b/examples/network/simple_sniffer/main/cmd_sniffer.c index aae307df62..64367a750c 100644 --- a/examples/network/simple_sniffer/main/cmd_sniffer.c +++ b/examples/network/simple_sniffer/main/cmd_sniffer.c @@ -7,6 +7,7 @@ */ #include #include +#include #include "argtable3/argtable3.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" diff --git a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c index fbcd3f1658..f0673c1949 100644 --- a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "esp_err.h" #include "esp_event.h" #include "esp_log.h" diff --git a/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c b/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c index abc01a900a..4e872f5e21 100644 --- a/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c +++ b/examples/storage/fatfs/fatfsgen/main/fatfsgen_example_main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "esp_vfs.h" #include "esp_vfs_fat.h" #include "esp_err.h" diff --git a/tools/cmake/toolchain_flags.cmake b/tools/cmake/toolchain_flags.cmake index 682e4e2602..cd273040fd 100644 --- a/tools/cmake/toolchain_flags.cmake +++ b/tools/cmake/toolchain_flags.cmake @@ -155,3 +155,28 @@ endfunction() function(idf_toolchain_remove_flags) _process_toolchain_flag_options() endfunction() + +# Workaround: Re-run CMake compiler ABI detection after ABI flags are set. +# +# Problem: CMake performs compiler checks at an early stage during +# toolchain.cmake processing. At this early stage, response files are not yet +# ready, which causes CMake paths (e.g., CMAKE__IMPLICIT_LINK_DIRECTORIES) +# to be incorrectly determined. +# +# Solution: Re-run the ABI detection after ABI flags are present to correctly +# determine these paths. +# +# Note: If the CMake API changes, this solution may need to be revised. +macro(idf_toolchain_rerun_abi_detection) + set(lang_ext_pairs "C|c" "CXX|cpp") + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) + foreach(lang_ext ${lang_ext_pairs}) + string(REPLACE "|" ";" lang_ext_parts ${lang_ext}) + list(GET lang_ext_parts 0 lang) + list(GET lang_ext_parts 1 ext) + if(DEFINED CMAKE_${lang}_ABI_COMPILED) + unset(CMAKE_${lang}_ABI_COMPILED) + cmake_determine_compiler_abi(${lang} ${CMAKE_ROOT}/Modules/CMake${lang}CompilerABI.${ext}) + endif() + endforeach() +endmacro() diff --git a/tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c b/tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c index dbbc75263e..2372c22f30 100644 --- a/tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c +++ b/tools/test_apps/storage/fatfsgen/main/fatfsgen_example_main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "esp_vfs.h" #include "esp_vfs_fat.h" #include "sdkconfig.h"