Wednesday, 30 July 2014

Chan's xprintf on the LPC810

Continuing on from the last post, now that the Uart is working and outputting some text we can add much more functionality to the debugging output with the excellent pint sized micro printf library from Chan.

You can get this library from http://elm-chan.org/fsw/strf/xprintf.html. When you have downloaded it then extract the xprintf.c and place in your src folder and also extract xprintf.h and place it in the inc folder.

In order to integrate this file we will need two functions that get and put characters to the Uart (or indeed any other device such as a LCD). The putc function must return void and take an unsigned char as an argument while the getc function must return an unsigned char and takes no arguments. These functions are shown below for the LPC810:


void uart0putc(unsigned char c){
 /* Wait until we're ready to send */
  while (!(LPC_USART0->STAT & UART_STAT_TXRDY));
   LPC_USART0->TXDATA = c;
}

unsigned char uart0getc(){
 /* Wait until we're ready to receive */
 while (!(LPC_USART0->STAT & UART_STAT_RXRDY));
  return LPC_USART0->RXDATA;
}

Now in our main loop we tell xprintf about them by using the xdev_out and xdev_in macros:


/* Init Chan's Embedded String Functions (xprintf ect) */
 xdev_out(uart0putc);
 xdev_in(uart0getc);

These can also be used again to switch the output to another device assuming the corresponding getc and putc functions exist for it.

Putting this all together we get a new main.c which now allows us to investigate the default clock settings configured by CMSIS (note that the Uart setup code has changed slightly in order to fix it taking the wrong clock signal which will become apparent if the main clock divisor in not one).


#include "LPC8xx.h"
#include "xprintf.h"

#define BAUDRATE 57600
#define UART_CFG_DATALEN_8      (0x01 << 2)  /* UART 8 bit length mode */
#define UART_CFG_PARITY_NONE    (0x00 << 4)  /* No parity */
#define UART_CFG_STOPLEN_1      (0x00 << 6)  /* UART One Stop Bit Select */
#define UART_STAT_RXRDY         (0x01 << 0)  /* Receiver ready */
#define UART_STAT_TXRDY         (0x01 << 2)  /* Transmitter ready for data */
#define UART_CFG_ENABLE         (0x01 << 0)

void uart0putc(unsigned char c){
 /* Wait until we're ready to send */
  while (!(LPC_USART0->STAT & UART_STAT_TXRDY));
   LPC_USART0->TXDATA = c;
}

unsigned char uart0getc(){
 /* Wait until we're ready to receive */
 while (!(LPC_USART0->STAT & UART_STAT_RXRDY));
  return LPC_USART0->RXDATA;
}

short uart0PollChar() {
 if (!(LPC_USART0->STAT & UART_STAT_RXRDY))
  return -1;
 return LPC_USART0->RXDATA;
}

int main(void) {
 /* Calculate and set SystemCoreClock */
 SystemCoreClockUpdate();

 /* Init Chan's Embedded String Functions (xprintf ect) */
 xdev_out(uart0putc);
 xdev_in(uart0getc);

 /* Enable AHB clock to the Switch Matrix and UART0 */
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7) | (1 << 14);

 /* Configure Switch Matrix so that Pin2 = U0_TXD and Pin3 = U0_RXD */
 LPC_SWM->PINASSIGN0 = 0xffff0004UL;

 /* Set the UART clock divisor to 1  */
 LPC_SYSCON->UARTCLKDIV = 1; // note on reset the value is 0. i.e clock is disabled
 int MainClock = SystemCoreClock * LPC_SYSCON->SYSAHBCLKDIV;

 /* Configure UART0 baud rate */
 LPC_USART0->BRG = ((MainClock / LPC_SYSCON->UARTCLKDIV) >> 4) / BAUDRATE - 1;
 LPC_SYSCON->UARTFRGMULT = ((((MainClock / LPC_SYSCON->UARTCLKDIV) >> 4) * (0x100)) / (BAUDRATE * (LPC_USART0->BRG + 1))) - (0x100);
 LPC_SYSCON->UARTFRGDIV = 0xFF; //note on reset the value is 0

 /* Set UART0 to 8N1 and finally enable */
 LPC_USART0->CFG = UART_CFG_DATALEN_8 | UART_CFG_PARITY_NONE | UART_CFG_STOPLEN_1 | UART_CFG_ENABLE;

    // Enter an infinite loop testing for the '0' and '1' keys
    while(1) {
     switch( uart0PollChar() ){
      case '0':
          xprintf("System Core Clock is %d hz\n\r",SystemCoreClock);
      break;
      case '1':
          xprintf("Main clock select is %0x\n\r",LPC_SYSCON->MAINCLKSEL);
      break;
     }
    }
    return 0 ;
}










1 comment:

  1. Thanks for the clear and concise explanation!

    Works like a charm on STM32F103RTB6, Code Sourcery tools, and a simple uart getc and putc.

    Ahmet Onat

    ReplyDelete