I am trying to retarget printf()
function for STM32F411RET microcontroller in ARM GCC toolchain environment which uses Newlib for standard C library.
When I search for how to retarget printf()
, many people says I need to implement _write()
or _write_r()
. And it seems both working.
But I still have questions about them:
When I look through the document of Newlib, it says I can implement write()
to output files, but it doesn't look working. It looks like we can implement _write()
but this function never be mentioned in the document. What happend to write()
? does an underscore make anything different?
In which situation _write_r()
is preferable than _wirte()
? I don't understand the concept of reenterncy in C. Any examples?
Thanks for reading this.
For the first question, it's because Newlib wants to avoid name clashes ("namespace clean versions") by prepending an underscore to the name. See also Why do C compilers prepend underscores to external names?
For the second question, see Reentrancy and Reentrant in C?. If you have a multi-threaded program running on your board, and multiple threads can call newlib functions, then you need to use the reentrant versions of the syscalls. You also need to use reentrant syscalls if interrupt handlers can call newlib functions. However, it's perfectly okay to use the reentrant syscalls in a single-threaded application.
For example, if you use non-reentrant syscalls in a multi-threaded application, there's just one single global errno-flag. If errors occur in two or more threads, the global errno value can be overwritten. In the reentrant syscalls, each thread has its own errno-flag (in the _reent-struct - see here for the implementation). Thus, each thread can check for and handle its own errors.
Note: You have to recompile newlib to select what syscall model you want to use. See http://www.embecosm.com/appnotes/ean9/ean9-howto-newlib-1.0.html#sec_configure_host .