UART printf() for the FRDM-K64F Board and Kinetis Design Studio

I had great plans for this Saturday: to work on really cool project. But as so many times, things turned out to be different. Maybe you have read my recent posts about printf()? A colleague wanted to use that article to the same thing with the Kinetis Design Studio on the FRDM-K64F board. I used the FRDM-KL25Z board, so I expected this to work out of the box for him too. Well, turned out that I was wrong about this, and my Saturday was used for debugging and googling about a printf() problem 😦

While things work as expected for the FRDM-KL25Z (ARM Cortex-M0+) and using the standard GNU GCC ARM Embedded from the launchpad, the application traps on the K64F (ARM Cortex-M4F) in initialise_monitor_handles() with KDS:

Trap in initialize_monitor_handles()

Trap in initialize_monitor_handles()

Initially I thought it might be because of semihosting debugger settings (see “Semihosting with Kinetis Design Studio“). However, as this worked fine with stock Eclipse, the launchpad GNU ARM libraries and as well on the KL25Z board, it must be something special with the ARM Cortex M4(F) libraries in KDS? The function name initialise_monitor_handles() suggested it indeed must be something around the default semihosting mode in KDS somehow. After a lot of searching, the conclusion was that it must be something about the _isatty() function?

_isatty()

That function is described e.g. here.

int _isatty( 
int fd  
);

The _isatty function determines whether fd is associated with a character device (a terminal, console, printer, or serial port).

This function validates the fd parameter. If fd is a bad file pointer, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns 0 and sets errno to EBADF.

That function is used in the context of file handles and standard I/O redirection. A good short article describes this topic here.

💡 In the normal GNU ARM Embedded (launchpad) linker and libraries I can turn off usage of the standard I/O functionality with -specs=nosys.specs in the linker options.

So from the stack trace it looks like the KDS (V1.0.1 beta) M4 library tries to create/allocate some file handles, and then asserts with that BKPT (Breakpoint) instruction. So somehow the library is defaulting to a non tty (terminal) implementation.

Solution

The solution (or workaround) then was to overwrite the library _isatty() function and add this function to the application instead:

int _isatty(int file) {
  /* _isatty returns a nonzero value if the descriptor is associated with a character device (a terminal, console, printer, or serial port). Otherwise, _isatty returns 0. */
  return 1;
}

And voilà, things work now as the should: printf() is working :-).

Summary

The Kinetis Design Studio is using a different library implementation than the standard GCC ARM Embedded from the launchpad. And it seems that the libraries for Cortex M0+ and Cortex M4F in KDS are somehow different. As a result, for M4F an extra function need to be added to make printf() with a physical serial port working. Otherwise it will trap/assert in initialise_monitor_handles().

KDS Projects on GitHub:

Happy TTYing 🙂

Advertisements

6 thoughts on “UART printf() for the FRDM-K64F Board and Kinetis Design Studio

  1. Thank you for this guide, but I have some problems with KDS 2.0.0. It still getting stuck in initialise_monitor_handles even with _isatty() added to main(). When running printf() from main() the call trace is as follows:
    main()->__swbuf_r()->_fflush_r()->_write_r()->_write()->initialise_monitor_handles()->SIGTRAP (Disassembly: bkpt 0x00ab).

    To turn off semihosting, I followed the following:
    Under Segger debugger settings, Debugger tab: “Allocate console for semihosting and SWO” is off
    Under Segger debugger settings, Startup tab: “Enable SWO” is off

    Like

  2. Pingback: Installing and using Kinetis Design Studio version 2 in Linux >> Karibe Muriuki

  3. Hello. Thanks for these tutorials. I am pretty new to this environment and your suggestions are a very good way to start. I am actually trying to setup the UART0 with the FRDM-K64F board, but not succeeding. I use the SerialLDD module in Processor Expert, which generates the “SendBlock” method. I use it as in the example of the module. This is my Events.c:

    char OutData[] = “Hello world”;
    LDD_TError Error;
    LDD_TDeviceData *MySerialPtr;
    […]
    Error = Serial1_SendBlock(MySerialPtr, OutData, sizeof(OutData)); //this is in a timer interrupt event

    The problem is that the function returns an error which is associated to the fact that the previous transmission was not complete (even if there was no previous transmission), and thus it does not send anything at all. Do you have any suggestions? Is there a flag I should set to 0 during initialization? I also have interrupts for “OnBlockReceived” and “OnBlockSent” but I am not using them at this stage.

    Like

    • If this works depends on your interrupt nesting. Depending on your interrupt priorities, it might not be possible to send using UART0 interrupts from your timer interrupt.
      Anyway I do not recommend that you do such a sending from interrupt as this increases interrupt latency: set a flag in the timer interrupt and do the sending outside in your main program.

      Like

      • Hi Erich,
        thanks, super quick! I tried with your suggestion but it didn’t work, and then I just realised that I didn’t initialize the pointer (MySerialPtr = Serial1_Init(NULL);). Sorry for wasting your time. I am not 100% sure why this is needed (I tought that all of the initialization was automatized by PE), anyway. I will also follow your suggestions in the future and move the communication in the main function.

        Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.