printf() with the FRDM-KL25Z Board and without Processor Expert

In this tutorial I explored how to use printf(), and this tutorial is so generic that it works for any processor/microcontroller. That flexibility is because I’m using Processor Expert. In case Processor Expert shall not be used, then some tweaks are needed. Here I show what is needed to have printf() working with the FRDM-KL25Z board. I use the UART0 connected to OpenSDA USB CDC for this.

Creating the Project

I create a new bareboard project. Nothing special here, except that ‘UART’ should be selected:

UART set for new project settings

UART set for new project settings

Low Level UART Support

As explained in this tutorial I, I need low-level UART support. CodeWarrior comes with the needed files for the TWR-KL25Z in “\MCU\ARM_GCC_Support\UART\TWR-KL25Z128”:

Low Level UART support files

Low Level UART support files

I copy these files into my project:

Copied Low Level UART Support Files

Copied Low Level UART Support Files

The TWR-KL25Z is using UART0 with PTA14/PTA15, while the FRDM-KL25Z is using UART0, but PTA1/PTA2. So I need to change the pin settings.

For this I disable in ConsoleIO.c, in ConsoleIO_Init() the settings for the Tower board, and add my change to use PTA1/PTA2:

void ConsoleIO_Init()
{
	InitClock();

	/* SIM_SCGC4: UART0=1 */
	SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
#if 0 /* TWR version: PTA14, PTA15 */
	/* PORTA_PCR15: ISF=0,MUX=3 */
	PORTA_PCR15 = (uint32_t)((PORTA_PCR15 & (uint32_t)~(uint32_t)(
				 PORT_PCR_ISF_MASK |
				 PORT_PCR_MUX(0x04)
				)) | (uint32_t)(
				 PORT_PCR_MUX(0x03)
				));
	/* PORTA_PCR14: ISF=0,MUX=3 */
	PORTA_PCR14 = (uint32_t)((PORTA_PCR14 & (uint32_t)~(uint32_t)(
				 PORT_PCR_ISF_MASK |
				 PORT_PCR_MUX(0x04)
				)) | (uint32_t)(
				 PORT_PCR_MUX(0x03)
				));
#else /* FRDM-KL25Z: PTA1/PTA2 */
	  /* PORTA_PCR1: ISF=0,MUX=2 */
	  PORTA_PCR1 = (uint32_t)((PORTA_PCR1 & (uint32_t)~0x01000500UL) | (uint32_t)0x0200UL);
	  /* PORTA_PCR2: ISF=0,MUX=2 */
	  PORTA_PCR2 = (uint32_t)((PORTA_PCR2 & (uint32_t)~0x01000500UL) | (uint32_t)0x0200UL);
#endif
	UART0_PDD_EnableTransmitter(UART0_BASE_PTR, PDD_DISABLE); /* Disable transmitter. */
	UART0_PDD_EnableReceiver(UART0_BASE_PTR, PDD_DISABLE); /* Disable receiver. */
	/* UART0_C1: LOOPS=0,DOZEEN=0,RSRC=0,M=0,WAKE=0,ILT=0,PE=0,PT=0 */
	UART0_C1 = 0x00U;                    /*  Set the C1 register */
	/* UART0_C3: R8T9=0,R9T8=0,TXDIR=0,TXINV=0,ORIE=0,NEIE=0,FEIE=0,PEIE=0 */
	UART0_C3 = 0x00U;                    /*  Set the C3 register */
	/* UART0_S2: LBKDIF=0,RXEDGIF=0,MSBF=0,RXINV=0,RWUID=0,BRK13=0,LBKDE=0,RAF=0 */
	UART0_S2 = 0x00U;                    /*  Set the S2 register */
	UART0_PDD_SetClockSource(UART0_BASE_PTR, UART0_PDD_PLL_FLL_CLOCK);
	UART0_PDD_SetBaudRate(UART0_BASE_PTR, 313U); /* Set the baud rate register. */
	UART0_PDD_SetOversamplingRatio(UART0_BASE_PTR, 3U);
	UART0_PDD_EnableSamplingOnBothEdges(UART0_BASE_PTR, PDD_ENABLE);
	UART0_PDD_EnableTransmitter(UART0_BASE_PTR, PDD_ENABLE); /* Enable transmitter */
	UART0_PDD_EnableReceiver(UART0_BASE_PTR, PDD_ENABLE); /* Enable receiver */
}

💡 To use different UART/port settings, the easiest way is to use a Processor Expert project as explained in this tutorial.

Example Code

For testing, I print a ‘hello world’ from the main() in main.c:

/*
 * main implementation: use this 'C' sample to create your own application
 *
 */

#include "derivative.h" /* include peripheral declarations */
#include
#include "ConsoleIO.h"

int main(void)
{
	int counter = 0;

	ConsoleIO_Init();
	for(;;) {
	   	counter++;
	   	printf("Hello world!\r\n");
	}
	return 0;
}

❗ Do not forget to include the correct header files, and to call ConsoleIO_Init()!

That’s it! Build, download and hopefully you see the messages printed to the console :-).

Floating point or not

Whenever possible, I avoid using floating point values in my projects: using floating point is adding a lot of code overhead I can avoid if I use integral or fixed point values. But if I want to use floating point in the ANSI library with printf() or scanf(), then I need to use the proper libraries. If I use

    printf("float value: %f\r\n", 3.75f);

And I get

float value: %f

then this means that I’m not using the correct library.

The ‘FP’ for (Floating Point) suffix in the library name for ARM gcc enable floating point support:

Floating Point Library Option

Floating Point Library Option

With this, I get the correct output:

float value: 3.750000

Project on GitHub

For reference, I have committed the CodeWarrior project and sources on GitHub here.

Happy Printing 🙂

18 thoughts on “printf() with the FRDM-KL25Z Board and without Processor Expert

  1. Pingback: Why I don’t like printf() | MCU on Eclipse

  2. Awesome tutorial, although it seems a little outdated compared to what you currently have on your github repository (for the example project FRDM-KL25Z_printf). In that example, you seem to have the intent of flashing the red LED while it waits for stream input. That LOOKS like the intent. What actually happens is my KL25Z waits at gets(), waiting for stdin input. I basically have to send a bunch of “things” into the terminal before the counter finally gets high enough to toggle the red LED. How can I fix this so it doesn’t actually wait/hang at gets() (or something similar like scanf() or getchar() )? I would expect it to look, see if anything is coming in, and if it isn’t it goes on with the rest of the code. That’s not the case in this example.

    Like

    • Hi Robert,
      thanks for your feedback!
      Yes, I had changed that demo project so it uses gets(). I have updated the project on GitHub now so it does the original thing, plus as a #define to enable the gets() part.
      As for your problem, I think the issue is with your terminal program, maybe? Does it send \r\n (linefeed) at the end? If not, then this might cause a problem as gets() waits until there is a new line.
      See http://en.cppreference.com/w/c/io/gets
      I hope this helpsl

      Like

      • When I hit return on my terminal (I’m using PuTTY) the characters are successfully sent to the KL25Z. My question is how to go about setting up some sort of interrupt for serial communication, such that the MCU does its business in an infinite loop but either has an interrupt for the terminal, or an if-statement it evaluates on every run-through of the loop. I don’t want it to hang, WAITING for user input. I checked out kbhit(), but it seems CodeWarrior doesn’t have conio.h and even if it did, it doesn’t make sense that the KL25Z would know what to do with it (the keyboard is connected to the COMPUTER, not the KL25Z). Does that make sense?

        Thanks,
        Robert

        Like

        • Hi Robert,
          I’m using the Asynchroserial component with Processor Expert. And this one is interrupt driven and features a FIFO buffer.
          So I do not need to wait for input: things come in by interrupt. And I can check the FIFO periodically (if something arrived), or getting events for every single character coming in.
          So what you describe is what I’m doing. But I’m not using the standard libraries as they are too much limited for this use case and for me. I’m using Processor Expert to generate that driver code for me.

          I hope this helps?

          Like

  3. Hello Erich,
    I tried to print a float number, but it would not work do yo have an idea why??

    Example:
    float var = 3.56;
    printf(“%f”,var);

    Result:

    %f

    Best regards…

    Like

  4. I´m using PE with GCC and Eclipse. Do you have or can point any place where I can find information on how to create or download the NewLib stubs c file ? I´m using your FSShell with CDC components. Thanks a lot.

    Like

  5. Hi Erich,

    I am not using KL25z, but my own hardware using the MKL26z256VLH4, can I still use the above example, using UART0 which I use for debugging?

    Like

  6. Hi Erich,

    I’m using Kinetis TWR-K60N512 and I would like to use the printf() for my bareboard project. I would like to use Virtual CDC USB serial port. I revised ‘ConsoleIO_Init()’ by changing UART3 to UART5, and PORTC16 & 17 to PORTE8 & PORTE9. But my program keeps getting suspended by the ‘default_handler()’ interrupt. What’s the workaround?

    Thanks.

    Like

    • Hi Dao,
      have you enabled clock gates for PORTE already? I suspect that you might get a hardfault on your default_handler. I recommend that you allocate indvidual interrupt handlers for each interrupt so you know the exact interrupt source.
      And I’m not sure why you are using UART for virtual USB CDC, as I think you want to communicate through USB (not through UART)? In any case you will need to re-write the standard I/O handlers for receiving and sending characters, including the interrupt handlers, otherwise things will not work. Anyway I do not recommend using printf() as using it is a bad idea and habit for embedded systems, see https://mcuoneclipse.com/2013/04/19/why-i-dont-like-printf/
      I hope this helps?

      Like

      • Yup, I have enabled the clock gates. Could you point me to an example that shows how I can allocate individual interrupt handlers for each interrupt?

        And yes, you are right, I want to communicate through USB, just like in the codewarrior example. I would like create my project with just c code (like the example, but it has many additional files…) and avoid using PE if possible. Could you also point me to the right tutorial(s) that demonstrate how to re-write the handlers that you mentioned ?

        What library should I include in order to use ‘puts’, can I use it without PE?

        Thanks!

        Like

        • For the interrupt handlers: I don’t have a tutorial for this, as this is widely different depending on your toolchain and tools you are using. Usually it is in the startup code file, search for the handler names.
          There you can define your own handlers, should be pretty obvious once you have found them.
          As for tutorials/example code: this is exactly what Processor Expert is for: it provides online help, example code and tutorials.
          As to where to define your special puts(): you might have a look at the GNU ARM Embedded (launchpad) default implementation and library files. I’m affraid that this is problably not simple, but if you search all the files you should be able to find it.

          I hope this helps, but you need to find your way through this.

          Like

Leave a reply to Rodrigo S. Cavalcanti Cancel reply

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