11

I am trying to retarget the printf() function for the STM32F411RET microcontroller in the ARM GCC toolchain environment which uses Newlib for the C standard library.

When I search for how to retarget printf(), many people say 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 like it is working. It looks like we can implement _write(), but this function is never be mentioned in the document. What happened to write()? Does an underscore make anything different?

  2. In which situation is _write_r() preferable to _write()? I don't understand the concept of reentrancy in C. Any examples?

5
  • 2
    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. Commented Aug 17, 2015 at 2:31
  • 3
    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. Commented Aug 17, 2015 at 12:53
  • 3
    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. Commented Aug 18, 2015 at 21:06
  • 2
    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... Commented Aug 24, 2015 at 6:44
  • 1
    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. Commented Aug 24, 2015 at 6:51

1 Answer 1

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 system calls. You also need to use reentrant system calls if interrupt handlers can call Newlib functions. However, it's perfectly okay to use the reentrant system calls in a single-threaded application.

For example, if you use nonreentrant system calls 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 system calls, 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 system call model you want to use. See 3.3. Extending configure.host for a New Target.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.