MDK-ARM Development Question: Using the Keil MDK-ARM Microcontroller Development Kit and the standard C Library, how does one implement access to multiple serial ports (UARTs) simultaneously when using the retargeting scheme of rewriting the lower level I/O functions? I am writing code for an STM32F103ZG which has five UARTs on board, all of which I need to access simultaneously.
It seems like, in the provided example (Blinky project), rewriting the lower level I/O routines (fputc(), fgetc(), etc.) just allows you to retarget to a single serial port.
In your code, when you use a higher level I/O function, such as printf(), there is only one corresponding lower level fgetc() routine to be called. So it would appear that you can only retarget to a single serial port.
I’ve got to believe that folks do this all the time, so what am I missing? Any suggestions on the simplest way to implement access to multiple UARTs would be greatly appreciated.
your mistake is that you think of using putc() for all UARTs. Most do not even use putc() for the first of many.
a simple FIFO transmit/recieve scheme is 'standard operating procedure'
Erik
Erik, Thanks very much! I appreciate you sending me off in the correct direction. Any idea where a novice like me might find an example of a simple UART FIFO transmit/receive scheme, such as you suggested? Thanks again for the quick response! James
My hope was to use the formatting advantages afforded by the higher level I/O routines such as printf(). Is there no way to do that if simultaneous access to multiple serial ports is required? James
printf() can't route data. It's the fprintf() function that supports stream selection.
So your retarget code must either have a fputc() that directs output to the correct serial port based on your FILE *f parameter. You may have hard-coded FILE pointers representing stdout, stderr, strprn - or maybe instead debug port, modem port, gps, ...
Another alternative is to make use of sprintf() and emit the generated string to the proper FIFO. So you might have:
mon_printf() - emit to monitor port. modem_printf() - emit to modem. tty_printf() - emit to some arbitrary tty somewhere.
Thanks! Using sprintf() is a great idea!! I'll do that. I guess I could use your same idea with sscanf() after reading from a USART buffer. Any chance you know where I might find examples of propery written input and output FIFO buffer routines for reading and writing to a UART? Again -- I really appreciate your response. James
Just google for sample code for your processor family. Keil have samples for other ARM families, but then you need to translate the actual register names and status bit names.
You want round-robin, FIFO, circular buffer etc as alternative search names.
But the implementation should have one index for inserting and another for extracting. On transmit, the main program owns the insert index and the ISR owns the extract index. Reverse on reception. But that means that as long as the indices can be atomically read, you don't need any locking primitives.
The nicest solution is an implementation that requires the FIFO to be 2^n elements large, and who just increment the indices without restarting them at zero when they reach the full size of the FIFO.
I can't thank you enough! James