Can an RTOS be really real-time?
Real-Time Operating Systems are meant for real-time applications. But with conventional shared-state concurrency and blocking, can you honestly know the worst-case execution time of an RTOS thread?
Memory Mapped I/O in C
Interacting with memory mapped device registers is at the base of all embedded development. Let's explore what tools the C language - standard of the industry - provide the developer with to face this task.
Cortex-M Exception Handling (Part 1)
This article describes how Cortex-M processors handle interrupts and, more generally, exceptions, a concept that plays a central role in the design and implementation of most embedded systems.
Creating a GPIO HAL and Driver in C
Creating a GPIO Hardware Abstraction Layer (HAL) in C allows for flexible microcontroller interfacing, overcoming the challenge of variability across silicon vendors. This method involves reviewing datasheets, identifying features, designing interfaces, and iterative development, as detailed in the "Reusable Firmware" process. A simplified approach prioritizes essential functions like initialization and read/write operations, showcased through a minimal interface example. The post also highlights the use of AI to expedite HAL generation. A detailed GPIO HAL version is provided, featuring extended capabilities and facilitating driver connection through direct assignments or wrappers. The significance of a configuration table for adaptable peripheral setup is emphasized. Ultimately, the blog illustrates the ease and scalability of developing a GPIO HAL and driver in C, promoting hardware-independent and extensible code for various interfaces, such as SPI, I2C, PWM, and timers, underscoring the abstraction benefits.
C to C++: Templates and Generics – Supercharging Type Flexibility
"C to C++: Templates and Generics – Supercharging Type Flexibility" illuminates the rigidity of C when managing multiple types and the confusion of code replication or macro complexity. In contrast, C++ offers templates, acting as type-agnostic blueprints for classes and functions, which allows for the creation of versatile and reusable code without redundancy. By using templates, developers can define operations like add once and apply them to any data type, simplifying codebases significantly. Generics further this concept, enabling a single code structure to handle diverse data types efficiently—a boon for embedded systems where operations must be performed on varying data, yet code efficiency is critical due to resource limitations. The blog walks through practical applications, showcasing how templates streamline processes and ensure type safety with static_assert, all while weighing the pros and cons of their use in embedded software, advocating for careful practice to harness their full potential.
Linear Feedback Shift Registers for the Uninitiated, Part I: Ex-Pralite Monks and Finite Fields
Later there will be, I hope, some people who will find it to their advantage to decipher all this mess. — Évariste Galois, May 29, 1832 I was going to call this short series of articles “LFSRs for Dummies”, but...
Help, My Serial Data Has Been Framed: How To Handle Packets When All You Have Are Streams
Today we're going to talk about data framing and something called COBS, which will make your life easier the next time you use serial communications on an embedded system -- but first, here's a quiz: Quick Diversion, Part I: Which of the...
The volatile keyword
Although the C keyword volatile is very useful in embedded applications, care is needed to use it correctly and vigilance is required to ensure its correct implementation by compilers.
Analog-to-Digital Confusion: Pitfalls of Driving an ADC
Imagine the following scenario:You're a successful engineer (sounds nice, doesn't it!) working on a project with three or four circuit boards. More than even you can handle, so you give one of them over to your coworker Wayne to design....
How to Deploy Local LLMs for Embedded Software Development: Hardware Selection and Trade-offs
In this post, I map the LLM terminology covered in the previous post to real hardware decisions. I walk through memory sizing depending on different parameters, the core trade-off between discrete GPU VRAM and unified memory. Finally, I describe a workflow to help you identify which setup is right for your workflow.
My device crashed in the field. How do I figure out why?
Embedded systems often crash in the field, leaving developers with nothing more than a disconnected device and zero visibility into the cause. When traditional debugging is impossible, coredumps provide the essential post-mortem data required to reconstruct the system’s final moments. Learn how to configure Zephyr RTOS and the Spotflow SDK to automatically capture, store, and analyze critical crash information—including stack traces, CPU registers, and variable states—remotely. Mastering this workflow allows you to diagnose and resolve elusive firmware faults long after a device has rebooted, transforming your remote debugging capabilities.
Can Spotflow Solve Remote Debugging for Embedded Systems?
Debugging complex embedded systems in the field requires more than just local logs and JTAG probes. To maintain visibility across a scaling fleet, engineers need robust cloud-based observability. This guide explores the integration of Spotflow with the Zephyr RTOS on an NXP FRDM-MCXN947 board. Learn how to configure your development workspace, navigate common Python versioning hurdles, and establish a secure MQTT connection. Follow along as we bridge the gap between local firmware execution and remote telemetry, setting the foundation for true fleet-wide monitoring and proactive system management.
C Is for Complacency: Friendship Is Not Transitive, but What About Module Dependencies?
In the C programming language, if module A depends on module B, and module B depends on module C, does this mean module A depends on module C? Well, it depends....
Ten Little Algorithms, Part 8: Miller-Rabin Primality Test (and Living with Uncertainty)
Part 8 of the Ten Little Algorithms series: A look at the Miller-Rabin primality test, along with Pollard's rho algorithm for factoring, and some perspectives on very low levels of uncertainty.
How to Deploy Local LLMs for Embedded Software Development: Terminology and Motivation
In this blog post series, I walk you through creating a fully local, offline AI pipeline. In this first post, I outline the motivation and relevant terminology that are important before we dive into hardware selection and implementation of the pipeline.
Your architecture was decided before you opened the schematic
Engineering teams often treat requirements as a simple feature checklist, but they actually hold the blueprint for your software architecture. By analyzing constraints collectively rather than in isolation, you can define critical architectural patterns—such as task scheduling and abstraction levels—long before the first schematic is drawn. This proactive approach eliminates wasted complexity, reduces development time, and allows software needs to inform hardware choices early in the cycle. Discover how to shift your design mindset to build lean, purposeful systems that align perfectly with business objectives from day one.
My Lowest-Friction Embedded Project Was Also the One That Shouldn't Have Worked
Ralph Hempel recounts the LEGO Powered Up rework that, against every external constraint, turned into the lowest-friction embedded development environment of his career. The talk connects the specific tools and habits that made it work to five soft qualities that any struggling team can start building with small experiments, not big-bang process changes.
Beyond the Packet: Designing Reliable Serial Communication for Embedded Systems
Serial communication between microcontrollers sounds simple until the protocol quietly breaks your system. Prabo Semasinghe walks through the design steps for building a robust communication framework: packet structure, error detection, acknowledgment handling, state machine design, and the failure-mode testing that actually proves it works.
The Data Problem Slowing Down Semiconductor Adoption
Silicon is shipping faster than ever. Devices are not. The 18 to 36 month gap between a chip becoming available and a product reaching the market is now almost entirely software integration, written by hand, rewritten for every operating system and every safety target. The fix isn't more engineers or better tools. It's better data, and a shared way to describe how chips actually behave.
Basic Sensors for an Autonomous Vehicle
The following are a few basic sensors that can be used to help an autonomous vehicle navigate its environment.The faster the vehicle is traveling, the faster the sensor must be processed. Moving vehicles could knock something over or...
Cutting Through the Confusion with ARM Cortex-M Interrupt Priorities
The insanely popular ARM Cortex-M processor offers very versatile interrupt priority management, but unfortunately, the multiple priority numbering conventions used in managing the interrupt priorities are often counter-intuitive, inconsistent,...
Choosing a Microcontroller for Your Vehicle
There are many things to take into consideration when choosing a microcontroller or microprocessor for your autonomous vehicle.VoltageSome processors run on 5V and others use 3.3V. Be sure to check the documentation before you buy. ...
From Embedded Software Engineer to Musician
In his first blog post on EmbeddedRelated, Jean Labrosse, the author of the uC/OS series and founder of Micrium, discusses his transition from an embedded software engineer to a musician.
Cracking the (embedded) Coding Interview
You never forget the day you land your first job. The thrill of receiving that call from your recruiter to tell you that you bagged your dream role! The relief when you finally see the offer letter you’ve been working towards for...
You Don't Need an RTOS (Part 1)
In this first article, we'll compare our two contenders, the superloop and the RTOS. We'll define a few terms that help us describe exactly what functions a scheduler does and why an RTOS can help make certain systems work that wouldn't with a superloop. By the end of this article, you'll be able to: - Measure or calculate the deadlines, periods, and worst-case execution times for each task in your system, - Determine, using either a response-time analysis or a utilization test, if that set of tasks is schedulable using either a superloop or an RTOS, and - Assign RTOS task priorities optimally.
Skills For Embedded Systems Software Developers
Contents: Introduction Do I Need To Be An Expert In Everything? How Much Time Do I need? Do I need A College Degree? Why Is The List So Big? Do I Really Need All These Things? The Skills Software Hardware Software Development...
Memory Mapped I/O in C
Interacting with memory mapped device registers is at the base of all embedded development. Let's explore what tools the C language - standard of the industry - provide the developer with to face this task.
How to Estimate Encoder Velocity Without Making Stupid Mistakes: Part II (Tracking Loops and PLLs)
Yeeehah! Finally we're ready to tackle some more clever ways to figure out the velocity of a position encoder. In part I, we looked at the basics of velocity estimation. Then in my last article, I talked a little about what's necessary to...







