From 249ef34699c2423d038b01f5c2b17aeb06b9c498 Mon Sep 17 00:00:00 2001 From: William Tambe Date: Wed, 23 Apr 2025 10:32:35 -0800 Subject: [PATCH 1/2] xtensa: support for C library provided by Xtensa toolchain This change add an additional C library implementation provided by Xtensa toolchain. Signed-off-by: William Tambe --- arch/xtensa/core/thread.c | 7 +++ boards/cdns/xt-sim/xt-sim_defconfig | 2 + cmake/linker/xt-ld/linker_libraries.cmake | 8 ++- include/zephyr/arch/xtensa/thread.h | 7 +++ lib/libc/CMakeLists.txt | 1 + lib/libc/Kconfig | 7 +++ lib/libc/xclib/CMakeLists.txt | 8 +++ lib/libc/xclib/libc-hooks.c | 15 +++++ lib/libc/xclib/multithreading.c | 67 +++++++++++++++++++++++ 9 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 lib/libc/xclib/CMakeLists.txt create mode 100644 lib/libc/xclib/libc-hooks.c create mode 100644 lib/libc/xclib/multithreading.c diff --git a/arch/xtensa/core/thread.c b/arch/xtensa/core/thread.c index 2bf1a7e11d37..31c99c4ab52f 100644 --- a/arch/xtensa/core/thread.c +++ b/arch/xtensa/core/thread.c @@ -27,6 +27,10 @@ Z_THREAD_LOCAL uint32_t is_user_mode; #endif /* CONFIG_USERSPACE */ +#if defined(CONFIG_XTENSA_LIBC) +#include +#endif + /** * Initializes a stack area such that it can be "restored" later and * begin running with the specified function and three arguments. The @@ -125,6 +129,9 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, __ASSERT((((size_t)stack_ptr) % XCHAL_DCACHE_LINESIZE) == 0, ""); sys_cache_data_flush_and_invd_range(stack, (char *)stack_ptr - (char *)stack); #endif +#if defined(CONFIG_XTENSA_LIBC) + _init_reent(&thread->arch.reent); +#endif } #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) diff --git a/boards/cdns/xt-sim/xt-sim_defconfig b/boards/cdns/xt-sim/xt-sim_defconfig index 9a055db716ff..b6c307baa8f2 100644 --- a/boards/cdns/xt-sim/xt-sim_defconfig +++ b/boards/cdns/xt-sim/xt-sim_defconfig @@ -8,3 +8,5 @@ CONFIG_GEN_IRQ_VECTOR_TABLE=n CONFIG_SIMULATOR_XTENSA=y CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=2000000 + +CONFIG_XTENSA_LIBC=y diff --git a/cmake/linker/xt-ld/linker_libraries.cmake b/cmake/linker/xt-ld/linker_libraries.cmake index f4fedfc4f0d4..bffdeb4a73de 100644 --- a/cmake/linker/xt-ld/linker_libraries.cmake +++ b/cmake/linker/xt-ld/linker_libraries.cmake @@ -6,4 +6,10 @@ set_linker_property(NO_CREATE PROPERTY c_library "-lc") set_linker_property(NO_CREATE PROPERTY rt_library "-lgcc") set_linker_property(NO_CREATE PROPERTY c++_library "-lstdc++") set_linker_property(NO_CREATE PROPERTY hal_library "-lhal") -set_linker_property(PROPERTY link_order_library "c;rt;hal") +if(CONFIG_XTENSA_LIBC) + set_linker_property(NO_CREATE PROPERTY m_library "-lm") + set_linker_property(NO_CREATE PROPERTY sim_library "-lsim") + set_linker_property(PROPERTY link_order_library "m;c;rt;sim;hal") +else() + set_linker_property(PROPERTY link_order_library "c;rt;hal") +endif() diff --git a/include/zephyr/arch/xtensa/thread.h b/include/zephyr/arch/xtensa/thread.h index 0b5112fb6d94..3ffa4df3d3d2 100644 --- a/include/zephyr/arch/xtensa/thread.h +++ b/include/zephyr/arch/xtensa/thread.h @@ -14,6 +14,10 @@ #include #endif +#ifdef CONFIG_XTENSA_LIBC +#include +#endif + /* Xtensa doesn't use these structs, but Zephyr core requires they be * defined so they can be included in struct _thread_base. Dummy * field exists for sizeof compatibility with C++. @@ -48,6 +52,9 @@ struct _thread_arch { */ uint32_t return_ps; #endif +#ifdef CONFIG_XTENSA_LIBC + struct _reent reent; +#endif }; typedef struct _thread_arch _thread_arch_t; diff --git a/lib/libc/CMakeLists.txt b/lib/libc/CMakeLists.txt index 075e066d59b4..1ef8084fa027 100644 --- a/lib/libc/CMakeLists.txt +++ b/lib/libc/CMakeLists.txt @@ -10,5 +10,6 @@ add_subdirectory_ifdef(CONFIG_IAR_LIBC iar) add_subdirectory_ifdef(CONFIG_MINIMAL_LIBC minimal) add_subdirectory_ifdef(CONFIG_NEWLIB_LIBC newlib) add_subdirectory_ifdef(CONFIG_PICOLIBC picolibc) +add_subdirectory_ifdef(CONFIG_XTENSA_LIBC xclib) add_subdirectory(common) diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 5d981e4719b0..e87baee23e84 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -143,6 +143,13 @@ config IAR_LIBC A reduced Zephyr minimal libc will be used for library functionality not provided by the IAR C Runtime Library. +config XTENSA_LIBC + bool "Xtensa C library" + depends on !NATIVE_APPLICATION + depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "xt-clang" + help + C library provided by Xtensa toolchain. + endchoice # LIBC_IMPLEMENTATION config HAS_NEWLIB_LIBC_NANO diff --git a/lib/libc/xclib/CMakeLists.txt b/lib/libc/xclib/CMakeLists.txt new file mode 100644 index 000000000000..1ae7c25db2d2 --- /dev/null +++ b/lib/libc/xclib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + libc-hooks.c + multithreading.c +) diff --git a/lib/libc/xclib/libc-hooks.c b/lib/libc/xclib/libc-hooks.c new file mode 100644 index 000000000000..72c479f252d5 --- /dev/null +++ b/lib/libc/xclib/libc-hooks.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 Cadence Design Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +char __os_flag __attribute__((retain)); /* Needed by xclib to indicate the presense of an OS */ + +int arch_printk_char_out(int c); +static int (*_stdout_hook)(int c) = arch_printk_char_out; + +void __stdout_hook_install(int (*hook)(int)) +{ + _stdout_hook = hook; +} diff --git a/lib/libc/xclib/multithreading.c b/lib/libc/xclib/multithreading.c new file mode 100644 index 000000000000..d8ac80a4d1c8 --- /dev/null +++ b/lib/libc/xclib/multithreading.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Cadence Design Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +int32_t _xclib_use_mt = 1; /* Enables xclib multithread support */ + +typedef struct k_mutex *_Rmtx; + +/* Number of Locks needed by _Initlocks() without calling malloc() + * which would infinitely call _Initlocks() recursively. + */ +#define NLOCKS (_MAX_LOCK + 1) + +static struct k_mutex _Mtxinit_mtx[NLOCKS]; + +void _Mtxinit(_Rmtx *mtx) +{ + static int i; /* static variable initially 0 */ + + if (i < NLOCKS) { + *mtx = &_Mtxinit_mtx[i]; + ++i; + } else { + *mtx = malloc(sizeof(struct k_mutex)); + } + if (!*mtx) { + k_panic(); + } + k_mutex_init(*mtx); +} + +void _Mtxdst(_Rmtx *mtx) +{ + if (mtx != NULL && *mtx != NULL && + (*mtx > &_Mtxinit_mtx[NLOCKS] || *mtx < &_Mtxinit_mtx[0])) { + free(*mtx); + } +} + +void _Mtxlock(_Rmtx *mtx) +{ + if ((mtx != NULL) && (*mtx != NULL)) { + k_mutex_lock(*mtx, K_FOREVER); + } +} + +void _Mtxunlock(_Rmtx *mtx) +{ + if ((mtx != NULL) && (*mtx != NULL)) { + k_mutex_unlock(*mtx); + } +} + +#if defined(__DYNAMIC_REENT__) +struct _reent *__getreent(void) +{ + return &k_current_get()->arch.reent; +} +#else +#error __DYNAMIC_REENT__ support missing +#endif From 295c7eb9c97fa563de34829cf24e2d36c1a8841a Mon Sep 17 00:00:00 2001 From: William Tambe Date: Fri, 2 May 2025 09:07:47 -0800 Subject: [PATCH 2/2] xtensa: support for C++ library using Xtensa toolchain Changes needed to build C++ code using Xtensa toolchain. Signed-off-by: William Tambe --- cmake/compiler/xt-clang/compiler_flags.cmake | 2 +- cmake/linker/xt-ld/linker_flags.cmake | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/compiler/xt-clang/compiler_flags.cmake b/cmake/compiler/xt-clang/compiler_flags.cmake index c70832ebc0f9..77ccd51be9bb 100644 --- a/cmake/compiler/xt-clang/compiler_flags.cmake +++ b/cmake/compiler/xt-clang/compiler_flags.cmake @@ -11,7 +11,7 @@ set_compiler_property(PROPERTY nostdinc_include) # For C++ code, re-add the standard includes directory which was # cleared up from nostdinc_inlcude in above lines with no # "include-fixed" this time" -if(CONFIG_CPP) +if(CONFIG_CPP AND NOT CONFIG_XTENSA_LIBC) execute_process( COMMAND ${CMAKE_C_COMPILER} --print-file-name=include/stddef.h OUTPUT_VARIABLE _OUTPUT diff --git a/cmake/linker/xt-ld/linker_flags.cmake b/cmake/linker/xt-ld/linker_flags.cmake index ab66461e4522..996002afc69f 100644 --- a/cmake/linker/xt-ld/linker_flags.cmake +++ b/cmake/linker/xt-ld/linker_flags.cmake @@ -8,7 +8,11 @@ check_set_linker_property(TARGET linker PROPERTY base ) if(NOT CONFIG_NATIVE_LIBRARY AND NOT CONFIG_EXTERNAL_MODULE_LIBCPP) - set_property(TARGET linker PROPERTY cpp_base -lstdc++) + if (CONFIG_XTENSA_LIBC) + set_property(TARGET linker PROPERTY cpp_base -lstdc++11) + else() + set_property(TARGET linker PROPERTY cpp_base -lstdc++) + endif() endif() check_set_linker_property(TARGET linker PROPERTY baremetal