4 years, 8 months ago.

[Keil uVision 5.2] - printf goes crazy

I am trying to export a program from the mbed online compiler to Keil uVision, however mbed does not support this export for my board (Wiznet W7500P):


So I exported manually and it seems to work properly except for the printf function that went crazy (prints "▒▒▒▒J▒▒▒" or "▒FOFO▒OVO" or "▒▒OVF▒▒RO" instead of "[INFO: /src/main.cpp:1320]").

Note: The exactly same code works perfectly if compiled in the online compiler

Have anyone faced a similar issue or has an insight about this issue?

Thanks, Pedro

1 Answer

4 years, 8 months ago.

Hi Petro, printf to what (on stdout?). This can be a baudrate problem. Anyway the mbed imported Keil does not support the serial console printing via USB tunnel. I use SWO printing for this.

Hi Helmut, you are right: printf on stdout that is redirected through an UART port. I also think it might be a baudrate problem but the exact same code works perfectly if compiled in the online compiler so maybe Keil is misconfigurating the baud rate or something like that. What do you mean by Keil does not support USB tunnel? This is the first time I am hearing about SWO, I will read about it. Thanks

posted by Pedro Sineiro Herig 20 May 2016

Hi Petro, all ARM CPU’s contain a remote debugging interface, this has also SWO channels included which allow high speed communication. The STM Nucleo, etc boards as well the Silicon Labs boards and others contain this SWO channel. Often it is used for printf debugging.

The STLink (for Nucleo) tool includes an SWO console window. The uVision includes an SWO console window.

For regular mbed printf debugging (on Nucleo) I use the UART which gets tunneled via USB and is visible as a tty/com port on Mac, Windows, Linux.

For uVision printf debugging I use the mbed SWO_Channel () library and redirect stdout to the SWO channel stream. (Search for SWO_Channel on mbed). uVision has no support for UART USB tunnelling but it supports the SWO channel.

    if (_useSWO) {
        swoOut = new SWO_Channel();
    } else {
        serOut = new BufferedSerial(USBTX, USBRX, 16, serialBufferSize);

This way I can use uVision with true debugging and keep my printf logging.

posted by Helmut Tschemernjak 20 May 2016

Helmut, thanks again for all your support. What do you mean by "redirect stdout"? Are you referring to the retarget.c file?

I tried to retarget the stdout using keil retarget.c file examples and it worked for simple programs (printf worked properly), however my actual project uses functions like fopen, fprintf and fclose and I am facing this issue: http://www.keil.com/support/docs/3279.htm

and the retarget file that the online compiler from mbed uses allowed me to compile the program with no errors but then the printf goes crazy.

Can you share a project in which you use the SWO_Channel () library with me? (I sent my email via private message)

posted by Pedro Sineiro Herig 20 May 2016

I don't know how to switch stdout, I believe code of freopen will show it. In my case I have a own developed debug base class which is inherited from all my classes, which means I can use my own printf which works with VAprintf and var args.

posted by Helmut Tschemernjak 20 May 2016

I investigated a little bit more into it, the stdout/stderr goes to the mbed default serial, there is no hook for it. The mbed library error() can be overwritten to be called with error (panic) messages,

Your serial logging should work, however the serial pass via USB is not supported in Keil.

posted by Helmut Tschemernjak 22 May 2016

I liked your idea of a debug base class which is inherited from all classes i believe it will also be the best solution for me. I'll work on that. Thanks a lot Helmut for all your time and support.

posted by Pedro Sineiro Herig 23 May 2016

Dear Pedro, as I explained I use a debug base class which includes an "dprint(fmt, ...) function. This I use in my app. In my main.cpp I have also an additional standard dprint(fmt, ...) C function which checks if my main app class is valid and calls the dprintf of debug class in my app.

This allows me to write generic mbed classes which are independent of my solution where I just declare dprintf as extern, thats it.

Once this is done you can print to any output (WIFI, SWO, Serial, or a log file), if you like even multiple log destinations at once. My printf puts a time stamp in front of the log and adds the extra CRLF chars. I call have a fucntion dump(name, addr, len) for hex dumping data, again as a base class, etc.

Good luck with your project.

posted by Helmut Tschemernjak 23 May 2016