++i and i++ : what’s the difference?
Although the ++ and -- operators are well known, there are facets of their operation and implementation that are less familiar to many developers.
The Asimov Protocol
While the Internet is choke-full of explanations of basic data communication protocols, very little is said about the higher levels of packing, formatting, and exchanging information in a useful and practical way. This less-charted land is still fraught with strange problems, whose solutions may be found in strange places – in this example, a very short, 60 years old Science Fiction story.
Embedded Developer’s New Year’s Resolution
Use the holiday pause to turn vague intentions into a practical embedded skills plan for the coming year. This post lays out concrete resolutions: adopt modern software design practices, pick up a modern language like C++ or Rust, and learn when to use RTOS, cooperative schedulers, or Zephyr. Small, focused improvements will pay off across firmware projects.
My TDD Journey Started Dec 6, 1999
My story of learning Test-Driven Development started 23 years ago today. TDD has helped me exercise my code well before there is target hardware to run on. TDD helps me prevent defects. It can help you too.
More than just a pretty face - a good UI is essential
A user interface can make or break a device - determining its success in the marketplace. With careful design, the UI can make the product compelling and result in a high level of satisfaction from new and experienced users.
Lightweight C++ Error-Codes Handling
The traditional C++ approach to error handling tends to distinguish the happy path from the unhappy path. This makes handling errors hard (or at least boring) to write and hard to read. In this post, I present a technique based on chaining operations that merges the happy and the unhappy paths. Thanks to C++ template and inlining the proposed technique is lightweight and can be used proficiently for embedded software.
Flood Fill, or: The Joy of Resource Constraints
When transferred from the PC world to a microcontroller, a famous, tried-and-true graphics algorithm is no longer viable. The challenge of creating an alternative under severe resource constraints is an intriguing puzzle, the kind that keeps embedded development fun and interesting.
Embedded Systems Co-design for Object Recognition: A Synergistic Approach
Embedded systems co-design for object recognition is essential for real-time image analysis and environmental sensing across various sectors. This methodology harmonizes hardware and software to optimize efficiency and performance. It relies on hardware accelerators, customized neural network architectures, memory hierarchy optimization, and power management to achieve benefits like enhanced performance, lower latency, energy efficiency, real-time responsiveness, and resource optimization. While challenges exist, co-designed systems find applications in consumer electronics, smart cameras, industrial automation, healthcare, and autonomous vehicles, revolutionizing these industries. As technology advances, co-design will continue to shape the future of intelligent embedded systems, making the world safer and more efficient.
Software is free and can right any wrong
Software changes are so much easier than hardware modifications, so the temptation is always to take this approach to fixing bugs. This may not always be a good idea.
Modern C++ in embedded development: Static Classes
Static classes give embedded C++ developers a clear way to group module functions while preventing accidental instantiation. This post shows how to implement C#-style static classes in C++ by deleting the default constructor, then use templates and C++20 concepts to make firmware business logic platform independent and type safe. It also covers testability techniques, including mock wrappers for unavoidable static state.
C to C++: Bridging the Gap from C Structures to Classes
Jacob Beningo walks through a practical, beginner-friendly path from C structures to C++ classes for embedded systems, using an LED example to make the ideas concrete. You will see how function pointers in C approximate methods, how C++ structs and classes let you place methods with data, and how access specifiers and constructors improve encapsulation and initialization. This gives a low-risk way to start adopting C++ features.
Getting Started With Zephyr: Devicetree Bindings
This blog post shines some light on how devicetrees are used in The Zephyr Project. Specifically, we understand the mechanisms that enable us to use nodes in the devicetree in the C source files. We use a sample provided in the Zephyr repository itself and work our way through portions of the Zephyr codebase to get insight into the mechanisms that make this possible.
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?
C to C++: 5 Tips for Refactoring C Code into C++
The article titled "Simple Tips to Refactor C Code into C++: Improve Embedded Development" provides essential guidance for embedded developers transitioning from C to C++. The series covers fundamental details necessary for a seamless transition and emphasizes utilizing C++ as a better C rather than diving into complex language features. The article introduces five practical tips for refactoring C code into C++. Replace #define with constexpr and const: Discouraging the use of #define macros, the article advocates for safer alternatives like constexpr and const to improve type safety, debugging, namespaces, and compile-time computation. Use Namespaces: Demonstrating the benefits of organizing code into separate logical groupings through namespaces, the article explains how namespaces help avoid naming conflicts and improve code readability. Replace C-style Pointers with Smart Pointers and References: Emphasizing the significance of avoiding raw pointers, the article suggests replacing them with C++ smart pointers (unique_ptr, shared_ptr, weak_ptr) and using references
Introduction to Microcontrollers - Hello World
Mike Silva walks through the classic embedded hello world by blinking an LED on both an AVR and an STM32. The tutorial covers GPIO configuration, bit manipulation, simple software delay loops, and common pitfalls such as compiler optimizations that can remove empty delays unless you use volatile. Practical wiring tips and debugging advice with a scope make this an ideal first lab for embedded engineers.
Mutex vs. Semaphores – Part 2: The Mutex & Mutual Exclusion Problems
Mutexes tackle many semaphore pitfalls by enforcing ownership and pairing lock and unlock operations, making mutual exclusion safer in RTOS code. This post explains how ownership enables recursion, priority inheritance and death detection, and why mutexes do not automatically solve circular deadlock or non-cooperative access. Read on for practical protocols such as Priority Inheritance and Priority Ceiling and a brief note on monitors.
Patterns of Thinking: Metaphors in Programming
Why do some programming ideas click while others confuse engineers? This post shows that the metaphors you choose — from biological classification for inheritance to a “quantum” analogy for hierarchical state machines — shape how developers learn, design, and communicate. It also explains the surprising power of anthropomorphic (“naïve psychology”) language in team discussions and gives practical cautions about when metaphors help or mislead.
Hidden Gems from the Embedded Online Conference Archives - Part 2
A look back at a deep dive into the Mars Perseverance flight software from one of the technical leads at JPL.
Best Firmware Architecture Attributes
A poor firmware architecture makes future product variants and team work costly; Dr. Tayyar GUZEL outlines the attributes that avoid that fate. The post emphasizes modularity, low coupling, and encapsulation, and shows how a hardware abstraction layer, blackboard pattern, and CI-based unit testing improve extensibility, portability, and robustness. Practical tips include using setter/getter APIs, Doxygen for dependency graphs, and nightly regression to catch interface breaks early.
Dark Corners of C - The Comma Operator
Ever seen a line like if (!dry_run && ((stdout_closed = true), close_stream(stdout) != 0)) and wondered what that comma means? Stephen Friederichs unpacks the rarely-discussed C comma operator, shows a circular-buffer example where it seemed to simplify looping, then demonstrates how precedence and readability problems (and even MISRA C bans) make it dangerous in practice. Read on for practical uses and cautionary lessons.
Donald Knuth Is the Root of All Premature Optimization
Knuth's famous line "premature optimization is the root of all evil" has turned into a blunt rule on forums, Jason Sachs argues, and that overuse masks important nuance. He walks through concrete embedded examples, from dsPIC33E floating-point timings to an ROI analysis in the Kittens Game and a continuous optimization toy problem, to show when to measure, when to speculate, and why profilers can mislead.
Energia - program a TI MSP430 using Arduino sketches
Energia brings Arduino simplicity to TI's MSP430, turning a fiddly toolchain into a sketch-based workflow you already know. Lonnie Honeycutt walks through why the Launchpad is a great low-cost dev option, outlines supported MSP430 families and caveats like 3.3 volt I/O, and shows a Halloween LED jack-o-lantern sketch to prove how quickly you can get blinking LEDs.
Using XML to describe embedded devices (and speak to them)
Make embedded devices tell you what they can do. Martin Strubel shows how to use XML and XSLT with the DClib/netpp framework to describe hardware, map registers into abstract properties, and auto-generate compact C, documentation, and VHDL. The netpp property protocol then lets you probe, query, and control those properties over TCP, UDP, or other transports, simplifying test benches and multi-device families.
Important Programming Concepts (Even on Embedded Systems) Part III: Volatility
Jason Sachs takes volatility out of the basement and into practical embedded programming. He shows why data that can change outside your thread of control breaks assumptions, how the volatile qualifier in C/C++ and Java affects compiler and CPU behavior, and when to prefer shadow registers, locks, or proper concurrency libraries instead of ad hoc volatile usage.
C to C++: Bridging the Gap from C Structures to Classes
Jacob Beningo walks through a practical, beginner-friendly path from C structures to C++ classes for embedded systems, using an LED example to make the ideas concrete. You will see how function pointers in C approximate methods, how C++ structs and classes let you place methods with data, and how access specifiers and constructors improve encapsulation and initialization. This gives a low-risk way to start adopting C++ features.
Introduction to Microcontrollers - More Timers and Displays
Mike Silva walks through using a single hardware timer to create the illusion of parallel tasks, combining a millisecond tick, deadline checks, and a cyclic executive to run time-driven and event-driven work. He shows safe deadline code that handles timer rollover and ISR races, and provides practical STM32 examples including SysTick-driven delays, atomic GPIO BSRR writes for LCD control, and a button-driven display demo.
Linear Feedback Shift Registers for the Uninitiated, Part II: libgf2 and Primitive Polynomials
Jason Sachs digs into practical finite-field arithmetic for LFSRs, using his libgf2 Python library as the hands-on guide. He shows how to test whether a polynomial is primitive, why that matters for maximal-length sequences, and how the library implements addition, multiplication, exponentiation, and shifts over GF(2). The post is both a math refresher and a code walkthrough for engineers who want to compute with LFSRs instead of just talk about them.
Coding - Step 0: Setting Up a Development Environment
Stephen Friederichs walks through setting up a minimal C development environment without an IDE, focusing on Windows. He explains why learning command-line toolchains matters, recommends GCC and Make as a durable base, and gives step-by-step MinGW installation and PATH configuration plus editor suggestions. The guide gets you compiling with mingw32-make and gcc so you can move on to makefiles and project structure.
Linear Feedback Shift Registers for the Uninitiated, Part VII: LFSR Implementations, Idiomatic C, and Compiler Explorer
Jason Sachs takes LFSR theory back to real hardware, showing multiple C implementations and dsPIC33E assembly to squeeze cycles out of Galois LFSR updates. He digs into idiomatic C pitfalls like rotate idioms, demonstrates tricks using unions and 16/32-bit views, and shows when inline assembly with SL/RLC and conditional-skip instructions pays off. The article also uses Compiler Explorer and supplies an MPLAB X test harness for verification.
Mutex vs. Semaphore - Part 1
Most forum answers get the semaphore versus mutex debate wrong. This post traces semaphores back to Dijkstra and Scholten, explains the difference between binary and counting semaphores, and highlights runtime hazards such as accidental release, recursive and task-death deadlocks, priority inversion, and misuse as signals. Read if you want to avoid common concurrency pitfalls in RTOS code.























