Tips for using printf

From Texas Instruments Embedded Processors Wiki

Jump to: navigation, search

Contents

General info on printf()

This first part is intended to cover generic printf() information as it pertains to standard C, not specific to TI or embedded processors.

The first thing to note is that a call to printf() is closely related to the call fprintf() that one would use for doing file I/O. Specifically, printf() is like calling fprintf(stdout,...). In other words, printf is writing to the stream/file stdout.

Buffering of data

There are 3 different methods that can be used for buffering data when using the C I/O functions:

  • Fully buffered (_IOFBF): The buffer is flushed when it is full.
  • Line buffered (_IOLBF): The buffer is flushed when an end-of-line character ('\n') is encountered. The stdout stream used by printf() is created as a line buffered stream.
  • Not buffered (_IONBF): There is no buffering, i.e. each character is output immediately. The stderr stream is not buffered.

How to use setvbuf()

Good info on setvbuf() can be found in this wikipedia article. To set/change buffering for a given stream you would make a call to setvbuf(). For example:

setvbuf(stdout, NULL, _IONBF, 0); // turn off buffering for stdout

If one wanted to avoid having memory dynamically allocated by printf() then one could call setvbuf() to avoid it. For example:

uint8_t static_array[20];
setvbuf(stdout, static_array, _IOLBF, sizeof(static_array));

Info pertaining to embedded processors

Introduction

Many people as they get started on a new processor are inclined to begin with a "hello world" project. Surprisingly, there are a lot of pitfalls in starting one of these projects! This section is intended to surface many of those common pitfalls.

Warning about using printf

The printf command has a major impact on real-time systems:

  • There is significant performance overhead when doing the string formatting, e.g. converting an int to ascii for display.
  • The actual display of data over JTAG will momentarily halt the processor, which causes major real-time problems.

How to use printf in a project

  • Step 1: Make sure you include the appropriate header file, e.g. stdio.h, when calling printf. Failure to do so will cause the compiler to incorrectly guess how the arguments should be placed on the stack/registers since printf takes a variable number of arguments.
  • Step 2: By default printf() requires space on the heap (i.e. it invokes malloc "under the hood"). [Note: When no heap is configured, printf silently fails, and no output is visible in CCS - specifically the "Stdout" window in CCS will not open.] Use setvbuf() in order to get printf to use a statically defined buffer or else make sure you have allocated enough heap space (minimum 1K words or 0x400):
    • For projects not using DSP/BIOS: Under Project -> Build Options -> Linker -> Heap Size(-heap) enter the heap size, e.g. 0x400
    • If using DSP/BIOS:
      • Open your tcf file in the configuration tool.
      • Right click on Memory Section Manager and go to Properties.
      • Uncheck the "No Dynamic Heaps" box if it is not already unchecked. Click OK to exit the dialog.
      • Right-click on the memory section where you would like to create a heap, e.g. DDR2 and go to Properties.
      • Click the "Create a heap in this memory" box and enter the size. Click OK to exit the dialog.
      • Right-click once again on Memory Section Manager and set the "segment for malloc/free" to a valid section, e.g. DDR2.
    • C2000 Users: Make sure that in linker command file you have properly allocated the .sysmem and .esysmem sections to valid memory of sufficient size. The heap gets allocated to the .sysmem section.
  • Step 3: Make sure you have allocated the .cio section to valid memory:
This section is used by the C I/O functions and needs to be allocated to valid data memory (PAGE 1) in the linker command file. It usually requires ~0x120 words but may be dependent on device family.
  • Step 4: Make sure you allow setting of CIO breakpoints at load:
Under Option -> Customize -> Program/Project Load -> Program make sure the Do Not Set CIO Breakpoint At Load is not checked. If this is checked, you will not see any CIO activity.
Note: The downside of allowing the setting of CIO break-points (unchecked box) is that when debugging from Flash, it will use one hardware break-point. You may need to move C I/O code to RAM to avoid this issue.
  • Step 5: Always flush your C I/O buffers before a breakpoint. The easiest way to do this is using a \n statement (new line) to terminate your printf. Since the stdout stream is line buffered this will cause the buffer to be flushed.
Alternatively, at the end of your code, or before setting a breakpoint, make sure you flush the buffers so when you hit the breakpoint, the last printf or fprintf() message is output:
fflush(stdout); // This will flush any pending printf output
fflush(FilePointer); // This will flush any pending fprintf output

Other General Tips

  • If you are accessing a binary file, be sure to open the file with a binary mode such as "rb". For more see the last paragraph of this discussion on binary data handling.

Using printf() to output to a UART

  1. Get/write a device driver for outputting data from the UART (or whatever interface you choose).
  2. Write the low-level functions as described in Chapter 8.2 The C I/O Functions of the C Compiler User's Guide.
  3. Call add_device() to add your functions to the stream table (i.e. in addition to stdin, stdout, stderr).
  4. Open your stream.
  5. Redirect your stream to stdout using freopen.
  6. Specify what buffering is to be used for your stream by calling setvbuf.

For example:

ret_val = add_device("uart", _SSA, uart_open, uart_close, uart_read, uart_write, uart_lseek, uart_unlink, uart_rename);
fid = fopen("uart","w");
freopen("uart:", "w", stdout); // redirect stdout to uart
setvbuf(stdout, NULL, _IONBF, 0); // turn off buffering for stdout
printf("Hello world!\r\n");

Additional Tips for DSP/BIOS Users

DSP/BIOS users should also read more about calling RTS functions from BIOS.

DSP/BIOS users have an alternative called LOG_printf(). See this FAQ for information on switching from printf() to LOG_printf().


For technical support please post your questions at http://e2e.ti.com. Please post only comments about the article Tips for using printf here.
Leave a Comment

Comments

Comments on Tips for using printf


Praetor said ...

Please add a section with instructions on how to do setup the heap in BIOS6 which does not use tcf files

--Praetor 11:55, 24 November 2009 (CST)

Personal tools