Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Printf support for MSP430 CCSTUDIO compiler

From Texas Instruments Wiki
Jump to: navigation, search

The following short guide how to work with printf() like functions with CCSTUDIO v5.x MSP430 compiler.

Compiling default printf() like functions

How the default printf() works - Behind the scene

The standard output of the printf() function is the debug console on CCS IDE. When the default printf() function is used, basically the compiler/debugger will add a breakpoint right after the code converting the strings finishes, and then pull the strings out the memory via JTAG and display it on the debug console of the IDE. This will of course cause the program slower.

Choosing the printf() compiler support setting

The CGT (Code Generation Tools - i.e. the compiler) v4.0 which comes with CCS v5.1 has three possible settings for the printf() support:

  • full: Supports all format specifiers. This is the default.
  • nofloat: Excludes support for printing floating point values. Supports all format specifiers except %f, %F, %g, %G, %e, and %E.
  • minimal: Supports the printing of integer, char, or string values without width or precision flags. Specifically, only the %%, %d, %o, %c, %s, and %x format specifiers are supported

The following figure shows how to change the setting in CCS v5.1:

Setting printf support.PNG


The following figure shows the setting in CCS v7. Note the location of the setting is now under Compiler->Advanced Options->Language Options. Also the default setting is now minimal.

Setting printf support ccsv7.png

Enabling C I/O use

To work with printf() function, it is also necessary to enable the C I/O use setting as shown in the following figure:

Enable cio function use.PNG

Increasing the heap memory size

The printf() library function requires high amount of allocated heap memory. For a single printf() code such as follows:

printf("Hello world %d!\n", counter++);

it requires around 300 bytes of memory heap. The following figure shows how to change the heap size on CCS v5.1:

Increase heap size.PNG

Debugging printf() function

Per default the standard output of printf() function is the debug console on the CCSTUDIO. Therefore before starting debugging the code, it is necessary to make sure the debug console of the project is activated (Select "View" -> "Console"). The following figure shows how the printf() function print the output to the debug console.

Running printf debug.PNG

Rerouting printf() output

Sometime it is desired to reroute the standard output to other I/O medium, for example UART interface. This can be done by overriding the fputc() and fputs() functions as described below.

Overriding the fputc() and fputs() functions

The easiest way to reroute the printf() output is by overriding the fputc() and fputs of the default RTS (Run-Time-Support) library functions. To do this, simply define both functions in the source code:

int fputc(int _c, register FILE *_fp);
int fputs(const char *_ptr, register FILE *_fp);

The following example code is done for MSP430F5438A on the MSP-EXP430F5438A with USB-UART connection on USCI_A1 module:

#include "msp430x54xA.h"
#include <stdio.h>
#include <string.h>

#define UART_PRINTF

#ifdef UART_PRINTF
int fputc(int _c, register FILE *_fp);
int fputs(const char *_ptr, register FILE *_fp);
#endif

void main(void)
{
  unsigned int counter=0;
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  // initialize clock module
  P1DIR |= 0x01;                            // P1.0 output
  UCSCTL3 |= SELREF__REFOCLK;
  UCSCTL4 |= SELA__REFOCLK;

  // initialize Timer_A module
  TA1CCTL0 = CCIE;                          // CCR0 interrupt enabled
  TA1CCR0 = 32768;
  TA1CTL = TASSEL__ACLK + MC__UP + TACLR;   // ACLK, up mode, clear TAR

#ifdef UART_PRINTF
  // initialize USCI module
  P5SEL |= BIT6 + BIT7;                     // P5.6,7 = USCI_A1 TXD/RXD
  UCA1CTL1 |= UCSWRST;                      // **Put state machine in reset**
  UCA1CTL1 |= UCSSEL__ACLK;                 // AMCLK
  UCA1BR0 = 27;                             // 32,768kHz 1200 (see User's Guide)
  UCA1BR1 = 0;                              // 32,768kHz 1200
  UCA1MCTL = UCBRS_2;                       // 32,768kHz 1200
  UCA1CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
#endif

  while(1)
  {
    __bis_SR_register(LPM3_bits+GIE);       // Enter LPM3, enable interrupts
    printf("Hello world %d!\r\n", counter++);
  }
}

// Timer A0 interrupt service routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
  P1OUT ^= 0x01;                            // Toggle P1.0
  __bic_SR_register_on_exit(LPM3_bits);
}

#ifdef UART_PRINTF
int fputc(int _c, register FILE *_fp)
{
  while(!(UCA1IFG&UCTXIFG));
  UCA1TXBUF = (unsigned char) _c;

  return((unsigned char)_c);
}

int fputs(const char *_ptr, register FILE *_fp)
{
  unsigned int i, len;

  len = strlen(_ptr);

  for(i=0 ; i<len ; i++)
  {
    while(!(UCA1IFG&UCTXIFG));
    UCA1TXBUF = (unsigned char) _ptr[i];
  }

  return len;
}
#endif

The output can then be captured by using Hyperterminal-like software program:

Uart printf output teraterm.PNG