diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 4f92cd07c568c6..0141bfde6490e0 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -25,6 +25,8 @@ source "$(BOARD_DIR)/Kconfig.defconfig" osource "$(KCONFIG_BINARY_DIR)/Kconfig.soc.defconfig" # This loads Zephyr base SoC root defconfigs osource "soc/$(ARCH)/*/Kconfig.defconfig" +# This loads the toolchain defconfigs +osource "$(TOOLCHAIN_KCONFIG_DIR)/Kconfig.defconfig" menu "Modules" diff --git a/cmake/compiler/armclang/compiler_flags.cmake b/cmake/compiler/armclang/compiler_flags.cmake index 48c0e0c798c5ad..3d0f713da4f40a 100644 --- a/cmake/compiler/armclang/compiler_flags.cmake +++ b/cmake/compiler/armclang/compiler_flags.cmake @@ -4,3 +4,6 @@ include(${ZEPHYR_BASE}/cmake/compiler/clang/compiler_flags.cmake) # Required ASM flags when using armclang, this should be handled by CMake, but # fails because of: https://gitlab.kitware.com/cmake/cmake/-/issues/19963 set_property(TARGET asm APPEND PROPERTY required "--target=${triple}") + +# Only the ARM Compiler C library is currently supported. +set_compiler_property(PROPERTY nostdinc) diff --git a/cmake/compiler/armclang/target.cmake b/cmake/compiler/armclang/target.cmake index 2a88bc294e7308..c84089fa1ae79f 100644 --- a/cmake/compiler/armclang/target.cmake +++ b/cmake/compiler/armclang/target.cmake @@ -67,13 +67,11 @@ foreach(isystem_include_dir ${NOSTDINC}) list(APPEND isystem_include_flags -isystem ${isystem_include_dir}) endforeach() -set(CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags}) +set(CMAKE_REQUIRED_FLAGS ${isystem_include_flags}) string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") -# Load toolchain_cc-family macros - -macro(toolchain_cc_nostdinc) - if(NOT "${ARCH}" STREQUAL "posix") - zephyr_compile_options( -nostdinc) - endif() -endmacro() +if(CONFIG_ARMCLANG_STD_LIBC) + # Zephyr requires AEABI portability to ensure correct functioning of the C + # library, for example error numbers, errno.h. + list(APPEND TOOLCHAIN_C_FLAGS -D_AEABI_PORTABILITY_LEVEL=1) +endif() diff --git a/cmake/kconfig.cmake b/cmake/kconfig.cmake index 979aa164fe1848..71668d0fe8aa10 100644 --- a/cmake/kconfig.cmake +++ b/cmake/kconfig.cmake @@ -103,6 +103,7 @@ set(COMMON_KCONFIG_ENV_SETTINGS BOARD_DIR=${BOARD_DIR} KCONFIG_BINARY_DIR=${KCONFIG_BINARY_DIR} TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR} + TOOLCHAIN_HAS_NEWLIB=$,y,n> EDT_PICKLE=${EDT_PICKLE} # Export all Zephyr modules to Kconfig ${ZEPHYR_KCONFIG_MODULES_DIR} diff --git a/cmake/toolchain/armclang/Kconfig b/cmake/toolchain/armclang/Kconfig new file mode 100644 index 00000000000000..c2df1e1024aa4c --- /dev/null +++ b/cmake/toolchain/armclang/Kconfig @@ -0,0 +1,23 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config LD_LINKER_SCRIPT_SUPPORTED + bool + default n + +choice LINKER_SCRIPT + default CMAKE_LINKER_GENERATOR +endchoice + +choice LIBC_IMPLEMENTATION + prompt "C Library Implementation" + default ARMCLANG_STD_LIBC + +config ARMCLANG_STD_LIBC + bool "ARM Compiler C library" + help + Use the full Arm Compiler runtime libraries. + A reduced Zephyr minimal libc will be used for library functionality + not provided by ARM Compiler standard libraries. + +endchoice diff --git a/cmake/toolchain/armclang/Kconfig.defconfig b/cmake/toolchain/armclang/Kconfig.defconfig new file mode 100644 index 00000000000000..a154f3035098db --- /dev/null +++ b/cmake/toolchain/armclang/Kconfig.defconfig @@ -0,0 +1,6 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SUPPORT_MINIMAL_LIBC + bool + default n diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index a3386fa0fb2070..00d453de56bd14 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -142,6 +142,7 @@ add_custom_target( ARCH=* ARCH_DIR=arch SOC_DIR=soc + TOOLCHAIN_HAS_NEWLIB=y KCONFIG_BINARY_DIR=${KCONFIG_BINARY_DIR} KCONFIG_WARN_UNDEF=y KCONFIG_TURBO_MODE=${KCONFIG_TURBO_MODE} diff --git a/lib/libc/CMakeLists.txt b/lib/libc/CMakeLists.txt index 6eea0313b4f543..fe72c26f7aa7dc 100644 --- a/lib/libc/CMakeLists.txt +++ b/lib/libc/CMakeLists.txt @@ -4,6 +4,8 @@ if(CONFIG_NEWLIB_LIBC) add_subdirectory(newlib) elseif(CONFIG_ARCMWDT_LIBC) add_subdirectory(arcmwdt) -else() +elseif(CONFIG_MINIMAL_LIBC) add_subdirectory(minimal) +elseif(CONFIG_ARMCLANG_STD_LIBC) + add_subdirectory(armstdc) endif() diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 74b742e0cbcd28..11945961da1c73 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -11,6 +11,10 @@ config REQUIRES_FULL_LIBC Helper symbol to indicate some feature requires a C library implementation with more functionality than what MINIMAL_LIBC provides +config SUPPORT_MINIMAL_LIBC + bool + default y + choice LIBC_IMPLEMENTATION prompt "C Library Implementation" default EXTERNAL_LIBC if NATIVE_APPLICATION @@ -21,6 +25,7 @@ config MINIMAL_LIBC bool "Minimal C library" depends on !NATIVE_APPLICATION depends on !REQUIRES_FULL_LIBC + depends on SUPPORT_MINIMAL_LIBC help Build with minimal C library. diff --git a/lib/libc/armstdc/CMakeLists.txt b/lib/libc/armstdc/CMakeLists.txt new file mode 100644 index 00000000000000..b92f061b411614 --- /dev/null +++ b/lib/libc/armstdc/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(src/errno.c) +zephyr_library_sources(src/string.c) +zephyr_library_sources(src/libc-hooks.c) + +zephyr_system_include_directories(include) diff --git a/lib/libc/armstdc/include/errno.h b/lib/libc/armstdc/include/errno.h new file mode 100644 index 00000000000000..58e1aee0aec437 --- /dev/null +++ b/lib/libc/armstdc/include/errno.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1984-1999, 2012 Wind River Systems, Inc. + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)errno.h 7.1 (Berkeley) 6/4/86 + */ + +/** + * @file + * @brief System error numbers + */ + +#ifndef ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_ERRNO_H_ +#define ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_ERRNO_H_ + +/** + * @brief System error numbers + * Error codes returned by functions. + * Includes a list of those defined by IEEE Std 1003.1-2017. + * + * This file is supposed to be used together with ARMClang and + * #define _AEABI_PORTABILITY_LEVEL 1 + * or + * -D_AEABI_PORTABILITY_LEVEL=1 + * + * For details, please refer to the document: + * 'C Library ABI for the Arm® Architecture, 2021Q1' + * + * @defgroup system_errno Error numbers + * @ingroup c_std_lib + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define errno (*z_errno()) + +#define EPERM 1 /**< Not owner */ +#define ENOENT 2 /**< No such file or directory */ +#define ESRCH 3 /**< No such context */ +#define EINTR 4 /**< Interrupted system call */ +#define EIO 5 /**< I/O error */ +#define ENXIO 6 /**< No such device or address */ +#define E2BIG 7 /**< Arg list too long */ +#define ENOEXEC 8 /**< Exec format error */ +#define EBADF 9 /**< Bad file number */ +#define ECHILD 10 /**< No children */ +#define EAGAIN 11 /**< No more contexts */ +#define ENOMEM 12 /**< Not enough core */ +#define EACCES 13 /**< Permission denied */ +#define EFAULT 14 /**< Bad address */ +#define ENOTBLK 15 /**< Block device required */ +#define EBUSY 16 /**< Mount device busy */ +#define EEXIST 17 /**< File exists */ +#define EXDEV 18 /**< Cross-device link */ +#define ENODEV 19 /**< No such device */ +#define ENOTDIR 20 /**< Not a directory */ +#define EISDIR 21 /**< Is a directory */ +#define EINVAL 22 /**< Invalid argument */ +#define ENFILE 23 /**< File table overflow */ +#define EMFILE 24 /**< Too many open files */ +#define ENOTTY 25 /**< Not a typewriter */ +#define ETXTBSY 26 /**< Text file busy */ +#define EFBIG 27 /**< File too large */ +#define ENOSPC 28 /**< No space left on device */ +#define ESPIPE 29 /**< Illegal seek */ +#define EROFS 30 /**< Read-only file system */ +#define EMLINK 31 /**< Too many links */ +#define EPIPE 32 /**< Broken pipe */ +/* Implemented in errno.c Argument too large */ +/* Implemented in errno.c Result too large */ +#define ENOMSG 35 /**< Unexpected message type */ +#define EDEADLK 45 /**< Resource deadlock avoided */ +#define ENOLCK 46 /**< No locks available */ +#define ENOSTR 60 /**< STREAMS device required */ +#define ENODATA 61 /**< Missing expected message data */ +#define ETIME 62 /**< STREAMS timeout occurred */ +#define ENOSR 63 /**< Insufficient memory */ +#define EPROTO 71 /**< Generic STREAMS error */ +#define EBADMSG 77 /**< Invalid STREAMS message */ +#define ENOSYS 88 /**< Function not implemented */ +#define ENOTEMPTY 90 /**< Directory not empty */ +#define ENAMETOOLONG 91 /**< File name too long */ +#define ELOOP 92 /**< Too many levels of symbolic links */ +#define EOPNOTSUPP 95 /**< Operation not supported on socket */ +#define EPFNOSUPPORT 96 /**< Protocol family not supported */ +#define ECONNRESET 104 /**< Connection reset by peer */ +#define ENOBUFS 105 /**< No buffer space available */ +#define EAFNOSUPPORT 106 /**< Addr family not supported */ +#define EPROTOTYPE 107 /**< Protocol wrong type for socket */ +#define ENOTSOCK 108 /**< Socket operation on non-socket */ +#define ENOPROTOOPT 109 /**< Protocol not available */ +#define ESHUTDOWN 110 /**< Can't send after socket shutdown */ +#define ECONNREFUSED 111 /**< Connection refused */ +#define EADDRINUSE 112 /**< Address already in use */ +#define ECONNABORTED 113 /**< Software caused connection abort */ +#define ENETUNREACH 114 /**< Network is unreachable */ +#define ENETDOWN 115 /**< Network is down */ +#define ETIMEDOUT 116 /**< Connection timed out */ +#define EHOSTDOWN 117 /**< Host is down */ +#define EHOSTUNREACH 118 /**< No route to host */ +#define EINPROGRESS 119 /**< Operation now in progress */ +#define EALREADY 120 /**< Operation already in progress */ +#define EDESTADDRREQ 121 /**< Destination address required */ +#define EMSGSIZE 122 /**< Message size */ +#define EPROTONOSUPPORT 123 /**< Protocol not supported */ +#define ESOCKTNOSUPPORT 124 /**< Socket type not supported */ +#define EADDRNOTAVAIL 125 /**< Can't assign requested address */ +#define ENETRESET 126 /**< Network dropped connection on reset */ +#define EISCONN 127 /**< Socket is already connected */ +#define ENOTCONN 128 /**< Socket is not connected */ +#define ETOOMANYREFS 129 /**< Too many references: can't splice */ +#define ENOTSUP 134 /**< Unsupported value */ +/* Implemented in errno.c Illegal byte sequence */ +#define EOVERFLOW 139 /**< Value overflow */ +#define ECANCELED 140 /**< Operation canceled */ + +#define EWOULDBLOCK EAGAIN /**< Operation would block */ + +/** + * @} + */ +#include_next + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_ERRNO_H_ */ diff --git a/lib/libc/armstdc/include/fcntl.h b/lib/libc/armstdc/include/fcntl.h new file mode 100644 index 00000000000000..2341803e37a82e --- /dev/null +++ b/lib/libc/armstdc/include/fcntl.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_FCNTL_H_ +#define ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_FCNTL_H_ + +#define O_CREAT 0x0200 +#define O_APPEND 0x0400 +#define O_EXCL 0x0800 +#define O_NONBLOCK 0x4000 + +#define F_DUPFD 0 +#define F_GETFL 3 +#define F_SETFL 4 + +int open(const char *name, int flags, ...); + +#endif /* ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_FCNTL_H_ */ diff --git a/lib/libc/armstdc/include/sys/timespec.h b/lib/libc/armstdc/include/sys/timespec.h new file mode 100644 index 00000000000000..55cb6b57d892f8 --- /dev/null +++ b/lib/libc/armstdc/include/sys/timespec.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Linaro Limited + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TIMESPEC_H_ +#define ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TIMESPEC_H_ + +#include + +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + +struct itimerspec { + struct timespec it_interval; /* Timer interval */ + struct timespec it_value; /* Timer expiration */ +}; + +#endif /* ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TIMESPEC_H_ */ diff --git a/lib/libc/armstdc/include/sys/types.h b/lib/libc/armstdc/include/sys/types.h new file mode 100644 index 00000000000000..7a46008b12fc7c --- /dev/null +++ b/lib/libc/armstdc/include/sys/types.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This defines the required types for the ARMClang compiler when comiling with + * _AEABI_PORTABILITY_LEVEL = 1 + * + * The types defined are according to: + * C Library ABI for the Arm® Architecture, 2021Q1 + * + */ +#ifndef ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TYPES_H_ +#define ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TYPES_H_ + +#if !defined(__ssize_t_defined) +#define __ssize_t_defined + +/* parasoft suppress item MISRAC2012-RULE_20_4-a item MISRAC2012-RULE_20_4-b + * "Trick compiler to make sure the type of ssize_t won't be + * unsigned long. View details in commit b889120" + */ +#define unsigned signed +typedef __SIZE_TYPE__ ssize_t; +#undef unsigned +#endif + +#if !defined(__off_t_defined) +#define __off_t_defined +typedef int off_t; +#endif + +#if !defined(__time_t_defined) +#define __time_t_defined +typedef unsigned int time_t; +#endif + +#if !defined(__clock_t_defined) +#define __clock_t_defined +typedef unsigned int clock_t; +#endif + +#endif /* ZEPHYR_LIB_LIBC_ARMSTDC_INCLUDE_SYS_TYPES_H_ */ diff --git a/lib/libc/armstdc/src/errno.c b/lib/libc/armstdc/src/errno.c new file mode 100644 index 00000000000000..923be5acc61156 --- /dev/null +++ b/lib/libc/armstdc/src/errno.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief System error numbers + * Error codes returned by functions. + * Includes a list of those defined by IEEE Std 1003.1-2017. + * + * This file is supposed to be used together with ARMClang and + * #define _AEABI_PORTABILITY_LEVEL 1 + * or + * -D_AEABI_PORTABILITY_LEVEL=1 + * + * For details, please refer to the document: + * 'C Library ABI for the Arm® Architecture, 2021Q1' + * + * @defgroup system_errno Error numbers + * @ingroup c_std_lib + * @{ + */ + +const int __aeabi_EDOM = 33; /**< Argument too large */ +const int __aeabi_ERANGE = 34; /**< Result too large */ +const int __aeabi_EILSEQ = 138; /**< Illegal byte sequence */ diff --git a/lib/libc/armstdc/src/libc-hooks.c b/lib/libc/armstdc/src/libc-hooks.c new file mode 100644 index 00000000000000..be7aef884cba6c --- /dev/null +++ b/lib/libc/armstdc/src/libc-hooks.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static int _stdout_hook_default(int c) +{ + (void)(c); /* Prevent warning about unused argument */ + + return EOF; +} + +static int (*_stdout_hook)(int) = _stdout_hook_default; + +void __stdout_hook_install(int (*hook)(int)) +{ + _stdout_hook = hook; +} + +volatile int *__aeabi_errno_addr(void) +{ + return &_current->errno_var; +} diff --git a/lib/libc/armstdc/src/string.c b/lib/libc/armstdc/src/string.c new file mode 100644 index 00000000000000..45f05155b18957 --- /dev/null +++ b/lib/libc/armstdc/src/string.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014 Wind River Systems, Inc. + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/** + * + * @brief Get fixed-size string length + * + * This function is not available in ARM C Standard library. + * + * @return number of bytes in fixed-size string + */ + +size_t strnlen(const char *s, size_t maxlen) +{ + size_t n = 0; + + while (*s != '\0' && n < maxlen) { + s++; + n++; + } + + return n; +} diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 86545756db3556..550f29a29890ef 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -328,6 +328,7 @@ def parse_kconfig(self): os.environ["ARCH"] = "*" os.environ["KCONFIG_BINARY_DIR"] = tempfile.gettempdir() os.environ['DEVICETREE_CONF'] = "dummy" + os.environ['TOOLCHAIN_HAS_NEWLIB'] = "y" # Older name for DEVICETREE_CONF, for compatibility with older Zephyr # versions that don't have the renaming @@ -522,6 +523,9 @@ def get_defined_syms(kconf): UNDEF_KCONFIG_WHITELIST = { "ALSO_MISSING", "APP_LINK_WITH_", + "ARMCLANG_STD_LIBC", # The ARMCLANG_STD_LIBC is defined in the toolchain + # Kconfig which is sourced based on Zephyr toolchain + # variant and therefore not visible to compliance. "CDC_ACM_PORT_NAME_", "CLOCK_STM32_SYSCLK_SRC_", "CMU",