0

I want use the function printf to print character on the serial port. I have read these 2 posts 1 and 2, But I'am not sure to understand the manip:

in the 1st link it's said:

To enable printf functionality, first you need to create a new __FILE struct. This struct is then called with FILE struct.

Why I have to create __FILE struct I didn't realy undrestand this sentence.

In the 2nd link it's said

To complete the separation from the standard I/O library we also have had to redefine __stdout and __stdin. These can be found inside the retarget.c file below the declaration of the __FILE structure.

If I redefine these 2 variables isn't that a compilation error I mean a redefinition.

Bence Kaulics
  • 7,066
  • 7
  • 33
  • 63
Mouin
  • 1,025
  • 4
  • 19
  • 33
  • That sure seems like the hard way to do it. Do you have `dup2()`? Does your platform have a "normal" `stdout` file descriptor value, such as Linux using file descriptor `1` for `stdout`? If so, just do something like `int fd = open( "/path/to/port"...); dup2( fd, STDOUT_FILENO);`. You might want to disable `stdout` buffering. – Andrew Henle Oct 01 '16 at 21:50
  • Maybe freopen could be of some use to you. – JohnTortugo Oct 01 '16 at 23:17
  • Thanks for the feedback, @Andrew Henle as i undrestand `printf` will use `fputc` to display the caracter on the scrreen so somewhere in `printf` function there is a call to `fputc(stdout, car)` so at this point if we have duplicated stdout fd the `car` will also be printd in the new fd (created by dup) but what happens then ? – Mouin Oct 02 '16 at 07:53
  • @ JohnTortugo According to [this post](http://stackoverflow.com/questions/1908687/how-to-redirect-the-output-back-to-the-screen-after-freopenout-txt-a-stdo) , it could be quite easy using `freopen ("/dev/tty", "a", stdout)` but actually am not using linux, anyway it may give some inspiration i will investigate more – Mouin Oct 02 '16 at 07:56
  • Seems like hard work to change the stdout handling underneath printf. Do you want to do it this way because you don't want to change existing printf() statemennts? If you can change those printf(), why not simply define serprintf() which uses sprintf() (or vsprintf()) to print to a string and then it outputs the string to the serialport? – DisappointedByUnaccountableMod Oct 02 '16 at 08:31
  • @barny yes this is the main reason, the above links describe the solution but i actually don't undrestand how they are working, of course i can change the printf with serprintf but it's question of curiosity – Mouin Oct 02 '16 at 10:02
  • @Mouin The links you provided are about trying to "separat[e] from the standard I/O library" in a very platform-specific way. As far as I can tell from what you've provided, your platform doesn't fully implement all C standard library functions, nor is it POSIX-compliant. So things like `dup2()` don't appear to be available. Is this what you're limited to: http://www.keil.com/support/man/docs/c51/c51_stdio_h.htm If so, you probably will have to write something like the code you provided the links to. Be aware, though, that such hacks will be platform-specific and easily broken. – Andrew Henle Oct 02 '16 at 12:25
  • Sometimes embedded compilers already direct stdout to the serial port, because otherwise printf would obviously be completely useless. So how do to this depends a lot on which compiler that is used. – Lundin Oct 03 '16 at 07:40
  • @AndrewHenle STM32 is an ARM microcontroller. This is likely a freestanding implementation, in which case desktop stuff like POSIX doesn't make any sense. Freestanding implementations don't have to provide stdio.h. – Lundin Oct 03 '16 at 07:43
  • Possible duplicate of [How to retarget printf() on an STM32F10x?](http://stackoverflow.com/questions/39815221/how-to-retarget-printf-on-an-stm32f10x) – Bence Kaulics Oct 03 '16 at 07:46

2 Answers2

1

This may possibly a duplication of How to make printf work on STM32F103?

I will put my answer, which I posted in the above thread, here too, anyway.

Writing an own printf implementation is an option, and probably the most recommended option according to me. Get some inspiration from the standard library implementation and write your own version, only to cater your requirements. In general, what you have to do is, first retarget a putc function to send char s through your serial interface. Then override the printf method by using the putc custom implementation. Perhaps, a very simple approach is sending the string character-wise by recursive calls for putc function.

Last but not least, you can find some lightweight printf implementations. The code size and the set of features offered by these lightweight implementations lie in between the custom written printf function and the stock standard prinf function (aka the beast). I have recently tried this and very pleased with its performance on an ARM core in terms of memory footprint and the number of execution cycles required. http://www.sparetimelabs.com/tinyprintf/tinyprintf.php

-PS

Copied from my own writings sometime back - http://mycola.info/2015/02/09/lightweight-printfscanf-for-embedded-applications/

ilya1725
  • 4,496
  • 7
  • 43
  • 68
SamR
  • 384
  • 3
  • 12
0

Add this piece of code in your code

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE * f)
#endif

PUTCHAR_PROTOTYPE {
    HAL_UART_Transmit( & huart2, (uint8_t * ) & ch, 1, 0xFFFF);
    return ch;
}

Only thing to edit is this line, set it as per your device serial port driver

HAL_UART_Transmit( & huart2, (uint8_t * ) & ch, 1, 0xFFFF);

Farrukh
  • 61
  • 3