Author Topic: Using printf with msp432e401y microcontroller  (Read 1990 times)

0 Members and 1 Guest are viewing this topic.

Offline Thomas83Topic starter

  • Contributor
  • Posts: 18
  • Country: fr
Using printf with msp432e401y microcontroller
« on: May 23, 2022, 09:28:41 am »
Hello everyone!

I just started working with the MSP432E401Y launchpad. My goal for  is to send some data to a terminal via UART0.
I am having trouble with the PRINTF Function, any data do not send to the terminal. It would be really difficult to implement what I need without these printf function.

Any help or an example would be greatly appreciated!
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26878
  • Country: nl
    • NCT Developments
Re: Using printf with msp432e401y microcontroller
« Reply #1 on: May 23, 2022, 09:34:35 am »
You'll likely need to write your own putchar() and puts() functions to send data to the serial port.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: Using printf with msp432e401y microcontroller
« Reply #2 on: May 23, 2022, 03:05:59 pm »
Hello everyone!

I just started working with the MSP432E401Y launchpad. My goal for  is to send some data to a terminal via UART0.
I am having trouble with the PRINTF Function, any data do not send to the terminal. It would be really difficult to implement what I need without these printf function.

Any help or an example would be greatly appreciated!

All of the examples TI provides with CCS for this part use a function UARTprintf() which is defined/declared in the files uartstdio.c/.h.
 
The following users thanked this post: Thomas83

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14439
  • Country: fr
Re: Using printf with msp432e401y microcontroller
« Reply #3 on: May 23, 2022, 04:58:02 pm »
You'll likely need to write your own putchar() and puts() functions to send data to the serial port.

Yes. I suspect TI already has working examples for this.

Another approach, more flexible and not requiring to know how to do the above is to implement your own function, using snprintf() instead for the formatting, an intermediate buffer, and then sending the buffer to whatever peripheral.
 
The following users thanked this post: Thomas83

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26878
  • Country: nl
    • NCT Developments
Re: Using printf with msp432e401y microcontroller
« Reply #4 on: May 23, 2022, 05:19:10 pm »
You'll likely need to write your own putchar() and puts() functions to send data to the serial port.

Yes. I suspect TI already has working examples for this.

Another approach, more flexible and not requiring to know how to do the above is to implement your own function, using snprintf() instead for the formatting, an intermediate buffer, and then sending the buffer to whatever peripheral.
That snprint method is messy. You'll need to declare a buffer and then transmit the data. Having the regular printf() working to write to a console output (in this case a serial port) makes code much cleaner and portable.
« Last Edit: May 23, 2022, 05:21:07 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 
The following users thanked this post: Thomas83

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14439
  • Country: fr
Re: Using printf with msp432e401y microcontroller
« Reply #5 on: May 23, 2022, 05:20:54 pm »
It's absolutely not messy and actually allows to define a fixed-size buffer instead of relying on printf(), which very often does dynamic allocation behind your back.
 
The following users thanked this post: Thomas83

Offline hans

  • Super Contributor
  • ***
  • Posts: 1637
  • Country: nl
Re: Using printf with msp432e401y microcontroller
« Reply #6 on: May 23, 2022, 05:46:02 pm »
It depends on the stdlib implementation of printf how that's implemented. If you're lucky it's doing an efficient non-buffered stream to putchar. If you're unlucky it drags in a complete stdlib with stdout, FILE* stream implementations and function pointers etcetera.

I prefer to use snprintf, at the cost of some extra buffer management. But atleast I can easily redirect serial data if needed. Portability of such a thing only requires a UartTxBytes(char*, size_t) function to be available for calling.
 
The following users thanked this post: Thomas83

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5894
  • Country: es
Re: Using printf with msp432e401y microcontroller
« Reply #7 on: May 23, 2022, 05:48:36 pm »
Search for "printf redirection" to find more about this procedure.
At least in SMT32 it's very easy, _write is usually declared as weak, meaning you can re-declare your own version.
Declare this function somewhere, ex. in main.c and expose it in main.h:
Code: [Select]
int _write(int fd, char* ptr, int len) {
    while(*ptr){
        UART_Send(*ptr++);
    }
    return len;
}

Then all std library functions using stdout will ultimately end there: printf, puts, putchar... and its variations.
« Last Edit: May 23, 2022, 07:54:06 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: Thomas83

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26878
  • Country: nl
    • NCT Developments
Re: Using printf with msp432e401y microcontroller
« Reply #8 on: May 23, 2022, 06:20:36 pm »
It's absolutely not messy and actually allows to define a fixed-size buffer instead of relying on printf(), which very often does dynamic allocation behind your back.
No. Printf typically uses a statically allocated buffer on embedded devices. Your own implementation could ofcourse use the stack as well.

printf("hello world")

Is definitely much cleaner compared to:

char my_buf[100];
int len;
len = snprintf(my_buf, sizeof(my_buf), "hello world");
send_to_a_uart(my_buf, len);

Why write a whole bunch of code to do what printf actually does under the hood? On top of that, it is also a lot of code replication which is bad.

Edit: if you need redirection to a different peripheral then either implement fprintf or do the multiplexing at the putchar() / puts() level. Most text based stuff in my embedded firmware deals with handling commands. The device where the command originates from, also receives the text output. Default the text output goes to the console port.
« Last Edit: May 23, 2022, 08:02:18 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 
The following users thanked this post: Thomas83

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: Using printf with msp432e401y microcontroller
« Reply #9 on: May 23, 2022, 06:34:09 pm »
You'll likely need to write your own putchar() and puts() functions to send data to the serial port.

Yes. I suspect TI already has working examples for this.

... which I noted in the post directly above yours.

Just sayin'.
 
The following users thanked this post: Thomas83

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3901
  • Country: gb
Re: Using printf with msp432e401y microcontroller
« Reply #10 on: May 23, 2022, 07:22:45 pm »
char_t -> console_out_char()
p_void_t -> console_out_pointer_as_hex()
p_uint8_t -> console_out_p_uint8_as_hex()
string_t -> console_out_string()
boolean_t -> console_out_boolean()
uint8_t -> console_out_uint8()
uint8_t -> console_out_uint8_as_hex()
sint8_t -> console_out_sint8()
uint16_t -> console_out_uint16()
sint16_t -> console_out_sint16()
sint16_t -> console_out_sint16_as_hex()
uint32_t -> console_out_uint32()
uint32_t -> console_out_uint32_as_hex()
sint32_t -> console_out_sint32()

'\n' -> console_out_NL()

one can always implement simple and dedicated things  :o :o :o
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 
The following users thanked this post: Thomas83

Offline Thomas83Topic starter

  • Contributor
  • Posts: 18
  • Country: fr
Re: Using printf with msp432e401y microcontroller
« Reply #11 on: May 24, 2022, 09:43:41 am »

as you advised me, I used the UARTprintf() function and it works.

Thank you everyone,
 

Offline rsjsouza

  • Super Contributor
  • ***
  • Posts: 5985
  • Country: us
  • Eternally curious
    • Vbe - vídeo blog eletrônico
Re: Using printf with msp432e401y microcontroller
« Reply #12 on: May 24, 2022, 10:48:57 am »
Search for "printf redirection" to find more about this procedure.
Indeed. Check the page below (near the end) for redirecting printf()

https://software-dl.ti.com/ccs/esd/documents/sdto_cgt_tips_for_using_printf.html
Vbe - vídeo blog eletrônico http://videos.vbeletronico.com

Oh, the "whys" of the datasheets... The information is there not to be an axiomatic truth, but instead each speck of data must be slowly inhaled while carefully performing a deep search inside oneself to find the true metaphysical sense...
 

Offline Thomas83Topic starter

  • Contributor
  • Posts: 18
  • Country: fr
Re: Using printf with msp432e401y microcontroller
« Reply #13 on: July 14, 2022, 12:25:25 pm »
Hi,

How can I use add puts and putc to work with printf function (msp432e401y).

I see that for msp432p:
https://github.com/bluehash/MSP432Launchpad/blob/master/MSP432-Launchpad-Printf-Support/printfOverride.c

Thanks for your help.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9889
  • Country: us
Re: Using printf with msp432e401y microcontroller
« Reply #14 on: July 14, 2022, 12:45:51 pm »
printf() may not use the heap but the string functions, called by printf(), just might.  If there is any reference to _sbrk() in the link output, a heap is probably being used.

Sometimes projects include "syscalls.c" where heap management and file IO is handled.  _sbrk() is often defined in this file.

I know absolutely nothing about the MSP432 toolchain and libraries.
 

Offline tellurium

  • Regular Contributor
  • *
  • Posts: 226
  • Country: ua
Re: Using printf with msp432e401y microcontroller
« Reply #15 on: July 14, 2022, 05:48:44 pm »
It all depends on the C library.

GNU ARM toolchain (https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain) comes with a C library called newlib, https://sourceware.org/newlib/ - developed by RedHat for embedded systems.

Newlib uses that _read/_write/....  "syscalls" mechanism. Higher level C functions like printf() just call those low level "syscalls". printf() eventually calls _write, fopen() eventually calls _open(), malloc() eventually calls _sbrk(), and so on. Thus, by modifying _write(), you can redirect printf() to whatever. That mechanism is called "IO retargeting".

STM32 Cube uses ARM GCC with newlib, that's why Cube projects typically include that syscalls.c - that's because of newlib C library.

Other toolchains, like TI's CCS, Keil's CC, might use a different  C library with a bit different retargeting mechanism. Search for "retargeting" in a particular doc should help.

This article is a good one for newlib: https://embeddedartistry.com/blog/2019/04/17/exploring-startup-implementations-newlib-arm/
« Last Edit: July 14, 2022, 06:02:58 pm by tellurium »
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: Using printf with msp432e401y microcontroller
« Reply #16 on: July 15, 2022, 11:11:18 am »
Quote
I used the UARTprintf() function and it works.

Quote
How can I use add puts and putc to work with printf function (msp432e401y)

If Ti has their own implementation of printf (UARTprintf), then they will also have their own implementation of UARTputChar or UARTwrite for single char or strings (this is what UARTprintf would be using). I doubt you want to start mixing in functions from a standard library such as newlib when you are already using what TI is providing.

Go to the source of UARTprintf, and you will find what functions they are using for single chars and strings.
 

Offline josuah

  • Regular Contributor
  • *
  • Posts: 119
  • Country: fr
    • josuah.net
Re: Using printf with msp432e401y microcontroller
« Reply #17 on: July 15, 2022, 12:54:10 pm »
Because I did not need anything complex like printf, I only have a fmtint() that returns a char*, a put(...) that print all print all strings as argument, them macros to make it easier:

Code: [Select]
/* format a signed integer `i64` at the end of `s` of size `sz` using base `b`
 * and return the first printable byte of `s` */
static char *fmtint(char *s, size_t sz, int64_t i64, uint8_t b);

/* print each string argument until NULL is encountered */
static int put_(char const *s, ...);

/* safer and easier wrapper around put_() */
#define put(...) put_(__VA_ARGS__, NULL)

/* macros to format integers and print them B(bin), D(dec), X(hex) */
#define fmtb(n) fmtint((char[65]){0}, 65, n, 2)
#define fmtd(n) fmtint((char[21]){0}, 21, n, 10)
#define fmtx(n) fmtint((char[17]){0}, 17, n, 16)
#define fmtc(c) (char[2]){ c, '\0' }

You end-up with something reasonable such as:

Code: [Select]
    put("error at address 0x", fmtx(addr), "\r\n");

The trick here is that the macros declare a nameless static buffer: (char[65]){0}
It saves from declaring on buffer per number to format every time.
Not all compilers might support this even though it is standard C99 afaik.

But maybe it is better to have something called printf, and behave like printf?
Otherwise, anyone else reading my code would have to investigate how put() works (5% of the code of printf though).

Yet another example of printf implementation to draw inspiration from is the one from scc, a compiler under ongoing development:
http://git.simple-cc.org/scc/file/src/libc/stdio/vfprintf%2Ec%2Ehtml

Something I have seen somewhere else:

Code: [Select]
puts("error at address 0x");
putx(addr);
puts("\r\n");

[EDIT: that last approach is the same as :]
« Last Edit: July 18, 2022, 10:34:45 am by josuah »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: Using printf with msp432e401y microcontroller
« Reply #18 on: July 17, 2022, 07:41:58 am »
Quote
It all depends on the C library.
Indeed.  See also funopen and/or fopencookie

these, along with the 'redefine _write()' solutions, do tend to drag in a complete newlib file-oriented library to implement "stdout", which is a lot of code and layers.   uart_printf() may do better...
(I think that essentially the _write()-style solutions change the bottom levels of stdout at compile-time, while the funopen-style solutions change the same bottom levels at run-time.  But they both end up invoking all the middle layers.)


Quote
If you're unlucky it drags in a complete stdlib with stdout, FILE* stream implementations...
I prefer to use snprintf, at the cost of some extra buffer management
Beware!  I think I've seen sprintf/etc also get implemented as part of a FILE* based implementation (or at least drag in a bunch of FILE* code, whether or not it's used.)

Making sure you are using newlib-nano and not just newlib may help.  For a while, chip vendors weren't being very careful about which version was appropriate.
 
The following users thanked this post: tellurium

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: Using printf with msp432e401y microcontroller
« Reply #19 on: July 17, 2022, 04:20:43 pm »
The snprintf solution is a good compromise, but does require figuring out how much buffer or stack space is enough. If your buffer ends uo smaller than needed at times with snprintf, your output just truncates (I suppose you could keep track of max needed and adjust the buffer size if on the stack). A simple example (one of many possible variations)-

https://godbolt.org/z/5doPMra3P

Like most anything else, creating a function is the way to go when using snprintf for this purpose (create once, then easy to use anywhere). One problem with newlib's stdio is it is hard to understand what is going on as the source code is filled with defines/aliases/ifdef's/etc. Using snprintf, at least you do not need much understanding to make it work. It will still use a FILE struct in the process (on the stack), which is quite large (~100 bytes for newlib), so the stack dips down some more in addition to a buffer you may have put on the stack (if that matters).

Compile size is usually not a big deal unless your mcu is on the low end. The above simple example (no uart setup, so does not function) compiles to about 3.1k on an stm32. The same example below, actually functioning using a uart buffer w/isr, using my own c++ cout style equivalent code in a c++ header (~300 lines), compiles to about 2.7k. The compiled sizes will be similar enough, even when 'printing' extensively, so compiled size is not necessarily a reason to favor one or the other.

Code: [Select]
#include "MyStm32.hpp" //uart inline instance created in there
int main(){
    u32 v = 0;
    while(1){
        uart << FG ORANGE "Hello World " << FG CYAN << Hex0xpad(8) << v++ << endl; //Hello World 0xNNNNNNNN
        //print( uart, FG ORANGE "Hello World ", FG CYAN, Hex0xpad(8), v++, endl ); //alternate syntax if tired of looking at chicken footprints

        }
}

The advantage to doing your own is you have complete control and can see/understand/modify the source code. I tried to figure out newlib stdio at one time, but got tired of going in circles reading the source, plus it seems to me the FILE struct is unreasonably large for the mcu's I use. I started to create a printf replacement, but switched to a c++ cout style instead as it seemed easier to write/read/modify. The advantage is I now have something I can use for any mcu with a c++ compiler, and I still have something that matches a (c++) standard way of formatting.

From what I gather searching online (although what I found looks like older code), TI has their own printf (UARTprintf) and is not using newlib to do any of it. Which is why I stated previously if you want putc/puts and are already using UARTprintf, then you just need find what the TI equivalent is for those. Here is an example of TI code (someones clone of TI code, first result from a search)-
https://github.com/ussserrr/maglev-ti-rtos/blob/master/uartstdio.c
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf