Features Documentation Examples Repository Blog Contact

Hello World

This example demonstrates the simplest possible application written for CMRX RTOS. By the end of this tutorial, you’ll understand how to create a basic application and integrate it with the CMRX kernel.

What You’ll Learn

  • How to create a basic CMRX application
  • Understanding processes and threads in CMRX
  • How to build and integrate applications with the kernel
  • Basic project structure and configuration

Understanding CMRX Applications

In CMRX, all user code is organized into applications (also called processes - these terms mean the same thing). Think of an application as a container that holds:

  • Your code (functions)
  • Data (variables)
  • Threads (execution contexts)

The key advantage is memory isolation: each application gets its own protected memory space that other applications cannot access. This makes your system more robust against bugs and security issues.

Basic Application Code

Here’s the simplest possible CMRX application:

#include <cmrx/application.h>

int app_main(void * data)
{
    while (1) {
        // Your application code goes here
        // This infinite loop keeps the thread running
    }
}

OS_APPLICATION_MMIO_RANGE(app, 0, 0)
OS_APPLICATION(app)
OS_THREAD_CREATE(app, app_main, NULL, 64)

What Each Line Does

  1. #include <cmrx/application.h> - Includes the CMRX application framework
  2. int app_main(void * data) - Your main application function (like main() in regular C programs)
  3. while (1) { } - An infinite loop that keeps the thread alive
  4. OS_APPLICATION_MMIO_RANGE(app, 0, 0) - Defines memory-mapped I/O ranges (none in this example)
  5. OS_APPLICATION(app) - Declares an application named “app”
  6. OS_THREAD_CREATE(app, app_main, NULL, 64) - Creates a thread that runs app_main() with the scheduler priority of 64

Building the Application

To build this code, you need to create a CMake configuration. Create a CMakeLists.txt file:

add_application(app app.c)
target_link_libraries(app stdlib)

Important: The name “app” in add_application() must match the name used in OS_APPLICATION(app).

How Memory Isolation Works

CMRX automatically creates isolated memory regions for each application. The rule is simple:

All data in the same static library as the OS_APPLICATION() macro belongs to that application.

This means you don’t need to manually configure memory partitions - CMRX handles it automatically based on your code organization.

Complete Project Setup

To create a working project, you need three parts:

  1. Hardware Configuration - Tell CMRX what microcontroller you’re using
  2. Kernel Integration - Include and configure the CMRX kernel
  3. Main Entry Point - Create the system startup code

Step 1: Hardware Configuration

For ARM-based microcontrollers, configure CMSIS support:

set(CMSIS_ROOT path/to/cmsis/inside/sdk)
set(DEVICE your_device_name)
set(CMSIS_LINKER_FILE path/to/linker/file)
include(FindCMSIS)

What These Variables Do:

  • CMSIS_ROOT - Path to CMSIS headers in your SDK
  • DEVICE - Your microcontroller’s part name (check your SDK documentation)
  • CMSIS_LINKER_FILE - Path to the linker script for your device

Step 2: Kernel Integration

Add CMRX to your build:

set(CMRX_ARCH arm)
set(CMRX_HAL cmsis)
include(CMRX)
add_subdirectory(path/to/cmrx)

add_firmware(hello_world main.c)
target_link_libraries(hello_world vendor_sdk)
target_app_applications(hello_world app)

What This Does:

  • Configures CMRX for ARM architecture with CMSIS HAL
  • Creates a firmware image called “hello_world”
  • Links your application to the firmware

Step 3: Main Entry Point

Create a main.c file for system initialization:

#include <RTE_headers.h>
#include CMSIS_device_header

long timing_get_current_cpu_freq(void)
{
    return SystemCoreClock;
}

int main(void)
{
    // Perform hardware initialization here
    // (configure clocks, peripherals, etc.)
    
    timing_provider_setup(1);
    os_start();  // Start the CMRX kernel
}

Why This File Exists:

  • Hardware setup is easier to do before the kernel starts
  • The code runs with full privileges to configure peripherals
  • Once os_start() is called, CMRX takes over and starts your applications

What Happens When You Run This

  1. Your microcontroller boots and runs main()
  2. Hardware initialization code executes
  3. os_start() launches the CMRX kernel
  4. The kernel creates your “app” application in isolated memory
  5. The kernel starts the thread running app_main()
  6. Your application runs in its infinite loop

Next Steps

This basic example doesn’t do anything visible, but it demonstrates the foundation of CMRX development. To make it useful, you could:

  • Add actual code inside the while(1) loop
  • Use CMRX APIs to interact with hardware
  • Create multiple applications for different tasks
  • Add inter-process communication between applications

For more complex examples covering full hardware and SDK integration process, check the CMRX documentation which provides how-to guides for variety of hardware:

64kB of protected memory ought to be enough for everyone.