If you ever wanted to debug your code(for your microcontroller) using printf() over UART in CooCox CoIDE then this tutorial will help you achieve that. In this tutorial we will see how to retarget printf() in CoIDE and send its output over UART to PC or Laptop to view the output in a serial console. This will work for most the ARM Microcontrollers supported by CooCox CoIDE like LPC176x, LPC134x, LPC111x, STM32F10x, etc..
STEP 1:
Create your CoIDE project as usual.
STEP 2:
Under Repository Tab select:
- Retarget Printf
- CMSIS Core
- CMSIS boot
This will add printf.c under group stdio along with cmsis and cmsis_boot.
Step 3:
Create and Add files: uart.c and uart.h to your Project. uart.c must contain the UART initialization code for your specific MCU along with a simple write() function that accepts a character as parameter and sends it over UART. uart.h must contain declarations for UART init and write functions. uart.h will be included in main.c, printf.c and uart.c.
Here is a template for uart source files (Complete Example in Example section)
uart.c template:
#include <stdio.h>
#include <ADD_MCU_SPECIFIC_HEADER_HERE>
#include "uart.h"
void initUART(void)
{
/*
UART initialization code here
*/
}
void uartWrite(char cChar) //Send a single character, called by PrintChar() defined in printf.c
{
/*
Code to send a character over UART
*/
}
uart.h template:
#ifndef _UART_HEADER_
#define _UART_HEADER_
void initUART(void);
void uartWrite(char data);
#endif
Step 4:
Edit printf.c to add following include line:
#include "uart.h"
Finally, we need to edit code inside function PrintChar(). By default it will be blank with a 3 line comment. Just add the following line before closing brace of this function:
uartWrite(c);
Here is a snippet of edited printf.c (showing frist 25 lines only):
/**************************************************************************//*****
* @file printf.c
* @brief Implementation of several stdio.h methods, such as printf(),
* sprintf() and so on. This reduces the memory footprint of the
* binary when using those methods, compared to the libc implementation.
********************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include "uart.h" //Add this line
/**
* @brief Transmit a char, if you want to use printf(),
* you need implement this function
*
* @param pStr Storage string.
* @param c Character to write.
*/
void PrintChar(char c)
{
/* Send a char like:
while(Transfer not completed);
Transmit a char;
*/
uartWrite(c); //Add this line
}
STEP 5:
Inside main() function of your project, call uartWrite() to init UART so we can use retargetted printf(). After that you can use printf() as usual. Needless to say, you will need to include <stdio.h> wherever you want to use printf().
Function call Hierarchy in CooCox CoIDE’s implementation
Retargeted Printf() in CoIDE examples
Now, lets see some concrete examples of retargetting printf() using UART with source code. The following example uses a baud rate of 115200.
Retarget printf() for LPC1343
Code for uart.c (For more, refer LPC1343 UART Programming Tutorial) :
/*(c) Umang Gajera - www.ocfreaks.com
* UART init and write functions for printf()
* Adapted from:
* https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/
* More Embedded stuff @ https://www.ocfreaks.com/cat/embedded/
* License : GPL */
#include <stdio.h>
#include "lpc13xx.h"
#include "uart.h"
#define THRE (1<<5) //Transmit Holding Register Empty
#define MULVAL 1
#define DIVADDVAL 0
#define Ux_FIFO_EN (1<<0)
#define Rx_FIFO_RST (1<<1)
#define Tx_FIFO_RST (1<<2)
#define DLAB_BIT (1<<7)
//#define LINE_FEED 0x0A //LF, For Linux, MAC and Windows Terminals
//#define CARRIAGE_RETURN 0x0D //CR, For Windows Terminals (CR+LF).
void initUART(void) //Sets up UART @ 115200 baud rate using UART_PCLK=72Mhz
{
/*Assuming CCLK=72Mhz!*/
//UART CLOCK Enable Sequence Step 1 - Select TXD,RXD functions
LPC_IOCON->PIO1_6 = 0x1; //Select RXD for PIO1_6
LPC_IOCON->PIO1_7 = 0x1; //Select RXD for PIO2_6
//UART CLOCK Enable Sequence Step 2 - Set Divider & Enable Clock
LPC_SYSCON->UARTCLKDIV = 1; //Set Divider by 1, so UART_PCLK=CCLK
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);//Enable UART clock
LPC_UART->LCR = 3 | DLAB_BIT ; /* 8 bits, no Parity, 1 Stop bit & DLAB set to 1 */
LPC_UART->DLL = 39;
LPC_UART->DLM = 0;
LPC_UART->FCR |= Ux_FIFO_EN | Rx_FIFO_RST | Tx_FIFO_RST;
LPC_UART->FDR = (MULVAL<<4) | DIVADDVAL; /* MULVAL=15(bits - 7:4) , DIVADDVAL=2(bits - 3:0) */
LPC_UART->LCR &= ~(DLAB_BIT);
//Now since we have applied DLL and DLM we now lock or freeze those values by disabling DLAB i.e DLAB=0
//Baud= ~115200. Now we can perform UART communication!
}
void uartWrite(char cChar) //Send a single character, called by PrintChar() defined in printf.c
{
while ( !(LPC_UART->LSR & THRE) ); // wait till the THR is empty
// now we can write to the queue
LPC_UART->THR = cChar;
}
Code for uart.h and edited printf.c is same as given in above section.
Source code for main.c :
/*(c) Umang Gajera - www.ocfreaks.com
* Retarget Printf() using UART in CoIDE tutorial
* More Embedded stuff @ https://www.ocfreaks.com/cat/embedded/
* License : GPL */
#include <stdio.h>
#include "lpc13xx.h"
#include "uart.h"
int main(void)
{
/*SystemInit(); gets called boot code and sets CCLK=72Mhz*/
initUART(); /*Init UART before calling printf()!*/
/*UART Baud = 115200*/
int num = 1343;
int num2 = -99;
int numh = 0x3CA;
char string1[] = "This is a String";
printf("Hi. I am printf() sending output over UART!\n\r");
printf("I have been called for:\n\r");
printf("OCFreaks.com - retarget printf() in CoIDE tutorial.\n\r");
printf("num = %d\n\r",num);
printf("num2 = %i\n\r",num2);
printf("numh(hex) = %X\n\r",numh);
printf("string1 = %s\n\r",string1);
while(1);
/*return 0; This won't execute*/
}
Screenshot of above example in action – sending printf() output over UART:
Retarget printf() for LPC1768/LPC1769
To retarget printf() for LPC1768 & LPC1769 microcontrollers in CooCox CoIDE, you will just need to modify uart.c file in the above example and replace the initUART() function with that for LPC176x. You can refer my previous LPC1768/LPC1769 UART Programming Tutorial for UART initialization function. I you face any problems please leave your comment below and I will try to help you out.
If you want to Retarget printf() for LPC176x in KEIL then check my other tutorial : Retarget/Redirect printf() and scanf() to uart in KEIL.