Recent from talks
Nothing was collected or created yet.
Newlib
View on WikipediaNewlib is a C standard library implementation intended for use on embedded systems. It is a conglomeration of several library parts, all under free software licenses that make them easily usable on embedded products.
It was created by Cygnus Support as part of building the first GNU cross-development toolchains. It is now maintained by Red Hat developers Jeff Johnston and Corinna Vinschen, and is used in most commercial and non-commercial GCC ports for non-Linux embedded systems.
System calls
[edit]The section System Calls[2] of the Newlib documentation describes how it can be used with many operating systems. Its primary use is on embedded systems that lack any kind of operating system; in that case it calls a board support package that can do things like write a byte of output on a serial port, or read a sector from a disk or other memory device.
Inclusion
[edit]Newlib is included in commercial GCC distributions by Atollic, CodeSourcery, Code Red, KPIT, Red Hat and others, and receives support from major embedded-processor architecture vendors such as ARM and Renesas. It is used as the standard C library in Cygwin, as well as being one standard C library among several for AmigaOS 4.
As of 2004[update], KallistiOS, an independent SDK targeting the Sega Dreamcast, has used Newlib as its standard C library, shipping it with many commercial titles on the platform.[3]
As of 2007[update], devkitARM and devkitPPC, toolchains targeted at homebrew development for commercial game systems, include Newlib as their C library. The Open-R SDK for Sony AIBO is also based on Newlib on top of the non-Unix Aperios.
As of 2013[update], Google Native Client SDK (NaCl) includes Newlib as the default C library over glibc.[4]
In 2019, Keith Packard released Picolibc,[5] a library offering standard C library APIs that targets small embedded systems with limited RAM, based on blending code from Newlib and AVR Libc.
See also
[edit]References
[edit]- ^ "Newlib releases".
- ^ System Calls, The Red Hat newlib C Library
- ^ "KallistiOS SourceForge Repository". Retrieved 9 January 2024.
- ^ "Native Client: Getting Started Tutorial". Retrieved 16 February 2013.
- ^ Picolibc: C Libraries for Smaller Embedded Systems
Further reading
[edit]- von Hagen, William L. (2006). The Definitive Guide to GCC, Second Edition. Berkeley, CA: Apress. pp. 289–290. ISBN 1-59059-585-8. Archived from the original on 2010-12-05. Retrieved 2011-01-07.
External links
[edit]- Newlib mailing list
- Embedding with GNU: Newlib, By Bill Gatliff, 2001-12-28, Embedded.com at the Wayback Machine (archived September 29, 2007)
Newlib
View on Grokipediaprintf(), malloc(), and file I/O operations while supporting resource-constrained hardware.[2] Developed as a conglomeration of software components from multiple sources, Newlib was originally assembled by Cygnus Solutions (now part of Red Hat) in the 1990s to support early GNU cross-compilation toolchains.[3]
Newlib's architecture emphasizes modularity and configurability, allowing developers to enable or disable features like multibyte character support, hardware floating-point acceleration, or space-optimized algorithms via build options such as --enable-newlib-mb or --enable-target-optspace.[4] This flexibility makes it suitable for a wide range of microcontrollers and real-time operating systems (RTOS), including integrations with toolchains like GCC, and platforms such as RTEMS, Zephyr, and Nios II.[5][6] Licensing is permissive and varied across its components—encompassing BSD, public domain, and other free software licenses—ensuring no requirement for source code disclosure or royalties in derivative projects, which facilitates its widespread adoption in commercial embedded products.[7][8] Annual snapshots are released from its Sourceware repository, with ongoing maintenance focused on compatibility with evolving C standards and embedded hardware trends.[4]
History and Development
Origins and Creation
Newlib was created by Cygnus Solutions in the late 1990s as part of the effort to build the first GNU cross-development toolchains for embedded targets lacking native operating system support.[3][9] This initiative addressed the need for a compact C standard library that could operate in resource-constrained environments, enabling developers to compile and run ANSI C code on diverse hardware without relying on heavy-weight system libraries.[5] The library was assembled by combining existing free software components from multiple open-source implementations, including parts derived from BSD and other public domain codebases.[10] These sources were selected for their permissive licenses, such as MIT and BSD variants, which allowed redistribution and modification while ensuring compatibility with the GNU toolchain.[10] This modular approach facilitated rapid development and broad applicability across different architectures. Newlib's initial design emphasized a lightweight alternative to full-featured libraries like glibc, prioritizing minimal dependencies to suit bare-metal and real-time operating system (RTOS) environments.[3] Cygnus Solutions, a key early contributor, integrated Newlib directly with the GNU Compiler Collection (GCC), streamlining cross-compilation workflows for embedded developers.[3] It has since evolved into modern releases under Red Hat maintenance.[1]Maintainers and Release History
Following the acquisition of Cygnus Support by Red Hat in 1999, Newlib's maintenance transitioned to Red Hat sponsorship around 2001, with primary maintainers Jeff Johnston ([email protected]) and Corinna Vinschen ([email protected]) overseeing development as Red Hat employees.[11][12] Newlib follows an annual release cadence for major versions, with early versions dating back to the late 1990s; subsequent releases include 2.0.0 in December 2012, 3.0.0 in January 2018, 4.0.0 in November 2020, 4.4.0 in December 2023, and the latest stable version 4.5.0 released on December 31, 2024.[13][14] Key milestones include integration with the GNU Compiler Collection (GCC) to support cross-development toolchains, the introduction of the nano-newlib variant in the 2010s (specifically with GCC ARM Embedded 4.7 in 2013) for resource-constrained embedded devices, and enhancements in versions 4.x such as support for new RISC-V ISA extensions and ongoing ARM architecture improvements.[15][16][17] Development occurs through the Git repository hosted on Sourceware.org, with contributions submitted as patches via the [email protected] mailing list using git format-patch and git send-email formats, emphasizing a focus on maintaining backward compatibility across releases.[13][11][18]Architecture and Components
Core Library Structure
Newlib's core library is structured as a modular amalgamation of several key components designed for embedded environments, primarily consisting of the standard C library (libc), which implements core functions such as string manipulation, memory allocation, and input/output operations, and the mathematics library (libm), which provides floating-point arithmetic routines compliant with IEEE 754 standards.[1][19] These sub-libraries form the foundational bulk of Newlib, with additional support modules integrated for compatibility with compilers like GCC, including runtime routines that handle low-level operations not covered by the standard C specification.[1]
A critical aspect of Newlib's internal organization is its reentrancy mechanism, which manages global variables through a single structure pointed to by the global pointer _impure_ptr. This pointer references a struct _reent instance, containing thread-specific state such as errno, file descriptors, and buffers, enabling safe operation in multi-threaded or "impure" environments where multiple execution contexts may access shared resources concurrently.[20] By default, Newlib initializes _impure_ptr to a single global _reent structure for single-threaded use, but in hosted environments, it can be dynamically reassigned per thread to maintain isolation and prevent race conditions during library calls.[21]
The library's design emphasizes modularity, permitting developers to selectively include or exclude features during compilation to optimize for resource-constrained targets; for instance, floating-point support from libm can be omitted to significantly reduce code size in integer-only applications.[22] This configurability is achieved through build-time options in the Newlib configuration system, allowing tailored builds like the lightweight "newlib-nano" variant that strips non-essential components while retaining core functionality.[16]
All components of Newlib are distributed under permissive free software licenses, with the core libc and libm primarily governed by the BSD license to facilitate broad adoption, while certain extensions and target-specific modules use GPL-compatible terms such as LGPL v2.1, ensuring compatibility for redistribution in both open-source and proprietary toolchains without imposing copyleft restrictions on linking applications.[10] This licensing approach, originating from contributions by entities like Red Hat and the Free Software Foundation, underscores Newlib's emphasis on portability and vendor neutrality.[10]
System Call Mechanism
Newlib interfaces with operating systems or hardware through a set of low-level system call stubs, which provide a uniform mechanism for operations such as input/output and memory allocation. These stubs, such as_read, _write, and _open, are not implemented within the core library but must be supplied by the host environment, board support package (BSP), or application code to enable functionality like file access or console output. For instance, the _write stub typically directs output to a specific device, while _open manages resource initialization, ensuring Newlib remains portable across diverse targets.[23]
The library supports multiple layers of system call implementations to accommodate varying environments. In hosted settings with POSIX-compliant systems, stubs invoke standard OS calls for full compatibility. For bare-metal applications without an OS, minimal stubs perform direct hardware interactions, such as returning error codes or zero for unsupported operations like _read (which might return 0 to indicate end-of-file). RTOS integrations, such as with FreeRTOS, extend this by providing hooks that route calls through the RTOS's scheduling and resource management, allowing seamless operation in multithreaded contexts.[23][24]
To support reentrancy in concurrent environments, Newlib offers variant stubs like _read_r, _write_r, and _open_r that accept a pointer to a reentrancy structure (struct _reent), enabling per-thread data management. The global _impure_ptr variable points to this structure, which stores thread-specific state, including errno values and file operation contexts, for syscalls involving dynamic allocation (e.g., malloc) or I/O. This design prevents data corruption across threads by isolating resources, with the structure initialized in startup code like crt0.c.[20]
In embedded targets, syscall stubs often feature simple, hardware-specific implementations; for example, a bare-metal _write might poll a UART peripheral to transmit characters sequentially without buffering or interrupts, ensuring reliable I/O on resource-constrained devices like microcontrollers. Such stubs are typically defined in a syscalls.c file within the BSP, overriding default weak symbols from Newlib's libnosys.a library.[23]
Features and Design Principles
Embedded System Adaptations
Newlib is particularly suited for embedded systems through its configurable options that minimize resource usage, such as the nano variant, which achieves a smaller footprint by excluding non-essential features like full locale support and advanced stdio buffering. The nano variant significantly reduces the code size compared to the full implementation, often by around 80% or more in sample applications, enabling deployment on memory-constrained microcontrollers without sacrificing core C standard library functionality. This size optimization is achieved via build-time configurations that prioritize code density over comprehensive feature sets, making it ideal for applications where every kilobyte matters.[25][26] A key adaptation for embedded environments is Newlib's lack of inherent assumptions about operating system services, instead depending on user-supplied stubs for system calls related to time, memory management, and input/output operations. This design facilitates bare-metal operation on resource-limited hardware, such as ARM Cortex-M series microcontrollers, where developers implement minimal syscall handlers to interface with hardware peripherals directly. By avoiding dependencies on a full OS, Newlib ensures portability and low overhead in environments without multitasking or file systems.[27][21] The math library component, libm, includes adaptations for embedded hardware lacking dedicated floating-point units, featuring software-emulated (soft-float) routines that can be selected during compilation. Precision is configurable to support either single-precision (float) or double-precision (double) operations, with dedicated functions like acosf for floats and acos for doubles to optimize performance and size based on application needs. These options allow developers to balance computational accuracy with the constraints of no-FPU devices, ensuring reliable mathematical computations in power-sensitive systems.[19][28] For concurrent embedded applications, Newlib incorporates thread-safety via reentrancy support, employing compile-time flags and the _impure_ptr mechanism to direct library functions to per-thread reentrancy structures (_reent). This approach stores thread-local state, such as errno and file pointers, preventing conflicts in multi-threaded contexts without requiring a complex OS. It is well-suited for lightweight real-time operating systems like FreeRTOS, where enabling reentrancy flags allows safe shared use of library routines across tasks.[29]Portability and Configuration
Newlib employs a GNU autotools-based build system, utilizing autoconf and automake to facilitate configuration and compilation across diverse host and target environments. The configuration process begins with theconfigure script, which accepts numerous options to tailor the library for specific use cases, such as the nano variant, which is selected at compile time using GCC specifications such as --specs=nano.specs for memory-constrained embedded systems, or --enable-newlib-multithread to include support for POSIX threads through reentrant implementations. These options allow developers to generate a customized library by specifying the target architecture and enabling or disabling features like reentrancy or formatted I/O optimizations during the build phase.[30][27]
The library's portability is achieved through its integration with GCC cross-compilers, enabling pre-built configurations for a wide range of architectures including x86, ARM, and RISC-V, often via board support packages (BSPs) provided by vendors. For instance, Intel FPGA toolchains incorporate Newlib adaptations within their BSPs for Nios processors, while Nordic Semiconductor's SDKs leverage Newlib for ARM-based nRF devices, allowing seamless deployment on vendor-specific hardware without extensive porting efforts. This modular design, combined with Libgloss for low-level system call stubs, ensures that Newlib can be adapted to new targets by implementing a minimal set of architecture-specific routines, such as those in the libc/machine/ directory.[1][31][32]
Newlib's permissive licensing, primarily under a BSD-style license, supports flexible distribution models, including static linking into closed-source firmware without requiring the disclosure of proprietary code. This contrasts with more restrictive licenses and facilitates its widespread adoption in commercial embedded products. To validate builds, Newlib includes a comprehensive testsuite run via make check-target-newlib, which employs the DejaGnu framework to execute regression tests assessing compliance with C99 and C11 standards, such as string handling, floating-point operations, and standard I/O functions, ensuring reliability across configurations.[10][30]
