top of page

Embedded Firmware Development: Process, Tools and Common Pitfalls

Writer: Srihari Maddula
Srihari Maddula
Nov 28, 2023
4 min read

Updated: 11 hours ago

Firmware is the code that runs directly on a microcontroller or system-on-chip. It sits in flash, starts when power is applied, and drives the hardware: reading sensors, switching outputs, talking over buses and radios. Some products run it on an RTOS. Many run it bare-metal.

What sets it apart is the environment. RAM is often counted in kilobytes. Timing is part of correctness, so a late answer can be as bad as a wrong one. There is usually no screen, no filesystem and no easy way to attach a debugger once the product is installed. A bug that reaches the field can mean a site visit or a recall.

pcb designing

How firmware differs from application software

  • It runs close to the hardware. Firmware configures clocks, interrupts, DMA and peripherals directly. Application software normally goes through an operating system.

  • Timing is deterministic. Many tasks have hard deadlines, so worst-case behaviour matters more than average speed.

  • Resources are fixed. Flash, RAM and power are set by the bill of materials. You cannot add memory after launch.

  • Lifetimes are long. Firmware ships in devices that run for years, so update and recovery paths are part of the design.

The development process

1. Requirements and hardware constraints. Start from the product: interfaces, timing budgets, power budget, expected lifetime and certification needs. Choose the MCU against those numbers (flash, RAM, peripherals, low-power modes), not the reverse. The output is a short spec that hardware and firmware engineers both sign off.

2. Architecture. A common layering is startup code and linker script, a hardware abstraction layer (HAL) with drivers, middleware such as an RTOS or protocol stacks, and then application logic. Keeping hardware access behind a thin HAL lets you run the logic on a PC.

3. Implementation. C is still the default, C++ is used for structure, and Rust is growing in new projects. Prefer static allocation to the heap, keep interrupt handlers short, and follow a coding standard such as MISRA C where safety matters. Enable a watchdog and decide what the system does when it fires.

4. Testing. Test in layers. Run unit tests on the host (Unity or CppUTest) and static analysis (cppcheck, clang-tidy). Then run integration tests on the target, ideally in a hardware-in-the-loop rig. Measure timing with a scope or logic analyzer, and measure current in every power state.

5. Programming and release. Images are flashed over SWD or JTAG during development and with a production programmer in manufacturing. Use a bootloader, sign release images, embed a version and build ID, and lock debug access on production units.

6. Maintenance. Plan for field updates from the start. Over-the-air updates, a crash log that survives resets, and a safe fallback image decide how painful a field bug will be.

secure boot mechanisms

Common challenges and what helps

Challenge

What helps

Little access to target hardware early on

A HAL and host-side tests, plus evaluation boards while prototypes are scarce

Tight flash and RAM

Check the linker map and size output on every build; avoid heap allocation

Timing bugs

Keep ISRs short, defer work to tasks, measure latency with a GPIO toggle and a scope

Many MCU or board variants

One HAL interface and a CI build for every target

Security

Secure boot, signed images, debug readout protection, no secrets in the source

| Challenge | What helps | |---|---| | Little access to target hardware early on | A HAL and host-side tests, plus evaluation boards while prototypes are scarce | | Tight flash and RAM | Check the linker map and size output on every build; avoid heap allocation | | Timing bugs | Keep ISRs short, defer work to tasks, measure latency with a GPIO toggle and a scope | | Many MCU or board variants | One HAL interface and a CI build for every target | | Security | Secure boot, signed images, debug readout protection, no secrets in the source |

Choosing a language

  • C is the common choice for efficiency, toolchain support and direct hardware control.

  • C++ suits larger systems that benefit from modularity, as long as you avoid exceptions and heavy dynamic allocation.

  • Rust offers memory safety and is a good fit for new code where the target is supported.

  • Assembly is for startup code and a few timing-critical routines.

  • Python is useful around the firmware: test automation, factory tools and log analysis.

firmware developer

Tools worth knowing

  • Compilers: GCC (arm-none-eabi) and LLVM/Clang.

  • IDEs: VS Code, Eclipse-based vendor IDEs, Keil µVision, IAR and MPLAB X.

  • Debug probes: Segger J-Link and ST-Link over SWD or JTAG.

  • Bench instruments: oscilloscope, logic analyzer, protocol decoders for I²C, SPI, UART and CAN, and a power analyzer.

  • RTOS and frameworks: FreeRTOS and Zephyr.

  • Automation: CI with a containerized toolchain so every commit builds and tests.

Where this leaves a firmware engineer

The job is wider than writing C. It covers working with the hardware team on pin and peripheral choices, debugging on the bench, designing for security and updates, and supporting the product through its life. A solid base in electronics or computer science, plus practice on real hardware, matters more than any single language.

EurthTech develops firmware together with hardware design and system testing for industrial and IoT products. To talk about a project, write to connect@eurthtech.com or see www.eurthtech.com/solutions.

Comments


EurthTech delivers AI-powered embedded systems, IoT product engineering, and smart infrastructure solutions to transform cities, enterprises, and industries with innovation and precision.

Factory:

Plot No: 41,
ALEAP Industrial Estate, Suramapalli,
Vijayawada,

India - 521212.

  • Linkedin
  • Twitter
  • Youtube
  • Facebook
  • Instagram

 

© 2025 by Eurth Techtronics Pvt Ltd.

 

Development Center:

4th Floor, Krishna towers, 100 Feet Rd, Madhapur, Hyderabad, Telangana 500081

Menu

|

Accesibility Statement

bottom of page