diff --git a/Kconfig b/Kconfig index 79415b4457..55d73d2a7c 100644 --- a/Kconfig +++ b/Kconfig @@ -230,7 +230,7 @@ mainmenu "Espressif IoT Development Framework Configuration" CONFIG_APP_BUILD_TYPE_RAM=y CONFIG_VFS_SUPPORT_TERMIOS= - CONFIG_NEWLIB_NANO_FORMAT=y + CONFIG_LIBC_NEWLIB_NANO_FORMAT=y CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y CONFIG_ESP_DEBUG_STUBS_ENABLE= CONFIG_ESP_ERR_TO_NAME_LOOKUP= diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index c1fb9041d9..aa575b9256 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -344,7 +344,7 @@ else() # Regular app build endif() endif() - if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT AND CONFIG_LIBC_NEWLIB AND CONFIG_NEWLIB_NANO_FORMAT) + if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT AND CONFIG_LIBC_NEWLIB AND CONFIG_LIBC_NEWLIB_NANO_FORMAT) if(NOT CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME AND NOT CONFIG_ESP_ROM_HAS_NEWLIB_NANO_PRINTF_FLOAT_BUG) # Newlib-nano functions contains time_t related functions # and cannot be used if they were compiled with 32 bit time_t @@ -352,7 +352,7 @@ else() # Regular app build endif() endif() - if(CONFIG_ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT AND CONFIG_LIBC_NEWLIB AND NOT CONFIG_NEWLIB_NANO_FORMAT) + if(CONFIG_ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT AND CONFIG_LIBC_NEWLIB AND NOT CONFIG_LIBC_NEWLIB_NANO_FORMAT) rom_linker_script("newlib-normal") endif() endif() diff --git a/components/esp_rom/patches/esp_rom_longjmp.S b/components/esp_rom/patches/esp_rom_longjmp.S index d76ac4f7e6..3c1ccce913 100644 --- a/components/esp_rom/patches/esp_rom_longjmp.S +++ b/components/esp_rom/patches/esp_rom_longjmp.S @@ -33,10 +33,13 @@ /* void longjmp (jmp_buf env, int val) */ - .align 4 .literal_position +#if CONFIG_SPIRAM_CACHE_LIBJMP_IN_IRAM + .section .iram1,"ax" +#endif .global __wrap_longjmp .type __wrap_longjmp, @function + .align 4 __wrap_longjmp: entry sp, 16 @@ -63,7 +66,7 @@ __wrap_longjmp: /* If not on S3, replacement of only the first instructions, then jump back to original longjmp implementation. - The jump target is the instrucion + The jump target is the instruction l32i a0, a2, 64 of the original code. Hence, the original code's entry instruction and windowstart modification are left out. diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index 3d4769ca67..1bb182f584 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -74,6 +74,7 @@ list(APPEND ldfragments "src/newlib.lf" "src/system_libs.lf") if(CONFIG_LIBC_NEWLIB) list(APPEND ldfragments src/libc.lf) + list(APPEND ldfragments src/libm.lf) else() list(APPEND ldfragments src/picolibc/libc.lf) endif() @@ -107,7 +108,7 @@ list(APPEND EXTRA_LINK_FLAGS "-u esp_libc_include_init_funcs") list(APPEND EXTRA_LINK_FLAGS "-u esp_libc_init_funcs") target_link_libraries(${COMPONENT_LIB} INTERFACE "${EXTRA_LINK_FLAGS}") -if(CONFIG_NEWLIB_NANO_FORMAT) +if(CONFIG_LIBC_NEWLIB_NANO_FORMAT) if(CMAKE_C_COMPILER_ID MATCHES "Clang") set(libc_dir_cmd ${CMAKE_C_COMPILER}) string(REPLACE " " ";" cflags_list ${CMAKE_C_FLAGS}) diff --git a/components/newlib/src/libc.lf b/components/newlib/src/libc.lf index 1f31f191c1..a8ebcf8930 100644 --- a/components/newlib/src/libc.lf +++ b/components/newlib/src/libc.lf @@ -6,7 +6,7 @@ [mapping:libc] archive: - if NEWLIB_NANO_FORMAT = y: + if LIBC_NEWLIB_NANO_FORMAT = y: libc_nano.a else: libc.a @@ -35,8 +35,8 @@ entries: libc_a-labs (noflash) libc_a-ldiv (noflash) libc_a-quorem (noflash) - libc_a-s_fpclassify (noflash) - libc_a-sf_nan (noflash) + libm_a-s_fpclassify (noflash) + libm_a-sf_nan (noflash) if SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM = y: libc_a-utoa (noflash) @@ -47,6 +47,7 @@ entries: if SPIRAM_CACHE_LIBIO_IN_IRAM = y: libc_a-wcrtomb (noflash) + libc_a-fwrite (noflash) libc_a-fvwrite (noflash) libc_a-wbuf (noflash) libc_a-wsetup (noflash) @@ -144,9 +145,9 @@ entries: libc_a-getenv_r (noflash) if SPIRAM_CACHE_LIBFILE_IN_IRAM = y: - lock (noflash) - isatty (noflash) - creat (noflash) + libc_a-lock (noflash) + libc_a-isatty (noflash) + libc_a-creat (noflash) libc_a-fclose (noflash) libc_a-open (noflash) libc_a-close (noflash) diff --git a/components/newlib/src/libm.lf b/components/newlib/src/libm.lf new file mode 100644 index 0000000000..32e2597ee7 --- /dev/null +++ b/components/newlib/src/libm.lf @@ -0,0 +1,10 @@ +[mapping:libm] +archive: + if LIBC_NEWLIB_NANO_FORMAT = y: + libm_nano.a + else: + libm.a +entries: + if SPIRAM_CACHE_LIBMATH_IN_IRAM = y: + libm_a-s_fpclassify (noflash) + libm_a-sf_nan (noflash) diff --git a/components/newlib/src/syscalls.c b/components/newlib/src/syscalls.c index ed5ee9f03a..23dfd834b4 100644 --- a/components/newlib/src/syscalls.c +++ b/components/newlib/src/syscalls.c @@ -11,6 +11,7 @@ #include #include #include +#include "esp_attr.h" #if CONFIG_IDF_TOOLCHAIN_GCC #include @@ -121,11 +122,17 @@ int fstat(int fd, struct stat *st) return _fstat_r(__getreent(), fd, st); } +#if CONFIG_SPIRAM_CACHE_LIBMISC_IN_IRAM +IRAM_ATTR +#endif int raise(int sig) { return _raise_r(__getreent(), sig); } +#if CONFIG_SPIRAM_CACHE_LIBMISC_IN_IRAM +IRAM_ATTR +#endif int system(const char* str) { return _system_r(__getreent(), str); diff --git a/components/newlib/test_apps/newlib/main/test_newlib.c b/components/newlib/test_apps/newlib/main/test_newlib.c index 65137cebe8..f8e3a8f468 100644 --- a/components/newlib/test_apps/newlib/main/test_newlib.c +++ b/components/newlib/test_apps/newlib/main/test_newlib.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 */ @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include "unity.h" #include "sdkconfig.h" #include "soc/soc.h" @@ -194,6 +197,112 @@ TEST_CASE("test 64bit int formats", "[newlib]") TEST_ASSERT_EQUAL(val, sval); } #else // CONFIG_NEWLIB_NANO_FORMAT + +#if CONFIG_SPIRAM_CACHE_WORKAROUND +static bool fn_in_iram(void *fn) +{ + const uintptr_t fnaddr = (int)fn; + return (fnaddr >= SOC_IRAM_LOW && fnaddr < SOC_IRAM_HIGH); +} + +TEST_CASE("Libc_nano in IRAM", "[newlib_nano]") +{ + TEST_ASSERT_TRUE(fn_in_iram(itoa)); + TEST_ASSERT_TRUE(fn_in_iram(memcmp)); + TEST_ASSERT_TRUE(fn_in_iram(memcpy)); + TEST_ASSERT_TRUE(fn_in_iram(memset)); + TEST_ASSERT_TRUE(fn_in_iram(strcat)); + TEST_ASSERT_TRUE(fn_in_iram(strcmp)); + TEST_ASSERT_TRUE(fn_in_iram(strlen)); + TEST_ASSERT_TRUE(fn_in_iram(longjmp)); + TEST_ASSERT_TRUE(fn_in_iram(abs)); + TEST_ASSERT_TRUE(fn_in_iram(div)); + TEST_ASSERT_TRUE(fn_in_iram(labs)); + TEST_ASSERT_TRUE(fn_in_iram(ldiv)); + TEST_ASSERT_TRUE(fn_in_iram(__fpclassifyd)); + TEST_ASSERT_TRUE(fn_in_iram(nanf)); + TEST_ASSERT_TRUE(fn_in_iram(utoa)); + TEST_ASSERT_TRUE(fn_in_iram(atoi)); + TEST_ASSERT_TRUE(fn_in_iram(atol)); + TEST_ASSERT_TRUE(fn_in_iram(strtol)); + TEST_ASSERT_TRUE(fn_in_iram(strtoul)); + TEST_ASSERT_TRUE(fn_in_iram(wcrtomb)); + TEST_ASSERT_TRUE(fn_in_iram(_fwrite_r)); + TEST_ASSERT_TRUE(fn_in_iram(__swbuf_r)); + TEST_ASSERT_TRUE(fn_in_iram(fputwc)); + TEST_ASSERT_TRUE(fn_in_iram(_wctomb_r)); + TEST_ASSERT_TRUE(fn_in_iram(ungetc)); + TEST_ASSERT_TRUE(fn_in_iram(fflush)); + TEST_ASSERT_TRUE(fn_in_iram(asctime)); + TEST_ASSERT_TRUE(fn_in_iram(asctime_r)); + TEST_ASSERT_TRUE(fn_in_iram(ctime)); + TEST_ASSERT_TRUE(fn_in_iram(ctime_r)); + TEST_ASSERT_TRUE(fn_in_iram(localtime)); + TEST_ASSERT_TRUE(fn_in_iram(gmtime)); + TEST_ASSERT_TRUE(fn_in_iram(gmtime_r)); + TEST_ASSERT_TRUE(fn_in_iram(strftime)); + TEST_ASSERT_TRUE(fn_in_iram(mktime)); + TEST_ASSERT_TRUE(fn_in_iram(_tzset_r)); + TEST_ASSERT_TRUE(fn_in_iram(time)); + TEST_ASSERT_TRUE(fn_in_iram(strptime)); + TEST_ASSERT_TRUE(fn_in_iram(toupper)); + TEST_ASSERT_TRUE(fn_in_iram(tolower)); + TEST_ASSERT_TRUE(fn_in_iram(toascii)); + TEST_ASSERT_TRUE(fn_in_iram(strupr)); + TEST_ASSERT_TRUE(fn_in_iram(bzero)); + TEST_ASSERT_TRUE(fn_in_iram(isalnum)); + TEST_ASSERT_TRUE(fn_in_iram(isalpha)); + TEST_ASSERT_TRUE(fn_in_iram(isascii)); + TEST_ASSERT_TRUE(fn_in_iram(isblank)); + TEST_ASSERT_TRUE(fn_in_iram(iscntrl)); + TEST_ASSERT_TRUE(fn_in_iram(isdigit)); + TEST_ASSERT_TRUE(fn_in_iram(isgraph)); + TEST_ASSERT_TRUE(fn_in_iram(islower)); + TEST_ASSERT_TRUE(fn_in_iram(isprint)); + TEST_ASSERT_TRUE(fn_in_iram(ispunct)); + TEST_ASSERT_TRUE(fn_in_iram(isspace)); + TEST_ASSERT_TRUE(fn_in_iram(isupper)); + TEST_ASSERT_TRUE(fn_in_iram(memccpy)); + TEST_ASSERT_TRUE(fn_in_iram(memchr)); + TEST_ASSERT_TRUE(fn_in_iram(memmove)); + TEST_ASSERT_TRUE(fn_in_iram(memrchr)); + TEST_ASSERT_TRUE(fn_in_iram(strcasecmp)); + TEST_ASSERT_TRUE(fn_in_iram(strcasestr)); + TEST_ASSERT_TRUE(fn_in_iram(strchr)); + TEST_ASSERT_TRUE(fn_in_iram(strcoll)); + TEST_ASSERT_TRUE(fn_in_iram(strcpy)); + TEST_ASSERT_TRUE(fn_in_iram(strcspn)); + TEST_ASSERT_TRUE(fn_in_iram(strdup)); + TEST_ASSERT_TRUE(fn_in_iram(_strdup_r)); + TEST_ASSERT_TRUE(fn_in_iram(strlcat)); + TEST_ASSERT_TRUE(fn_in_iram(strlcpy)); + TEST_ASSERT_TRUE(fn_in_iram(strlwr)); + TEST_ASSERT_TRUE(fn_in_iram(strncasecmp)); + TEST_ASSERT_TRUE(fn_in_iram(strncat)); + TEST_ASSERT_TRUE(fn_in_iram(strncmp)); + TEST_ASSERT_TRUE(fn_in_iram(strncpy)); + TEST_ASSERT_TRUE(fn_in_iram(strndup)); + TEST_ASSERT_TRUE(fn_in_iram(_strndup_r)); + TEST_ASSERT_TRUE(fn_in_iram(strnlen)); + TEST_ASSERT_TRUE(fn_in_iram(strrchr)); + TEST_ASSERT_TRUE(fn_in_iram(strsep)); + TEST_ASSERT_TRUE(fn_in_iram(strspn)); + TEST_ASSERT_TRUE(fn_in_iram(strstr)); + TEST_ASSERT_TRUE(fn_in_iram(strtok_r)); + TEST_ASSERT_TRUE(fn_in_iram(strupr)); + TEST_ASSERT_TRUE(fn_in_iram(srand)); + TEST_ASSERT_TRUE(fn_in_iram(rand)); + TEST_ASSERT_TRUE(fn_in_iram(rand_r)); + TEST_ASSERT_TRUE(fn_in_iram(_getenv_r)); + TEST_ASSERT_TRUE(fn_in_iram(isatty)); + TEST_ASSERT_TRUE(fn_in_iram(fclose)); + TEST_ASSERT_TRUE(fn_in_iram(creat)); + TEST_ASSERT_TRUE(fn_in_iram(_fwalk_sglue)); + TEST_ASSERT_TRUE(fn_in_iram(__sinit)); + TEST_ASSERT_TRUE(fn_in_iram(raise)); + TEST_ASSERT_TRUE(fn_in_iram(system)); +} +#endif // SPIRAM_CACHE_WORKAROUND TEST_CASE("test 64bit int formats", "[newlib]") { char* res = NULL; diff --git a/components/newlib/test_apps/newlib/sdkconfig.ci.nano_psram_esp32 b/components/newlib/test_apps/newlib/sdkconfig.ci.nano_psram_esp32 new file mode 100644 index 0000000000..7ee21fd72c --- /dev/null +++ b/components/newlib/test_apps/newlib/sdkconfig.ci.nano_psram_esp32 @@ -0,0 +1,16 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_LIBC_NEWLIB_NANO_FORMAT=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y +CONFIG_SPIRAM_CACHE_LIBJMP_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBMATH_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBIO_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBTIME_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBCHAR_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBMEM_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBSTR_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBRAND_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBENV_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBFILE_IN_IRAM=y +CONFIG_SPIRAM_CACHE_LIBMISC_IN_IRAM=y diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 3b5b0eeedc..7973872efa 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -445,6 +445,7 @@ components/esp_rom/include/esp_rom_crc.h components/esp_rom/linux/esp_rom_crc.c components/esp_rom/linux/esp_rom_md5.c components/esp_rom/patches/esp_rom_crc.c +components/esp_rom/patches/esp_rom_longjmp.S components/esp_system/ubsan.c components/esp_wifi/src/mesh_event.c components/fatfs/diskio/diskio.c diff --git a/tools/ci/check_ldgen_mapping_exceptions.txt b/tools/ci/check_ldgen_mapping_exceptions.txt index 6bd2d5330f..5637afad87 100644 --- a/tools/ci/check_ldgen_mapping_exceptions.txt +++ b/tools/ci/check_ldgen_mapping_exceptions.txt @@ -1,4 +1,5 @@ libc +libm sha256_coredump gcc clang_rt_builtins