19.2 Picolibc Library
The picolibc library implements the standard C and C++ library functions, types, and
macros; however, it provides additional thread safety and re-entrancy functionality not
available in the default library. It can be linked to a project using the
-mchp-stdlibc option, see Mchp-stdlibc Option.
The picolibc library is available for C and C++ projects and supports all ARM devices.
Use of the picolibc library disables the smart IO features associated with functions
like printf(). Math functions will also be linked from the picolibc
library with this selection. You may select between speed- and space-orientated library
alternatives of the picolibc library using the -mlibc-variant
option.
The picolibc library defines thread-safe instances of the errno global
variable, which is used by many standard library functions to indicate that an error was
detected during execution. These variables are defined to use Thread-Local Storage
(TLS), see Thread-local Storage. Using
TLS ensures that each thread has its own instance of errno, preventing
conflicts between threads.
The picolibc library also uses a global lock for APIs sharing global data. This includes
the malloc() family of functions, onexit() and
atexit(), and functions using timezones. This lock protects
relevant functions from race conditions and provides data integrity, ensuring that your
application is safe for use in a multithreaded environment. This prevents multiple
threads from accessing and modifying memory simultaneously, which could lead to
corruption or crashes.
Your application code must provide several functions to fully implement the retargetable
locking API. The picolibc library provides stubs for all of these functions, which can
be completed to suit your application. The stubs as provided do not perform locking, so
a single-threaded application can still use the library, despite locking being enabled.
See the document at github.com/picolibc/picolibc/blob/1.8.6/doc/locking.md for information. If you are using an RTOS, you might need to map
these functions to the RTOS's mutex functions. Ensure that your application initializes
and uses these locks correctly. Acquire the global lock before calling functions such as
malloc(), which uses locking to share global data. Release the lock
after the operation is complete.
Note that, like most standard C library implementations for bare-metal embedded systems,
low-level system functions must be provided by the operating environment or application
code. This includes functions such as gettimeofday(),
read(), write(), _exit(), etc.
The semihosting library does provide implementations of these functions, but these
functions would typically need to be customised to work with your specific hardware. You
may see an "undefined reference" error from the linker when linking.
