GZM Embedded Systems
Back to blog
// article Firmware bench

How far can Zephyr RTOS go with 16 KB of RAM?

· Jorge Guzman
ZephyrRTOSPIC32CMModbusCortex-M0
PIC32CM MC00 Curiosity Nano running the demo, with the IHM shield showing a Modbus screen and a USB-RS485 adapter

In this article we explore running Zephyr RTOS on the PIC32CM MC00 Curiosity Nano devkit from Microchip. This is not meant to be an introduction to Zephyr RTOS, for that, you can watch the webinars Zephyr RTOS: First Steps and Zephyr RTOS: Building a Complete IoT Application to understand how the build, debug and flashing environment is set up.

Introduction

At the June 2026 Embarcados event, the Embedded Systems & IoT Seminar, I received a board with the PIC32CM1216 microcontroller straight from Rogério Moreira, of Microchip. It is an ARM Cortex-M0 with just 128 KB of Flash and 16 KB of RAM.

Early in my career I had already worked on maintaining code for a product built around a dsPIC33FJ256 (256 KB Flash and 30 KB of RAM). I remember struggling a lot to cut down memory usage. Every byte, function, .c/.h file or misaligned struct counted during the build.

Times have changed, though, and I got curious about how far I could go with only 16 KB of RAM and still build a real application on this devkit, with the added challenge of doing it on Zephyr RTOS as well.

I chose Zephyr RTOS because it already had support for the PIC32CM family and for the sensors, the Modbus protocol and the display I wanted to use in this demo. This devkit has no official Zephyr support, so I had to create an out-of-tree custom board with all the DTS and overlay files for our demo.

The demo

For this article we built a simple monitoring-and-control demo over Modbus. The idea was to bring together, in a single application, the main peripherals and services you typically find in a real embedded product: sensors, a display, I/O expansion, data storage in Flash and industrial communication, all running on Zephyr RTOS.

The board acts as a Modbus RTU device (unit id 1, 115200 8N1), exposed through a USB-to-RS485 adapter. Over that bus you can read the sensors, follow the system state and control the outputs (LEDs) remotely. Locally, an OLED display shows operating information and four keys allow direct interaction with the application.

This demo includes the following features:

  • Modbus RTU
  • VL53L0X distance sensor
  • SHT3x temperature and humidity sensor
  • SSD1306 OLED display
  • Shield with an MCP23008 I²C expander
    • 4 LEDs
    • 4 keys
  • Internal RTC
  • Watchdog
  • NVS storage using the last 16 KB of internal Flash
    • Saves the LED state when the board powers up
    • Saves how many times the key has been pressed
  • Shell terminal

Electrical connections:

PinFunctionPeripheral
PA00UART TXConsole shell
PA01UART RX
PA08I²C SDASHT3x, VL53L0X, SSD1306, MCP23008
PA09I²C SCL
PA14UART TXModbus RS-485
PA15UART RXModbus RS-485
PA10GPIO (output)RS-485 DE/RE
PA02GPIO (output)IHM shield RESET
PA03GPIO (input)MCP23008 INT
PA22GPIO (input)SW0 button
PA23GPIO (output)On-board LED0

Shield with display, 4 keys and 4 LEDs Shield with display, 4 keys and 4 LEDs

Shield with the MCP23008 I²C expander Shield with the MCP23008

The board assembled for the demo The board assembled for the demo

Flashing and debugging

The devkit already ships with an on-board programmer, which lets us both flash and debug the firmware directly from VSCode using the Cortex-Debug plugin.

To speed up the workflow, we automated the whole process inside VSCode itself:

  • We created task runners that wrap the west commands (build, flash and the GDB server), removing the need to type commands into the terminal on every cycle.
  • We set up a debug launch that starts the GDB server (via pyOCD) and connects Cortex-Debug to the board, allowing step-by-step debugging, variable inspection and breakpoints right in the editor. With that, flashing and debugging the application comes down to a single click, making the development cycle much faster and more productive.

The task runners created in VSCode Task runners created

You can find the source code at: https://github.com/JorgeGzm/PIC32-ArtigoZephyr

To run this demo we used:

  • Ubuntu 24.04
  • Zephyr SDK 1.0.1
  • Zephyr Project v4.4.0

Modbus software

To test and validate the Modbus communication, we built a Python application with a graphical interface to monitor and control the device: reading the sensors, showing device information and the number of times the board’s key was pressed, turning the board’s LED on and off, displaying the application uptime, the current RTC value, and running an automatic routine that syncs the RTC date and time with the computer’s clock.

The Python Modbus monitor built for the demo Python software built for the demo

Conclusion

Over the past few years I have moved to working with more powerful microcontrollers. In the last product I worked on, for example, we used an STM32H7 with 2 MB of internal Flash and 1 MB of internal RAM, plus 32 MB of external SDRAM and 16 MB of external NOR Flash.

It was surprising to see everything that was possible with a microcontroller that offers few pins and memory resources considered “limited” (128 KB of Flash and 16 KB of RAM). The demo was able to run a full Zephyr RTOS application while consuming about 105 KB of Flash (80%) and 13.6 KB of RAM (83%).

[223/223] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:      105276 B       128 KB     80.32%
             RAM:       13624 B        16 KB     83.15%
        IDT_LIST:           0 B        32 KB      0.00%

This demonstration was a reminder of how much times have changed. Code quality, driver abstraction levels and software architecture for embedded systems have all evolved significantly.

As a result, it has become viable to consider more modest microcontrollers, such as the PIC32CM1216, in product development. Combined with Zephyr RTOS, it gains access to a mature ecosystem that supports a wide range of sensors, communication protocols and ready-to-use features, reducing development effort and speeding up the creation of embedded solutions.

Originally published

This article was first published in Portuguese on the Embarcados portal.

Read the original on Embarcados