# FreeRTOS vs Zephyr: How to Choose an RTOS for a Connected Sensor

FreeRTOS vs Zephyr compared on one connected sensor: drivers, scheduling, build system, memory, and OTA updates. See how the hardware decides the RTOS.

Written by [Nico Tzovanis](https://www.flux.ai/nico)

Published Nov 2026 - 11 min read

![FreeRTOS vs Zephyr: How to Choose an RTOS for a Connected Sensor](https://www.flux.ai/p/assets/blogs/freertos-vs-zephyr/main.webp)

Flux, the AI hardware engineer, writes the firmware for this kind of device on either RTOS. Tell Flux to use FreeRTOS or Zephyr, and it sets up the tasks, queues, timers, and interrupts, maps each pin and peripheral to the nets in your schematic, builds the firmware, and reports flash and RAM use. It also sets up signed OTA updates with two firmware slots and rollback. The firmware stays in step with the schematic, the PCB, and the enclosure in the same project.

[Start Free Trial](https://www.flux.ai/signup)

FreeRTOS vs Zephyr comes down to how much of the system you want the RTOS to supply. FreeRTOS is a small, MIT-licensed scheduler kernel: tasks, queues, semaphores, and software timers. You add it to the vendor SDK of your microcontroller, and the SDK supplies the drivers and the radio stack. Zephyr is a complete RTOS from the Linux Foundation, under the Apache 2.0 license. It brings its own drivers, devicetree hardware description, Bluetooth and IP networking, a build system, and an OTA bootloader.

So the hardware decides. If the chip vendor's SDK is built on FreeRTOS, use FreeRTOS. If the chip vendor's SDK is built on Zephyr, or the product needs Bluetooth, networking, and signed updates across more than one board, use Zephyr. Below, one connected sensor is worked through both ways so you can see where each choice comes from.

## The example: a battery-powered environmental sensor

The device is a wall-mounted sensor for a building-monitoring product:

-   A BME280 temperature, humidity, and pressure sensor on I2C, read once every 30 seconds.
-   An accelerometer with an interrupt pin that wakes the device when someone removes it from the wall.
-   A Bluetooth Low Energy link to a gateway. A second product variant uses Wi-Fi.
-   Two AA cells, with a battery-life target of two years.
-   Signed over-the-air (OTA) updates with rollback, because nobody opens 2,000 enclosures to reflash them.
-   A molded enclosure with a PCB antenna that needs a keep-out zone at the board edge.

The firmware has the same three jobs on either RTOS:

1.  **Sensor task:** wake on a timer, read the BME280, and put the reading in a queue.
2.  **Radio task:** take readings from the queue and send them, then let the radio sleep.
3.  **Tamper interrupt:** wake on the accelerometer pin and send an alarm at once.

## FreeRTOS vs Zephyr at a glance

| Area | FreeRTOS | Zephyr |
| --- | --- | --- |
| **Scope** | Scheduler kernel. Libraries such as FreeRTOS-Plus-TCP and coreMQTT are separate add-ons. | Kernel plus drivers, sensor API, Bluetooth host and controller, IP stack, file systems, logging, shell. |
| **License** | MIT | Apache 2.0 |
| **Drivers** | From the vendor SDK (ESP-IDF, STM32Cube, MCUXpresso) or your own code. | In-tree drivers behind common APIs, selected by devicetree. |
| **Hardware description** | C headers and the vendor's configuration tool. | Devicetree files and overlays for each board. |
| **Configuration** | `FreeRTOSConfig.h` | Kconfig (`prj.conf`) |
| **Build system** | Whatever the SDK uses: CMake, Make, or an IDE project. | CMake with the `west` meta-tool. |
| **Flash footprint** | Kernel alone is typically 6 to 12 KB. | Larger, because the image includes the drivers and subsystems you enable. |
| **OTA updates** | Vendor OTA component or an add-on library. | MCUboot bootloader with signed images and two slots, integrated in the build. |
| **Vendor SDKs built on it** | Espressif ESP-IDF, many STM32 and NXP examples. | Nordic nRF Connect SDK, plus upstream support for many STM32, NXP, and ESP32 parts. |

## The sensor on FreeRTOS

With FreeRTOS, you write the task structure yourself and call the vendor SDK for the I2C driver and the radio. The sensor task uses `vTaskDelayUntil()` so the 30-second period does not drift, and it hands each reading to the radio task through a queue:

```
typedef struct { bool tamper; int32_t temp_mc; uint32_t hum_mpct; uint32_t press_pa; } reading_t;
static QueueHandle_t readings;

static void sensor_task(void *arg) {
    TickType_t last = xTaskGetTickCount();
    for (;;) {
        reading_t r = { .tamper = false };
        if (bme280_read(&r) == 0) {          /* your driver, on the SDK's I2C API */
            xQueueSend(readings, &r, 0);
        }
        vTaskDelayUntil(&last, pdMS_TO_TICKS(30000));
    }
}

static void radio_task(void *arg) {
    reading_t r;
    for (;;) {
        if (xQueueReceive(readings, &r, portMAX_DELAY) == pdPASS) {
            radio_send_reading(&r);            /* vendor BLE or Wi-Fi stack */
        }
    }
}

void app_main(void) {
    readings = xQueueCreate(8, sizeof(reading_t));
    xTaskCreate(sensor_task, "sensor", 2048, NULL, 5, NULL);
    xTaskCreate(radio_task,  "radio",  4096, NULL, 4, NULL);
}
```

The tamper interrupt puts a message with `tamper = true` at the front of the same queue with `xQueueSendToFrontFromISR()`. The radio task wakes and sends the alarm before the next reading. For low power, you enable tickless idle with `configUSE_TICKLESS_IDLE` so the core sleeps between ticks, and the vendor port puts the chip in its deepest sleep mode that keeps the timer running.

This is the shortest path on the Wi-Fi variant. The ESP32 family's ESP-IDF already runs FreeRTOS, its Wi-Fi stack and OTA component run as FreeRTOS tasks, and the code above is what an ESP-IDF application looks like. The cost: the BME280 driver, the pin assignments, and the update flow are your code, tied to one vendor's SDK. If the next product uses a different chip, you rewrite those parts.

## The sensor on Zephyr

With Zephyr, you describe the hardware and enable the features, and the RTOS supplies the driver. The BME280 goes in a devicetree overlay for the board:

```
&i2c0 {
    status = "okay";
    bme280: bme280@76 {
        compatible = "bosch,bme280";
        reg = <0x76>;
    };
};
```

The features go in `prj.conf`:

```
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_PM=y
```

The bootloader goes in `sysbuild.conf`:

```
SB_CONFIG_BOOTLOADER_MCUBOOT=y
```

The application reads the sensor through the generic sensor API, so the same code works with another supported sensor:

```
K_MSGQ_DEFINE(readings, sizeof(struct sensor_value) * 3, 8, 4);
static const struct device *bme = DEVICE_DT_GET(DT_NODELABEL(bme280));

static void sensor_thread(void *p1, void *p2, void *p3) {
    struct sensor_value v[3];
    for (;;) {
        if (sensor_sample_fetch(bme) == 0) {
            sensor_channel_get(bme, SENSOR_CHAN_AMBIENT_TEMP, &v[0]);
            sensor_channel_get(bme, SENSOR_CHAN_HUMIDITY, &v[1]);
            sensor_channel_get(bme, SENSOR_CHAN_PRESS, &v[2]);
            k_msgq_put(&readings, v, K_NO_WAIT);
        }
        k_sleep(K_SECONDS(30));
    }
}
K_THREAD_DEFINE(sensor_tid, 1024, sensor_thread, NULL, NULL, NULL, 5, 0, 0);
```

The radio thread takes values from `readings` and updates a GATT characteristic. When every thread sleeps, the power management subsystem puts the SoC in its low-power state. With sysbuild, `west build --sysbuild` builds MCUboot with the application, signs the application image, and puts two image slots in the board's flash partitions. After an update, the new image confirms itself with `boot_write_img_confirmed()`. If it does not, MCUboot goes back to the previous image at the next reset.

This is the shortest path on the BLE variant with a Nordic nRF52840 or nRF54 part. The nRF Connect SDK is built on Zephyr, so the Bluetooth stack, power management, and update flow come from the same tree. The cost is the learning curve: devicetree, Kconfig, and `west` are three new tools for an engineer who knows only a vendor IDE, and the image is larger than a bare FreeRTOS kernel.

## Compare memory with a real build, not a datasheet

The FreeRTOS kernel is small, but the kernel is not the firmware. A connected sensor also carries a radio stack, a TLS or BLE security layer, a sensor driver, and a bootloader. On both RTOSes, the radio stack usually uses most of the flash and RAM. Compare the two choices on the same features:

-   Build both versions for the target with BLE or Wi-Fi, the sensor, low power, and OTA enabled.
-   Read the flash and RAM totals from the linker map, and list the largest symbols.
-   Check the result against the part's flash after you reserve the second OTA slot. Two slots halve the space for the application.
-   Check the stack size of each task under the worst case, for example during a BLE connection and a sensor read at the same time.

Zephyr gives you `west build -t rom_report` and `ram_report` for this. On FreeRTOS, read the map file from the SDK build and check stack use with `uxTaskGetStackHighWaterMark()`.

## How the hardware picks the RTOS

| If your hardware is | Choose | Why |
| --- | --- | --- |
| **ESP32-class Wi-Fi sensor** | FreeRTOS | ESP-IDF, its Wi-Fi stack, and its OTA component already run on FreeRTOS. |
| **Nordic nRF BLE sensor** | Zephyr | The nRF Connect SDK, its Bluetooth stack, and MCUboot are built on Zephyr. |
| **STM32 with an existing STM32Cube codebase** | FreeRTOS | Keep the HAL drivers and the team's code. Add FreeRTOS through the vendor middleware. |
| **One product line on several MCU families** | Zephyr | Devicetree and the common driver APIs keep the application code the same across boards. |
| **Small MCU with tight flash and no radio** | FreeRTOS | The kernel alone fits where a full RTOS image does not. |

## How Flux writes the firmware for either RTOS

The RTOS choice depends on the schematic, and the schematic depends on the enclosure, the antenna, and the battery. In Flux, all of them are in one project, and you ask the agent for the firmware with the hardware it runs on:

-   **Tasks, queues, and timers on either RTOS.** Tell Flux to set up FreeRTOS or Zephyr, or bare-metal timer interrupts, with the task priorities and data flow you need. It writes the firmware starter document with the microcontroller, framework, build system, and libraries.
-   **A pin map from the schematic.** Flux maps the I2C bus, the interrupt pin, and the boot pins from the schematic nets, and names each firmware define after its net. When you move a pin, it updates the map and the source.
-   **Real builds and memory reports.** Flux compiles for ARM, RISC-V, ESP32-class, nRF, RP2040, AVR, and STM32 targets. It returns `.elf`, `.bin`, `.hex`, and `.map` files, reports flash and RAM use, and lists the largest symbols. That is the memory comparison above, in minutes.
-   **Host unit tests before the board arrives.** Flux runs tests for the sensor conversion and the message format without hardware, and writes a CI workflow that builds and tests every change.
-   **OTA with rollback.** Flux adds a bootloader with two firmware slots, signed images, rollback, and the update flow in the app or the cloud.
-   **Battery life from the power budget.** Flux sets the sleep mode, the wake sources, and the duty cycle, then estimates battery life from the power budget.
-   **Mechanical values in firmware.** Flux reads the sensor position and the enclosure dimensions from the mechanical model and adds them as named firmware constants. When the enclosure changes, it updates them.

Prompts like these do the work in a Flux project:

-   “Use Zephyr for this nRF52840 sensor. Read the BME280 every 30 seconds, send it over BLE, wake on the accelerometer interrupt, and add MCUboot OTA with rollback.”
-   “Set up FreeRTOS tasks on this ESP32-S3 board for sensor sampling and Wi-Fi, with the sensor readings in a queue. Build it and report flash and RAM use.”
-   “Estimate battery life on two AA cells for this firmware. Show the active time, sleep current, and wake sources.”
-   “Move the antenna keep-out to the top edge of the enclosure, update the board outline, and keep the firmware pin map in step with the new schematic.”

Without Flux, an RTOS evaluation takes a week or two: one engineer ports the sensor to two SDKs, another changes the board, and the enclosure waits. In Flux, the agent builds both versions, reports the numbers, and keeps the schematic, PCB, enclosure, and firmware in the same project in a few hours. Read more about [electronics design in Flux](https://www.flux.ai/p/eda) and the [firmware docs](https://docs.flux.ai/reference/firmware). For the chip choice that comes before the RTOS, read [STM32 vs ESP32](https://www.flux.ai/p/blog/stm32-vs-esp32).

Open a project and tell Flux what the sensor must do. It writes the firmware for the board and the enclosure you design with it.

[Start Free Trial](https://www.flux.ai/signup)

## FAQs

### What is the difference between FreeRTOS and Zephyr?

FreeRTOS is a small scheduler kernel that you add to a vendor SDK, which supplies the drivers and the radio stack. Zephyr is a complete RTOS with its own drivers, devicetree hardware description, Kconfig configuration, Bluetooth and IP networking, a CMake and west build system, and MCUboot for OTA updates.

### Is Zephyr better than FreeRTOS?

Neither is better for every device. Zephyr is the faster path for a Bluetooth sensor on a Nordic part, or a product line on several MCU families. FreeRTOS is the faster path on an ESP32 with ESP-IDF, on an STM32 with an existing STM32Cube codebase, or on a small MCU with tight flash.

### Does Zephyr use more memory than FreeRTOS?

The FreeRTOS kernel alone is typically 6 to 12 KB of flash, and a Zephyr image includes the drivers and subsystems you enable, so a minimal Zephyr build is larger. In a connected sensor, the radio stack and the bootloader use most of the memory on both. Build both versions with the same features and compare the linker map.

### Can I run FreeRTOS or Zephyr on an ESP32?

Yes. ESP-IDF, the Espressif SDK, runs on FreeRTOS. Zephyr also supports many ESP32 parts upstream. For a Wi-Fi product that uses the ESP-IDF Wi-Fi stack and OTA component, FreeRTOS is the shorter path.

### Can Flux write FreeRTOS and Zephyr firmware?

Yes. Tell Flux which RTOS to use and how the tasks work together. Flux sets up tasks, queues, timers, and interrupts on FreeRTOS or Zephyr, maps the pins from your schematic, builds the firmware, and reports flash and RAM use. It can also add OTA updates with rollback and estimate battery life from the power budget.

## About the author

[Nico Tzovanis](https://www.flux.ai/nico)

Nico is a professional electronics and PCB design engineer at Flux. Find him on Flux [@nico](https://www.flux.ai/nico)

Let’s start building

Build your big idea together with Flux. All you need to do is describe what you want to make, or what problem you want to solve. Flux will work with you to make it a reality.

![Close-up photo of a PCB made with Flux, with an ESP32 module, buttons, and a microSD slot.](https://www.flux.ai/p/assets/blogs/miscellaneous/sidebar-cta-pcb.webp) [Try it Free](https://www.flux.ai/signup)

## Related Content

[

![Teal line art of a desktop monitor with a tangled circuit board, a mouse and a cursor on the left, and a clean exploded eight-layer circuit board with length-matched traces on the right, on a dark background](https://www.flux.ai/p/assets/blogs/ai-computer-use-altium-pcb-routing/main.webp)

### AI Moving a Mouse in Altium Is the Worst Way to Design a PCB

7 Min Read](https://www.flux.ai/p/blog/ai-computer-use-altium-pcb-routing)[

![Line illustration: a rigid-flex circuit board above its fabrication drawing sheet, with a drill pattern, an exploded layer stackup, and the enclosure shell for the board](https://www.flux.ai/p/assets/blogs/pcb-fabrication-drawing/main.webp)

### Your PCB Fabrication Drawing Now Comes From the Design

6 Min Read](https://www.flux.ai/p/blog/pcb-fabrication-drawing)[

![a space-themed background with stars and a floating astronaut helmet to the left. Large, bold text reads '6 Prompting Tips to Get the Most Out of Copilot', indicating a focus on maximizing the use of a digital assistant or tool.](https://www.flux.ai/p/assets/blogs/copilot-6-prompting-tips/main.webp)

### 6 Prompting Tips to Get the Most Out of Copilot

6 Min Read](https://www.flux.ai/p/blog/6-prompting-tips-to-get-the-most-out-of-copilot)[

![5 Pro Tips for Better Routing with AI Auto-Layout](https://www.flux.ai/p/assets/blogs/5-tips-for-ai-auto-layout/main.webp)

### 5 Pro Tips for Better Routing with AI Auto-Layout

5 Min Read](https://www.flux.ai/p/blog/5-pro-tips-for-better-routing-with-ai-auto-layout)[

![Agri.iO revolutionizes farming with Flux](https://www.flux.ai/p/assets/blogs/case-study-agri-io/main.webp)

### Agri.iO revolutionizes farming with Flux

4 Min Read](https://www.flux.ai/p/blog/agri-io-revolutionizes-farming-with-flux)[

![Isometric teal line drawing on a dark background: a circuit board and its open enclosure on a workbench, with connected checkpoints that lead from a plan to a finished device](https://www.flux.ai/p/assets/blogs/ai-adoption-hardware-teams-customer-success/main.webp)

### AI Adoption Is a People Problem: How Flux Customer Success Gets Hardware Teams to ROI

7 Min Read](https://www.flux.ai/p/blog/ai-adoption-hardware-teams-customer-success)

See All (6)

## Let’s start building.

Let’s build your idea together. All you need to do is describe what you want to make, or what problem you want to solve. Flux will work with you to make it a reality.

[Try it Free](https://www.flux.ai/signup)

 ![Close-up of a Flux-designed printed circuit board](https://www.flux.ai/p/assets/homepage-v2/mission-visual.webp)
