/M5P1_MuProkaron

A tiny real-time kernel focusing on formal reliability and simplicity.

Primary LanguageCThe UnlicenseUnlicense

logo

One RTOS (RMP)

Github release Github commits language Build CII Best Practices Codacy Badge Join the chat at https://gitter.im/M5P1_MuProkaron/Lobby

点击 这里 查看中文版。

    RMP is a small real-time operating system which focuses on formal reliability and simplicity. It achieves reliability by deployment of formal techniques(not completed yet; only whitebox testing with 100% branch coverage done. The kernel can be regarded as pre-certified IEC 61508 SIL2, or EAL 4). All the basic functionalities that are necessary for RTOSes are provided, but nothing more. This guarantees that the system is the minimum possible kernel and is also suitable to be used as a guest operating system when hosted on virtual machine monitors.

    This operating system is much leaner than any other RTOSes, especially when compared to FreeRTOS or RT-Thread, and understanding it should be simple enough. Yet it provides a complete set of functions that you may need during resource-constrained microcontroller development, such as efficient memory management, anti-aliasing graphics, and various helper functions. All these features come in a single .C file, and are without any extra RAM consumption!

    The manual of the operating system can be found here.

    Read Contributing and Code of Conduct if you want to contribute, and Pull Request Template when you make pull requests. This software is an official work of EDI, and thus belongs to the public domain. All copyrights reserved by EDI are granted to all entities under all applicable laws to the maximum extent.

    For vendor-supplied packages and hardware abstraction libraries, please refer to the M0P0_Library repo to download and use them properly.

Quick Demo

Linux minimal runnable binary

    Download the precompiled 32-bit linux binary here and watch benchmark results!

Built-in graphics : widgets, example and FXAA anti-aliasing

Controls Calculator FXAA

Basic thread operations

Create a thread

    RMP_Thd_Crt(&Thd_1            /* Thread control block */, 
                Func_1            /* Thread entry */,
                &Stack_1[238]     /* Stack address */,
                (void*)0x12345678 /* Parameter */,
                1                 /* Priority */, 
                5                 /* Timeslices */);

Delete a thread

    RMP_Thd_Del(&Thd_1            /* Thread control block */);

Suspend a thread

    RMP_Thd_Suspend(&Thd_1        /* Thread control block */);

Resume a thread

    RMP_Thd_Resume(&Thd_1         /* Thread control block */);

Delaying a thread

Delay

    void Func_1(void* Param)
    {
        RMP_PRINTK_S("Parameter passed is ");
        RMP_PRINTK_U((ptr_t)Param);
        RMP_PRINTK_S("\r\n");
        while(1)
        {
            RMP_Thd_Delay(30000);
            RMP_PRINTK_S("Delayed 30000 cycles\r\n\r\n");
        };
    }

    void RMP_Init_Hook(void)
    {
        RMP_Thd_Crt(&Thd_1, Func_1, &Stack_1[238], (void*)0x12345678, 1, 5);
    }

Send from one thread to another

Send

    void Func_1(void* Param)
    {
        ptr_t Time=0;
        while(1)
        {
            RMP_Thd_Delay(30000);
            RMP_Thd_Snd(&Thd_2, Time, RMP_MAX_SLICES);
            Time++;
        };
    }

    void Func_2(void* Param)
    {
        ptr_t Data;
        while(1)
        {
            RMP_Thd_Rcv(&Data, RMP_MAX_SLICES);
            RMP_PRINTK_S("Received ");
            RMP_PRINTK_I(Data);
            RMP_PRINTK_S("\n");
        };
    }

    void RMP_Init_Hook(void)
    {
        RMP_Thd_Crt(&Thd_1, Func_1, &Stack_1[238], (void*)0x12345678, 1, 5);
        RMP_Thd_Crt(&Thd_2, Func_2, &Stack_2[238], (void*)0x87654321, 1, 5);
    }

Counting semaphores

Semaphore

    void Func_1(void* Param)
    {
        while(1)
        {
            RMP_Thd_Delay(30000);
            RMP_Sem_Post(&Sem_1, 1);
        };
    }

    void Func_2(void* Param)
    {
        ptr_t Data;
        while(1)
        {
            RMP_Sem_Pend(&Sem_1, RMP_MAX_SLICES);
            RMP_PRINTK_S("Semaphore successfully acquired!\r\n\r\n");
        };
    }

    void RMP_Init_Hook(void)
    {
        RMP_Sem_Crt(&Sem_1,0);
        RMP_Thd_Crt(&Thd_1, Func_1, &Stack_1[238], (void*)0x12345678, 1, 5);
        RMP_Thd_Crt(&Thd_2, Func_2, &Stack_2[238], (void*)0x87654321, 1, 5);
    }

Memory pool operations

    /* Initialize memory pool */
    RMP_Mem_Init(Pool, Pool_Size);

    /* Allocate from the pool */
    Mem=RMP_Malloc(Pool, Alloc_Size);

    /* Free allocated memory */
    RMP_Free(Pool, Mem);

Typical performance figures for all supported architectures

    Flash and SRAM consumption is calculated in kB, while the other figures are calculated in CPU clock cycles. All values listed in the table below are typical (useful system) values, not minimum values, because minimum values on system size seldom make any real sense. HAL library are also included in the size numbers.

    The absolute minimum value for RMP is about 1.6k ROM and 432 byte RAM, which is reached on the HC32L136K8TA (Cortex-M0+) port, and this number even included the 60-byte thread control block and 256-byte stack of the first thread, and a 64-byte kernel interrupt response stack. The OS kernel and the stripped down HAL only consumes 52 bytes of memory combined. If you are willing to push this limit even further, then the manufacturer HAL is a rip-off for you and you can roll your own.

Machine Toolchain Flash SRAM Yield Mail Sem Mail/Int Sem/Int Mem
DSPIC33E XC16-GCC 4.46 1.15 526 828 750 914 884 579
MSP430 TI CCS7 2.90 0.64 495 906 786 830 736 1575
Cortex-M0 Keil uVision 5 4.94 1.65 374 663 616 659 617 N/A
Cortex-M0+ Keil uVision 5 6.25 1.65 334 607 544 588 552 N/A
Cortex-M3 Keil uVision 5 5.31 1.65 252 513 448 465 418 311
Cortex-M4 Keil uVision 5 5.46 1.66 188 386 353 361 329 233
Cortex-M7 Keil uVision 5 6.66 1.65 196 288 277 296 296 183
Cortex-M7 GCC 7.71 1.98 176 313 276 290 268 193
Cortex-M7-RVM Keil uVision 5 2.09 2.29 1068 1256 1195 884 866 176
Cortex-M7-RVM GCC 2.15 2.10 1103 1277 1225 907 866 177
Cortex-R4 TI CCS7 15.1 1.42 281 458 406 424 368 274
Cortex-R5 TI CCS7 18.2 3.72 305 471 426 472 432 267
MIPS M14k XC32-GCC 17.2 2.46 263 378 358 430 420 211
RV32IMAC GCC 2.24 2.89 261 585 506 ~800** ~800** N/A
X86-LINUX GCC N/A N/A 33000 35000 33000 35000 33000 136

*As a comparison, RT-Linux 4.12's best context switch time on Cortex-M7 is bigger than 25000 cycles. This is measured with futex; if other forms of IPC such as pipes are used, this time is even longer.

**This is for reference only; the part used for evaluation relies on SPI Flash interface and can sometimes have a response time of 45000 cycles on a single instruction cache miss. Conventionally external SPI-Flash based device need large internal memory to run their code from to make these measurements, however this part simply does not have that much memory.

  • DSPIC33E is evaluated with DSPIC33EP512MU810.
  • MSP430 is evaluated with MSP430FR5994.
  • Cortex-M0 is evaluated with STM32F030F4P6.
  • Cortex-M0+ is evaluated with STM32L053C8T6.
  • Cortex-M3 is evaluated with STM32F103RET6.
  • Cortex-M4 is evaluated with STM32F405RGT6.
  • Cortex-M7 is evaluated with STM32F767IGT6.
  • Cortex-M7-RVM is evaluated with STM32F767IGT6, and the RMP runs as a guest OS in the RVM embedded hypervisor.
  • Cortex-R4 is evaluated with TMS570LS0432.
  • Cortex-R5 is evaluated with TMS570LC4357.
  • MIPS M14k is evaluated with PIC32MZ2048EFM100.
  • RV32IMAC is evaluated with FE310-G000.
  • X86 Linux is evaluated with Ubuntu 16.04 on i7-4820k @ 3.7GHz.

    All compiler options are the highest optimization (usually -O3) and optimized for time.

  • Yield : The time to yield between different threads.
  • Mail : The mailbox communication time between two threads.
  • Sem : The semaphore communication time between two threads.
  • Mail/Int : The time to send to a mailbox from interrupt.
  • Sem/Int : The time to post to a semaphore from interrupt.
  • Mem : The time to do an operation on memory, e.g. allocation/free.

Possible New Architecture Supports

Architecture Reason Priority
RL78 Largely used 16-bit MCU ⭐⭐⭐⭐⭐
TI C2000 Largely used DSP ⭐⭐⭐⭐
MicroBlaze Largely used soft core ⭐⭐
NIOS II Largely used soft core

Architectures NOT Supported

Architecture Reason Workaround
PIC18 Hardware stack Use RMS State-machine based OS
AVR32 In decline Use more popular Cortex-M and Cortex-Rs
ARMv5 New versions available Use newer Cortex-M and Cortex-Rs
x86-64 Advanced system Use RME Microkernel-based OS
Cortex-A Advanced system Use RME Microkernel-based OS
Coldfire In decline Use more popular Cortex-M and Cortex-Rs
PowerPC In decline Use more popular Cortex-M and Cortex-Rs
RX100/600/600S Rarely used Use more popular Cortex-M and Cortex-Rs
Tricore Rarely used Use more popular Cortex-M and Cortex-Rs
MB91460 Rarely used Use more popular Cortex-M and Cortex-Rs

Getting Started

    These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Prerequisites

    You need Cortex-M or Cortex-R or MIPS or MSP430 microcontroller development kits to run the tests. This RTOS focuses on value-line MCUs and do not concentrate on high-end MCUs or MPUs. Do not use QEMU simulator to test the projects because they do not behave correctly in many scenarios.

    If you don't have a development board, a x86-based Linux port of RMP is also available. However, running RMP on top of linux uses the ptrace system call and signal system, thus it is not particularly fast. Just run the example and observe benchmark output.

    Other platform supports should be simple to implement, however they are not scheduled yet. For Cortex-A and other CPUs with a memory management unit (MMU), go M7M1_MuEukaron Real-Time Multi-Core Microkernel instead; M7M1 supports some Cortex-Ms and Cortex-Rs as well.

Compilation

    The Vendor Toolchain or Eclipse projects for various microcontrollers are available in the Project folder. Refer to the readme files in each folder for specific instructions about how to run them. However, keep in mind that some examples may need vendor-specific libraries such as the STMicroelectronics HAL. Some additional drivers may be required too. These can be found in M0P0_Library repo.

Running the tests

    To run the sample programs, simply download them into the development board and start step-by-step debugging. Some examples will use one or two LEDs to indicate the system status. In that case, it is necessary to fill the LED blinking wrapper functions.

    To use the graphics library and other advanced features, please refer to the user manual.

Deployment

   When deploying this into a production system, it is recommended that you read the manual in the Documents folder carefully to configure all macros correctly.

Built With

  • Keil uVision 5 (armcc)
  • Code composer studio
  • MPLAB X XC32
  • GCC/Clang-LLVM

    Other toolchains are not recommended nor supported at this point, though it might be possible to support them later on.

Contributing

    Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

EDI Project Information

    Mutate - Protero - Prokaron (M5P1 R4T1)

Starring Contributors

    Leifeng Song - ARM Cortex-M3/4/7 assembly port.