SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: How to Learn MCU Programming with Makefiles and an ARM Toolchain?
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

How to Learn MCU Programming with Makefiles and an ARM Toolchain?

David Moore
Last updated: September 15, 2023 11:50 am
David Moore 8 Min Read
Share
SHARE

Learning to program microcontroller units (MCUs) using makefiles and an ARM toolchain provides a powerful and flexible workflow for embedded development. Makefiles allow you to automate the build process while the ARM toolchain gives you access to the robust ARM Cortex architecture. With some setup and practice, you’ll be able to compile, flash, and debug your programs quickly and efficiently.

Contents
Understanding the ComponentsChoosing an MCUInstalling the ARM ToolchainConfiguring a MakefileFlashing the ExecutableDebugging with GDBIntegrating Library CodeTips for Effective Embedded ProgrammingExpanding Your Skills

Understanding the Components

Before diving into the details, let’s review the key components that make up this embedded development environment:

  • MCU – The microcontroller unit itself. This is the chip with the ARM processor that runs your code. Examples include STM32, NXP Kinetis, Atmel SAM, etc.
  • Toolchain – The compiler, assembler, linker and other tools that convert your C/C++ code into an executable that can run on the target MCU.
  • Makefile – A file that defines rules for building your executable from source code using the toolchain.
  • Flashing – The process of getting your executable program onto the MCU’s flash memory.
  • Debugging – Tools and techniques for running your program in a debug environment and finding bugs.

Choosing an MCU

The first step is choosing an MCU to work with. Some popular options include:

  • STM32 – Cortex-M3/M4 chips made by STMicroelectronics. Very wide selection of affordable development boards.
  • NXP Kinetis – Cortex-M4F chips made by NXP. Also with lots of dev board options.
  • Atmel SAM – Cortex-M0+ chips made by Atmel/Microchip. Used in Arduino Zero/MKR boards.

Look at development boards from Adafruit, SparkFun, STM, and other vendors to find one that fits your needs and budget. The STM32 Discovery and Nucleo boards are a good starting point. Pick an MCU that supports ARM’s CMSIS libraries for simpler software development.

Installing the ARM Toolchain

You’ll need a toolchain compatible with your chosen MCU architecture. For Cortex-M0/M3/M4 parts, the GNU Arm Embedded Toolchain from ARM is a good option. You can download pre-built binaries for Windows, Mac and Linux. Make sure to get the version that matches the instruction set for your MCU (ARMv6-M, ARMv7-M, etc).

Add the bin directory for the toolchain to your system PATH so you can easily invoke the compiler, assembler and other tools from the command line. On Linux/Mac: export PATH=$PATH:/opt/gnu-arm-embedded/bin

The key tools you’ll use are:

  • arm-none-eabi-gcc – The compiler that converts C/C++ code to assembly
  • arm-none-eabi-as – The assembler that converts assembly to machine code
  • arm-none-eabi-ld – The linker that combines object files into an executable
  • arm-none-eabi-gdb – The GNU debugger for testing on the device or simulator

Configuring a Makefile

A makefile contains rules for building your executable from source files. This is more convenient than invoking the tools manually each time. Makefiles support variables, targets, automatic dependency checking, and handy features for embedded development like flashing and debugging targets.

Start with a simple makefile like this: # Toolchain path TOOLCHAIN=/opt/gnu-arm-embedded # Build target TARGET=program # Source files SRC=main.c utils.c # Compiler flags CFLAGS=-mcpu=cortex-m3 -mthumb -O1 -g3 -Wall -std=gnu99 # Linker flags LDFLAGS=-T../ld/stm32f1.ld -Wl,-Map=program.map # Rule to build executable $(TARGET).elf: $(SRC) arm-none-eabi-gcc $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) # Rules for converting to hex/bin $(TARGET).hex: $(TARGET).elf arm-none-eabi-objcopy -O ihex $(TARGET).elf $(TARGET).hex $(TARGET).bin: $(TARGET).elf arm-none-eabi-objcopy -O binary $(TARGET).elf $(TARGET).bin

This makefile builds an executable called program.elf from main.c and utils.c, converting it to Intel hex and binary formats for flashing. Customize the flags for your MCU architecture, source files, and desired output filenames.

Flashing the Executable

To get your program running on the MCU, you’ll need to flash the executable. This writes the binary file to the chip’s memory. Flashing requires an external debugger/programmer hardware interface. Some options are:

  • On-board debug circuitry like ST-LINK found on Discovery/Nucleo boards
  • Dedicated JTAG/SWD adapters that connect to debug ports
  • USB-to-serial adapters paired with the UART bootloader on the chip

For example, to flash using OpenOCD and an ST-LINK debugger: openocd -f board/st_nucleo_f3.cfg telnet localhost 4444 program program.elf verify reset

This connects OpenOCD to the debugger, uploads the program, resets the board, and starts execution. The makefile can automate this process so flashing is a single command.

Debugging with GDB

To test and debug code on the device, the GNU debugger (GDB) is quite useful. It allows stepping through code, setting breakpoints, watching variables, etc. To use the Arm GDB that comes with the toolchain: arm-none-eabi-gdb program.elf target remote localhost:3333 load …use step, next, break, watch, etc

This connects to a GDB server running on port 3333 (started by OpenOCD) and loads the program. Add commands like break main and run to control execution. Making effective use of GDB takes some practice but unlocks powerful debugging abilities.

Integrating Library Code

Most projects will utilize some external library code. This may include the MCU vendor’s HAL drivers, CMSIS libraries for ARM Cortex, middleware stacks like FreeRTOS, or other open source libraries. To use these in your project:

  1. Add include paths to the libraries in CFLAGS
  2. Link any necessary pre-built library files into the executable using LDFLAGS
  3. Call the appropriate initialization code early on
  4. Use clean and consistent style when invoking library APIs

Most libraries come with examples and documentation to help get started. Take time to understand the architecture and concepts used by the library code to make the most effective use of it.

Tips for Effective Embedded Programming

Here are some key tips to keep in mind when writing code for MCUs:

  • Use a modular, layered architecture for better code organization
  • Minimize dynamic memory allocation due to limited heap space
  • Implement power management to reduce energy consumption
  • Handle peripherals at a low level for best performance
  • Write reentrant and thread-safe code when using an RTOS
  • Enable optimizations in the compiler and verify they work correctly
  • Handle errors and timeouts robustly to avoid crashing

Following best practices from the outset will prevent many issues and lead to more stable and reusable firmware code.

Expanding Your Skills

To become an expert embedded programmer using ARM MCUs, keep learning and expanding your skills in areas like:

  • Peripheral interfacing – I2C, SPI, USB, CAN, etc.
  • Real-time operating systems and multithreading
  • Low power techniques and wireless communication
  • Toolchain and compiler internals and usage
  • Bootloaders, firmware upgrades, and robust field updates
  • Testing and validation methodologies

There are great resources available through ARM, open source projects, MCU vendor communities, and books/training material. Immerse yourself and keep practicing – experience is the best teacher!

With the core skills of makefiles, the ARM toolchain, and solid embedded programming principles, you’ll be ready to take on any Cortex-M based project.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article How many cycles does an ARM Cortex M0 use to multiply floats?
Next Article What is the Voltage of ARM 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

Loading the EXC_RETURN Value for Cortex-M Context Switching

Context switching between threads or tasks on Cortex-M processors involves…

4 Min Read

What Is the Difference Between Arm Cortex A and M?

Arm processors are designed by Arm Holdings and licensed to…

6 Min Read

ARM Processor Architecture

ARM processors are based on the ARM architecture developed by…

7 Min Read

What is EK TM4C123GXL?

The EK TM4C123GXL is a low-cost evaluation board based on…

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

Sign in to your account