C standard libraries on bare metal
Yes, there is a standard, simply the C standard library. The library functions do not require a "full blown" OS, or any OS at all, and there are a number of implementations out there tailored to "bare metal" code, Newlib perhaps being the best known.
Taking Newlib as an example, it requires you to write a small subset of core functions, mainly how files and memory allocation is handled in your system. If you're using a common target platform, chances are that someone already did this job for you.
If you're using linux (probably also OSX and maybe even cygwin/msys?) and type man strlen
, it should have a section called something like CONFORMING TO
, which would tell you that the implementation conforms to a specific standard. This way you can figure out if something you've been using is a standard function or if it depends on a specific OS.
Is there a standard related to how a c library should be implemented or do you have to relearn peculiarity of a library implementations when you switch to new board which provides a different BSP?
First off, the C standard defines something called a "freestanding" implementation, as opposed to a "hosted" implementation (which is what most of us are familiar with, the full range of C functions supported by the underlying OS).
A "freestanding" implementation needs to define only a subset of the C library headers, namely those that do not require support, or even the definition of functions (they merely do #define
s and typedef
s):
<float.h>
<iso646.h>
<limits.h>
<stdalign.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
<stdnoreturn.h>
When you're taking the next step toward a hosted implementation, you will find that there are only very few functions that really need to interface "the system" in any way, with the rest of the library being implementable on top of those "primitives". In implementing the PDCLib, I made some effort to isolate them in a separate subdirectory for easy identification when porting the lib to a new platform (examples for the Linux port in parenthesis):
getenv()
(extern char * * environ
)system()
(fork()
/execve()
/wait()
)malloc()
andfree()
(brk()
/sbrk()
/mmap()
)_Exit()
(_exit()
)time()
(gettimeofday()
)
And for <stdio.h>
(arguably the most "OS-involved" of the C99 headers):
- some way to open a file (
open()
) - some way to close it (
close()
) - some way to remove it (
unlink()
) - some way to rename it (
link()
/unlink()
) - some way to write to it (
write()
) - some way to read from it (
read()
) - some way to reposition within it (
lseek()
)
Certain details of the library are optional, with the standard merely offering them to be implemented in a standard way but not making such an implementation a requirement.
The
time()
function may legally just return(time_t)-1
if no time-keeping mechanics are available.The signal handlers described for
<signal.h>
need not be invoked by anything other than a call toraise()
, there is no requirement that the system actually sends something likeSIGSEGV
to the application.The C11 header
<threads.h>
, which is (for obvious reasons) very dependent on the OS, need not be provided at all if the implementation defines__STDC_NO_THREADS__
...
There are more examples, but I don't have them at hand right now.
The rest of the library can be implemented without any help from the environment.(*)
(*)Caveat: The PDCLib implementation is not complete yet, so I might have overlooked a thing or two. ;-)
Standard C is actually defined separate from the operating environment. No assumption is made about a host OS being present, and those parts that are host dependent are defined as such.
That is, the C Standard is already pretty bare metal.
Of course, those language parts we love so much, the libraries, are often where the core language pushes that host specific stuff. Hence, the typical "xxx-lib" cross compiler stuff found for many bare metal platform tools.