Implementing write(), _write() or _write_r() with Newlib?
Asked Answered
N

1

11

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:

  1. 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?

  2. 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.

Nidia answered 16/8, 2015 at 4:50 Comment(5)
Since Standard C doesn't define a write function, conforming programs are allowed to define their own function (or variable) named write without it changing how printf behaves. This means that printf can't use a function named write, it has to use a function with a name that conforming programs aren't allowed to use, like say _write.Alisa
write() will work with open(); they are standard POSIX type functions. The special files number 0, 1, 2 are for stdin, stdout, stderr (typically). You write the implementation of these for newlib and if the file is >2 then it is some special file which you must index somehow. Ie, the open() would have specified a desired file to write to and returned a file number >2. USER code must not rely on these values. However, implementers need to define something.Rocaille
Not a direct answer to your question but this printf.c implementation is very easy to port to microcontrollers. I've used it several times and never had a problem with it except for one caveat: some compilers will optimize printf to puts and in the process break everything. In this case you can either implement puts too or rename printf to something else.Caniff
Pinetwig gave an excellent response below. One important point I'd like to make: "open()", "write()" and friends are usually thin wrappers around the underlying system calls. Unlike "printf()" (which is complicated code fully implemented in the C library), "write()" is usually just a minimal C interface to the OS. I'm not sure you want to mess with it...Anni
PS: Here's a good discussion of "reentrancy'. It's important to note that "reentrancy" is closely related to "thread safety", but they are not the same. For example, a subroutine might call itself (or call a nested function that in turn calls it again), and Bad Things can happen if it maintains any "static" data. A good example is "strtok()", which is neither thread-safe nor reentrant.Anni
L
3

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 .

Linearity answered 24/8, 2015 at 6:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.