SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Printf Retargetting for Nano-Specs Cortex M0
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

Printf Retargetting for Nano-Specs Cortex M0

Andrew Irwin
Last updated: October 5, 2023 9:58 am
Andrew Irwin 6 Min Read
Share
SHARE

The Cortex-M0 is an ultra low power 32-bit ARM Cortex-M microcontroller targeted for various nano-scale embedded applications. Retargetting printf allows directing output from the standard C library printf function to a custom destination like UART, LCD display or other peripherals instead of default semihosting console. This enables printing messages directly from C programs running on Cortex-M0 without need for debugger connection.

Contents
Overview of Cortex-M0 ArchitectureRetargetting Printf to Output to UARTOptimizing Printf OutputRetargetting Printf to LCD DisplayConclusion

Overview of Cortex-M0 Architecture

The Cortex-M0 processor is a 32-bit RISC core optimized for low power consumption. Key features include:

  • 32-bit ARMv6-M architecture
  • Up to 48MHz clock speed
  • Single-cycle 32-bit multiplier
  • Nested Vectored Interrupt Controller
  • Wake up interrupt controller
  • Single precision hardware FPU (optional)

The Cortex-M0 integrates on-chip debug components like Embedded Trace Macrocell (ETM) and Micro Trace Buffer (MTB) for real-time tracing. It has a Memory Protection Unit (MPU) for memory access control and supports ARMv6 Thumb-2 instruction set for higher code density.

For I/O and peripherals, the Cortex-M0 includes upto 32 GPIO pins, SPI, I2C, UART, ADC and DAC. The debug interface uses Serial Wire Debug (SWD) and JTAG protocols. Overall, the Cortex-M0 microarchitecture provides an optimal balance of power, performance and cost for tiny battery-powered embedded devices.

Retargetting Printf to Output to UART

By default, the printf function in newlib C library for Cortex-M0 uses semihosting to send output to the debugger console. To retarget printf to UART serial port, we need to reimplement the low-level _write() function which is called by printf internally.

The steps are:

  1. Configure UART module for required baud rate, frame format and I/O pins.
  2. Implement _write() to send bytes to UART transmit buffer.
  3. Link the C library for your application with retargetted _write().

This will redirect any printf output to UART rather than semihosting. For example:


// UART initialization

void init_uart() {
   // Enable clock for UART module
   // Set baud rate, frame format
   // Configure TX and RX pins
   // Enable UART module
} 

// Retargetted _write()

int _write(int fd, char* ptr, int len) {
   // Load UART transmit buffer one byte at a time
   for(int i = 0; i < len; i++) {
      uart_send_byte(ptr[i]);
   }
   return len; 
}

int main() {
   init_uart(); // Initialize UART
   printf("Hello World!"); // Output over UART
}

Optimizing Printf Output

There are several techniques to optimize printf output on Cortex-M0 to reduce code size and improve performance:

  • Enable printf call optimization: Compiler flags like -ffunction-sections and –gc-sections can eliminate unused printf functionality.
  • Use reduced printf library: Lightweight printf versions like miniprintf have smaller code size.
  • Avoid float formatting: Omit any %f specifiers to avoid linking in floating point support.
  • Use printf buffering: Buffer characters locally before sending to UART to reduce interrupts.
  • Consider printf alternatives: Direct UART output functions can be more efficient for simple needs.

Let’s look at some examples of these optimizations:


// Optimized printf call

#include "printf.h" // Link only required printf functions

int main() {
   printf("Value: %d", var); // No unused formatting features
}

// Reduced library

#include "miniprintf.h" // Smaller printf implementation 

void main() {
   mprintf("Result: %d", result); // Optimized for embedded systems
}

// Avoid floats

int main() {
   uint32_t count = 42;
   printf("Count: %lu", count); // Use integer format specifiers  
}

// Printf buffering

#define PRINTF_BUF_SIZE 64

char printf_buf[PRINTF_BUF_SIZE]; 
int printf_idx;

int _write(int fd, char* ptr, int len) {
   // Add chars to local buffer
   // Transmit buffer when full
   // Clear buffer
}

// Alternative I/O

void uart_printf(char *str) {
   // Direct UART output
   while(*str) {
      uart_send_byte(*str++); 
   }
}

The optimal printf implementation depends on the application requirements. A combination of the above techniques allows efficient printf usage even on the memory and performance constrained Cortex-M0 MCU.

Retargetting Printf to LCD Display

For applications using LCD display, printf can also be retargetted to directly print messages on the LCD screen. This again requires implementing a custom _write() function.

For example with a character LCD:


#include "lcd.h" // LCD library  

int _write(int fd, char *ptr, int len) {
   for(int i = 0; i < len; i++) {
      lcd_print_char(ptr[i]); // Print each char
   }
   return len;
}

int main() {
   lcd_init(); // Initialize LCD
   printf("Cortex-M0 LCD!"); // Print on LCD
}

The LCD library handles lower level interfacing like sending data and commands over SPI or I2C bus to the LCD controller. The retargetted _write() routes the printf output to lcd_print_char() function to display each character on the LCD screen.

For graphics LCD, printf can be made to print text at specific coordinates by implementing lcd_print_char() accordingly in the LCD library interface.

Conclusion

Retargetting printf allows flexible redirection of standard output to fit the design needs of tiny Cortex-M0 systems. Choosing appropriate optimizations can ensure printf usage has minimal impact on performance and code size. The ability to retarget printf makes it easier to integrate printf debugging in the development workflow for Cortex-M0 projects.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Cortex-M0+ hangs on return
Next Article How to activate Eventrecorder together with RTX5 using Cortex-M0?
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

Tips for bare metal Cortex-M23 programming in uVision5

Programming Cortex-M23 microcontrollers in bare metal mode using uVision5 can…

7 Min Read

ARM Processor Full Form

ARM stands for 'Advanced RISC Machines'. It is a processor…

10 Min Read

What are Double-Precision (DP) floating-point instructions in Arm Cortex-M series?

Double-precision (DP) floating-point instructions refer to operations that process 64-bit…

7 Min Read

Arm Cortex M1 vs Microblaze

The Arm Cortex-M1 and the Xilinx Microblaze are both 32-bit…

9 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account