Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -926,11 +926,14 @@ if(CONFIG_USERSPACE)
${APP_SMEM_UNALIGNED_LD}
)

if(CONFIG_PICOLIBC)
set(LIBC_PARTITIONS -l libc.a z_libc_partition)
endif()
if(CONFIG_NEWLIB_LIBC)
set(NEWLIB_PART -l libc.a z_libc_partition)
set(LIBC_PARTITIONS -l libc.a z_libc_partition)
Comment on lines +929 to +933
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

  if(CONFIG_PICOLIBC OR CONFIG_NEWLIB_LIBC)
    set(LIBC_PARTITIONS -l libc.a z_libc_partition)
  endif()

endif()
if(CONFIG_NEWLIB_LIBC_NANO)
set(NEWLIB_PART -l libc_nano.a z_libc_partition)
set(LIBC_PARTITIONS -l libc_nano.a z_libc_partition)
endif()

add_custom_command(
Expand All @@ -939,7 +942,7 @@ if(CONFIG_USERSPACE)
${ZEPHYR_BASE}/scripts/gen_app_partitions.py
-d ${OBJ_FILE_DIR}
-o ${APP_SMEM_UNALIGNED_LD}
${NEWLIB_PART}
${LIBC_PARTITIONS}
$<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
DEPENDS
Expand Down Expand Up @@ -990,7 +993,7 @@ if(CONFIG_USERSPACE)
${ZEPHYR_BASE}/scripts/gen_app_partitions.py
-e $<TARGET_FILE:app_smem_unaligned_prebuilt>
-o ${APP_SMEM_ALIGNED_LD}
${NEWLIB_PART}
${LIBC_PARTITIONS}
$<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
DEPENDS
Expand Down
8 changes: 8 additions & 0 deletions doc/getting_started/toolchain_3rd_party_x_compilers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ You can build toolchains from source code using crosstool-NG.

./go.sh <arch>

You can use this method to build a toolchain using picolibc as
well. ``sdk-ng`` has configurations for arm64-picolibc, arm-picolibc and
riscv64-picolibc (which supports both 32- and 64- bit RISC-V targets).

.. code-block:: console

./go.sh <arch>-picolibc

.. note::

Currently, only i586 and Arm toolchain builds are verified.
Expand Down
30 changes: 30 additions & 0 deletions doc/getting_started/toolchain_other_x_compilers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,33 @@ the common prefix is ``/usr/bin/arm-none-eabi-`` (including the trailing dash,
``-``). If your toolchain is installed in ``/opt/mytoolchain/bin`` with binary
names based on target triplet ``myarch-none-elf``, ``CROSS_COMPILE`` would be
set to ``/opt/mytoolchain/bin/myarch-none-elf-``.

Other C Libraries
#################

Once you have a cross compiler installed and configured, you may need to install
a C library. For example, you might install the picolibc-arm-none-eabi package
on Debian-based Linux systems:

.. code-block:: console

# On Debian
sudo apt-get install picolibc-arm-none-eabi

Or, you may install picolibc from source. To get the picolibc source, download a
tarball from github:

$ wget https://github.com/picolibc/picolibc/archive/1.4.6.tar.gz
$ tar xf 1.4.6.tar.gz
$ cd picolibc-1.4.6

There are sample configurations for a range of cross compilers provided with
picolibc, including RISC-V and ARM. For example, to build picolibc using an
arm-none-eabi compiler:

..code-block:: console

$ mkdir build
$ cd build
$ sh ../do-arm-configure
$ ninja install
7 changes: 7 additions & 0 deletions doc/guides/c_library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ support for ``newlib`` is a set of hooks available under
:file:`lib/libc/newlib/libc-hooks.c` which integrates the c library with basic
kernel services.

Zephyr can be used with ``picolibc`` by selecting the
:option:`CONFIG_PICOLIBC` in the application configuration file. Part of the
support for ``picolibc`` is a set of hooks available under
:file:`lib/libc/picolibc/libc-hooks.c` which integrates the c library with basic
kernel services. Applications that do not require floating point scanf or printf
functionality can select the
:option:`CONFIG_PICOLIBC`

Minimal C Library
*****************
Expand Down
20 changes: 17 additions & 3 deletions include/sys/libc-hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* that need to call into the kernel as system calls
*/

#ifdef CONFIG_NEWLIB_LIBC
#if defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC)

/* syscall generation ignores preprocessor, ensure this is defined to ensure
* we don't have compile errors
Expand Down Expand Up @@ -58,7 +58,21 @@ extern struct k_mem_partition z_malloc_partition;
*/
#define Z_MALLOC_PARTITION_EXISTS 1
#endif /* CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0 */
#endif /* CONFIG_MINIMAL_LIBC */
#elif defined(CONFIG_PICOLIBC)
/* If we are using picolibc, the heap arena is in one of two areas:
* - If we have an MPU that requires power of two alignment, the heap bounds
* must be specified in Kconfig via CONFIG_PICOLIBC_ALIGNED_HEAP_SIZE.
* - Otherwise, the heap arena on most arches starts at a suitably
* aligned base addreess after the `_end` linker symbol, through to the end
* of system RAM.
*/
#if (!defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) || \
(defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) && \
CONFIG_PICOLIBC_ALIGNED_HEAP_SIZE))
#define Z_MALLOC_PARTITION_EXISTS 1
extern struct k_mem_partition z_malloc_partition;
#endif
#endif /* CONFIG_PICOLIBC */

#ifdef Z_MALLOC_PARTITION_EXISTS
/* Memory partition containing the libc malloc arena. Configuration controls
Expand All @@ -68,7 +82,7 @@ extern struct k_mem_partition z_malloc_partition;
#endif

#if defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_STACK_CANARIES) || \
defined(CONFIG_NEED_LIBC_MEM_PARTITION)
defined(CONFIG_PICOLIBC) || defined(CONFIG_NEED_LIBC_MEM_PARTITION)
/* Minimal libc has no globals. We do put the stack canary global in the
* libc partition since it is not worth placing in a partition of its own.
*
Expand Down
8 changes: 8 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,17 @@ config THREAD_USERSPACE_LOCAL_DATA
depends on USERSPACE
default y if ERRNO && !ERRNO_IN_TLS

config LIBC_ERRNO
bool
help
Use external libc errno, not the internal one. This makes sure that
ERRNO is not set for libc configurations that provide their own
implementation.

config ERRNO
bool "Enable errno support"
default y
depends on !LIBC_ERRNO
help
Enable per-thread errno in the kernel. Application and library code must
include errno.h provided by the C library (libc) to use the errno
Expand Down
3 changes: 3 additions & 0 deletions kernel/errno.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ static inline int *z_vrfy_z_errno(void)
#include <syscalls/z_errno_mrsh.c>

#else
#ifndef CONFIG_PICOLIBC
int *z_impl_z_errno(void)
{
return &_current->errno_var;
}
#endif /* CONFIG_PICOLIBC */

#endif /* CONFIG_USERSPACE */

#endif /* CONFIG_ERRNO_IN_TLS */
Expand Down
4 changes: 4 additions & 0 deletions lib/libc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# SPDX-License-Identifier: Apache-2.0

if(CONFIG_PICOLIBC)
add_subdirectory(picolibc)
else()
if(CONFIG_NEWLIB_LIBC)
add_subdirectory(newlib)
else()
add_subdirectory(minimal)
endif()
endif()
Comment on lines +3 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make an elseif() in this case.

Suggested change
if(CONFIG_PICOLIBC)
add_subdirectory(picolibc)
else()
if(CONFIG_NEWLIB_LIBC)
add_subdirectory(newlib)
else()
add_subdirectory(minimal)
endif()
endif()
if(CONFIG_PICOLIBC)
add_subdirectory(picolibc)
elseif(CONFIG_NEWLIB_LIBC)
add_subdirectory(newlib)
else()
add_subdirectory(minimal)
endif()

35 changes: 35 additions & 0 deletions lib/libc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ config MINIMAL_LIBC
help
Build with minimal C library.

config PICOLIBC
bool "Picolibc library"
depends on !NATIVE_APPLICATION
select THREAD_LOCAL_STORAGE if ARCH_HAS_THREAD_LOCAL_STORAGE
select LIBC_ERRNO
help
Build with picolibc library. The picolibc library is expected to be
part of the SDK in this case.

config NEWLIB_LIBC
bool "Newlib C library"
depends on !NATIVE_APPLICATION
select LIBC_ERRNO
help
Build with newlib library. The newlib library is expected to be
part of the SDK in this case.
Expand All @@ -41,11 +51,36 @@ endchoice # LIBC_IMPLEMENTATION
config HAS_NEWLIB_LIBC_NANO
bool

if PICOLIBC

config PICOLIBC_INTEGER_PRINTF
bool "Build with picolibc integer-only printf"
help
Build with floating point printf disabled. This will reduce the size
of the image.

config PICOLIBC_ALIGNED_HEAP_SIZE
int "Picolibc aligned heap size (bytes)"
depends on MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
depends on USERSPACE
default 0
help
If user mode is enabled, and MPU hardware has requirements that
regions be sized to a power of two and aligned to their size,
and user mode threads need to access this heap, then this is necessary
to properly define an MPU region for the heap.

If this is left at 0, then remaining system RAM will be used for this
area and it may not be possible to program it as an MPU region.

endif # PICOLIBC

if NEWLIB_LIBC

config NEWLIB_LIBC_NANO
bool "Build with newlib-nano C library"
depends on HAS_NEWLIB_LIBC_NANO
select LIBC_ERRNO
default y
help
Build with newlib-nano library, for small embedded apps.
Expand Down
41 changes: 41 additions & 0 deletions lib/libc/picolibc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_sources(libc-hooks.c)

# Zephyr normally uses -ffreestanding, which with current GNU toolchains
# means that the flag macros used by picolibc <inttypes.h> to signal
# support for PRI.64 macros are not present. To make them available we
# need to hook into the include path before the system files and
# explicitly include the picolibc header that provides those macros.
zephyr_include_directories(include)

# define __LINUX_ERRNO_EXTENSIONS__ so we get errno defines like -ESHUTDOWN
# used by the network stack
zephyr_compile_definitions(__LINUX_ERRNO_EXTENSIONS__)

zephyr_link_libraries(
m
c
gcc # Lib C depends on libgcc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No changes requested, but with the fact that Zephyr is working towards more toolchains, especially LLVM, and thus also the support of compiler-rt runtime library, I was wondering if picolib could be used in that case.

Also this makes me wonder if the use of picolib should be restricted, based on toolchain in use.
But that would probably need to go into a bigger work at later time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

picolibc built with llvm still requires libgcc as that has all of the helper functions required by the underlying ABI, such as the __aeabi functions for ARM. -lgcc would be automatically inserted into the link command by the compiler front-end (either clang or gcc) if zephyr wasn't using -nostdlib. zephyr could probably remove that flag and simply let the compiler front end insert both -lc and -lgcc.

)

# The -T/dev/null avoids pulling in picolibc.ld
zephyr_link_libraries(
--specs=picolibc.specs
-T/dev/null
)

zephyr_compile_options(
--specs=picolibc.specs
-D_GNU_SOURCE
)

if(CONFIG_PICOLIBC_INTEGER_PRINTF)
zephyr_compile_options(
-DPICOLIBC_INTEGER_PRINTF_SCANF
)
zephyr_link_libraries(
-DPICOLIBC_INTEGER_PRINTF_SCANF
)
endif()
Loading