How to use I2C devices in (Apache) NuttX: Scanning for Devices
Hands-on guide to scanning I2C peripherals on NuttX using a Raspberry Pi Pico, showing how the RTOS exposes i2c master instances and the i2ctool. The article walks through where the RP2040 I2C driver lives, how to enable I2C0 in menuconfig, build and flash nuttx, and run the i2c dev command to probe the bus. Verify sensors like BMP280 or SSD1306 before registering drivers.
When a Mongoose met a MicroPython, part I
This is more a framework than an actual application, with it you can integrate MicroPython and Cesanta's Mongoose.
Mongoose runs when called by MicroPython and is able to run Python functions as callbacks for the events you decide in your event handler. The code is completely written in C, except for the example Python callback functions, of course. To try it, you can just build this example on a Linux machine, and, with just a small tweak, you can also run it on any ESP32 board.
Using (Apache) NuttX Buttons Subsystem
You do not need to poke GPIO registers to read switches in NuttX, the OS provides a Buttons subsystem that delivers named events, multi-button support, and optional software debouncing. This post walks through wiring two breadboard buttons on a Raspberry Pi Pico, enabling the input and buttons drivers via menuconfig, building nuttx.uf2, and testing the buttons over the usbnsh serial console. It highlights why a simple hardware debounce is still a good idea.
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.
Using (Apache) NuttX USERLED Subsystem
Controlling an LED with raw GPIO works, but NuttX's USERLED subsystem makes it cleaner and portable. This post walks through enabling the LED driver in menuconfig, mapping the RaspberryPi Pico LED in the board files, and using the /dev/userleds device with printf to set up to 32 LEDs with a single write. It finishes with a hands-on challenge to expand the setup to eight LEDs on a breadboard.
Getting Started With Zephyr: Bluetooth Low Energy
In this blog post, I show how to enable BLE support in a Zephyr application. First, I show the necessary configuration options in Kconfig. Then, I show how to use the Zephyr functions and macros to create a custom service and characteristic for a contrived application.
Using GPIO in (Apache) NuttX RTOS
Blinking an LED is the embedded Hello World, and this tutorial walks through using GPIOs on NuttX running on a Raspberry Pi Pico. It shows how to enable the GPIO driver and example in menuconfig, build and flash the nuttx.uf2, and use NSH gpio device files to read and write pins. The post also explains polling versus interrupt-driven inputs and the pull-up/edge setup needed for button interrupts.
Optimizing Real-Time Operating Systems for Efficient Edge Devices
Edge devices need real-time responsiveness but run on tight CPU, memory, and power budgets. This post breaks down what an RTOS brings to the edge: deterministic task scheduling, lean memory management, protocol support, and modular scalability, then tackles common challenges like synchronization and security. Read it for practical best practices on scheduling and protocols plus a look at future trends such as edge AI integration and interoperable infrastructure.
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.
Getting Started With Zephyr: Writing Data to EEPROM
In this blog post, I show how to implement a Zephyr application to interact with EEPROM. I show how the Zephyr device driver model allows application writers to be free of the underlying implementation details. Unfortunately, the application didn't work as expected, and I'm still troubleshooting the cause.
Practical CRCs for Embedded Systems
Stephen Friederichs shows a practical way to get correct CRC code quickly by using PyCRC to generate C implementations, then verifying them on the desktop and an AVR ATMega328P. The post walks through the common generation algorithms, how to self-test with the standard "123456789" check value, and a real timing comparison that exposes the speed versus memory tradeoffs for 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.
Designing Communication Protocols, Practical Aspects
When your MCU must talk to a PC or smartphone, a clear protocol saves time and headaches. This post gives practical guidance for fast bring-up: how to structure a compact header, keep payloads byte-aligned and debug-friendly, and reserve bits for future use. It also covers CRCs for integrity, timeout and retry strategies for resynchronisation, and the simple start code trick that makes debugging easier.
Getting Started With Zephyr: Saving Data To Files
In this blog post, I show how to implement a Zephyr application to mount a microSD card, create a new file on the microSD card, and write data to it. The lessons learned from such an application can be helpful for devices out in the field that need to write data to off-board memory periodically, especially in cases where Internet access may be sporadic.
OOKLONE: a cheap RF 433.92MHz OOK frame cloner
Fabien Le Mentec built a pocket device that listens to and clones 433.92MHz OOK frames, automating the tedious reverse engineering of cheap wireless outlets. The prototype uses a Moteino with an RFM69 to sample demodulated OOK data, stores pulse durations in SRAM, and replays frames; the code and hardware notes are available on GitHub along with limitations and next steps.
Using a RTLSDR dongle to validate NRF905 configuration
Fabien Le Mentec wanted to be sure his nRF905 radio link was configured correctly before trusting it across seven floors. Instead of guessing, he used a cheap RTLSDR dongle, rtl_fm, and a small custom decoder to inspect the 433 MHz traffic directly. The result was a practical way to validate packet framing, Manchester coding, and signal strength without relying only on the radio module’s own feedback.
Working With ESP-C3-32S-Kit Dev Board
This hands-on guide walks through setting up the ESP-C3-32S-Kit with ESP-IDF, from installing the toolchain to flashing and monitoring a hello-world example. It shows JTAG debugging with OpenOCD and GDB, how to use the NimBLE BLE stack for peripheral and central roles, and how to capture and filter BLE traffic with a Nordic sniffer and Wireshark so you can inspect pairing and connection behavior.
Linear Feedback Shift Registers for the Uninitiated, Part XIV: Gold Codes
Gold codes solve a practical spread-spectrum problem, sharing one PRBS across many transmitters eventually runs into ugly synchronization and correlation issues. Jason Sachs walks through why shifted copies of a single LFSR sequence are not enough, then shows how preferred pairs of m-sequences create a family of Gold codes with bounded cross-correlation. The post wraps with Python experiments and a UART DSSS demo that decodes multiple overlapping messages cleanly.
Surprising Linux Real Time Scheduler Behavior
An embedded Linux data acquisition project ran into puzzling UART latency whenever heavy UI animations ran. Moving all app threads to SCHED_FIFO helped but did not eliminate delays. After reading about kernel worker thread interactions, Matthew moved the UI back to the normal scheduler and the jitter vanished. The post highlights an unexpected kernel level priority inversion risk and a pragmatic workaround.
How to use I2C devices in (Apache) NuttX: Scanning for Devices
Hands-on guide to scanning I2C peripherals on NuttX using a Raspberry Pi Pico, showing how the RTOS exposes i2c master instances and the i2ctool. The article walks through where the RP2040 I2C driver lives, how to enable I2C0 in menuconfig, build and flash nuttx, and run the i2c dev command to probe the bus. Verify sensors like BMP280 or SSD1306 before registering drivers.
Practical CRCs for Embedded Systems
Stephen Friederichs shows a practical way to get correct CRC code quickly by using PyCRC to generate C implementations, then verifying them on the desktop and an AVR ATMega328P. The post walks through the common generation algorithms, how to self-test with the standard "123456789" check value, and a real timing comparison that exposes the speed versus memory tradeoffs for embedded systems.
Using a RTLSDR dongle to validate NRF905 configuration
Fabien Le Mentec wanted to be sure his nRF905 radio link was configured correctly before trusting it across seven floors. Instead of guessing, he used a cheap RTLSDR dongle, rtl_fm, and a small custom decoder to inspect the 433 MHz traffic directly. The result was a practical way to validate packet framing, Manchester coding, and signal strength without relying only on the radio module’s own feedback.
OOKLONE: a cheap RF 433.92MHz OOK frame cloner
Fabien Le Mentec built a pocket device that listens to and clones 433.92MHz OOK frames, automating the tedious reverse engineering of cheap wireless outlets. The prototype uses a Moteino with an RFM69 to sample demodulated OOK data, stores pulse durations in SRAM, and replays frames; the code and hardware notes are available on GitHub along with limitations and next steps.
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.
Real-time clocks: Does anybody really know what time it is?
Most RTC chips still expose calendar fields rather than seconds-since-epoch, forcing embedded engineers to write ugly conversion code. Jason Sachs makes the case for offset encoding, subseconds, and an explicit snapshot feature to simplify interval math, raise precision, and avoid rare timing bugs. Read this practical take on RTC trade-offs and a short wishlist for chip makers.
How to use I2C devices in (Apache) NuttX: Adding support for an I2C device in your board
You can add an I2C sensor to NuttX with a few file edits, menuconfig tweaks, and a standard build-and-flash cycle. This guide shows how the BMP280 barometer was integrated into the Raspberry Pi Pico bringup by copying and adapting an existing board driver, wiring the sensor to I2C0, enabling the BMP280 option in menuconfig, and compiling and flashing the resulting nuttx.uf2. It includes exact wiring and build tips.
Working With ESP-C3-32S-Kit Dev Board
This hands-on guide walks through setting up the ESP-C3-32S-Kit with ESP-IDF, from installing the toolchain to flashing and monitoring a hello-world example. It shows JTAG debugging with OpenOCD and GDB, how to use the NimBLE BLE stack for peripheral and central roles, and how to capture and filter BLE traffic with a Nordic sniffer and Wireshark so you can inspect pairing and connection behavior.
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.
Interfacing LINUX with microcontrollers
Fabien presents a practical pattern: put Internet- facing logic on a Linux board and keep time-critical I/O on a microcontroller, using a Raspberry Pi and a Teensy 3.0. He introduces MASL, a reusable userspace library that hides master-slave details and shows how to use userspace SPI, sysfs GPIO and epoll for programming, reset and event-driven signaling with working code examples.
How to Give Persistent Names To USB-Serial Devices on Ubuntu 14.04
When your dock reshuffles ttyUSB assignments, Tayyar shows how to bind USB-serial devices to persistent names on Ubuntu 14.04. The post walks through using dmesg and udevadm to locate unique attributes like KERNELS and ATTRS{serial}, creating /etc/udev/rules.d entries with NAME and SYMLINK, and applying rules with udevadm trigger. It includes common pitfalls and quick fixes to get minicom talking to the right port.



















