A guide to bare-metal programming for the Internet of Things (IoT) – Arm Community blogs

Embedded programming these days usually implies the use of development frameworks, which make development faster and easier. For example, Arm Keil comes with an integrated IDE, debugger, and a set of software packages that provide an RTOS, drivers, middleware like TCP/IP stack, and libraries like mbedTLS (SSL/TLS) or lvgl (graphics). Cube IDE from STMicroelectronics provides similar capabilities, and MCUXpresso from NXP, TI CCS, Microchip’s MPLAB, and so on.

When developers start a project in one of those frameworks, they develop an application code on top of various software layers. Often, a developer may choose to bypass all these layers, and develop code that directly communicates with the hardware. That is often referred as bare-metal programming. The motivation of doing so can be one of the following:

  • To have a full control and understanding of every bit of the developed application, which often decreases the maintenance burden
  • To achieve the maximum performance and flexibility from the target hardware. while initially more time consuming that can pay off greatly as the project moves along
  • To avoid spending time to fix and debug an underlying software layer, especially if they are poorly tested, documented, and buggy

Developing on a bare-metal could be done without an IDE, just using any editor and an Arm GCC compiler. Also it can be done using an IDE, for example using Arm Keil. In any case, a developer needs to understand several key concepts:

  • How memory is organized
  • How peripherals work
  • The layout of the generated binary code
  • How linker script is used to generate a necessary layout
  • Vector table, interrupts, and weak symbols
  • CMSIS headers: Arm core and vendor peripheral

These are covered in the bare-metal programming guide written by Sergey Lyubka.

The guide starts at the very foundation, and assumes no prior embedded development experience. Only the knowledge of the C programming language is required. The guide is written as a step-by-step walk-through over all necessary topics – memory map organization, peripheral I/O, and so on. It begins with a classic LED blink, through a more advanced topic of timers, interrupts, and finally to an embedded web server that exposes an interactive device dashboard. The guide ends by covering crucial topics of automated software build and automated test on a target hardware.

Sergey Lyubka is an Engineering Director at Cesanta. Cesanta is an Arm partner, and develops the following products:

  • https://mongoose.ws: An open-source HTTP/MQTT/Websocket network library
  • https://vcon.io: A remote firmware update and serial monitor framework

Latest articles

Related articles