Code Monkey home page Code Monkey logo

openpicortos's Introduction

picoRTOS

OpenPicoRTOS Latest Release Commits since

Very small, safe, lightning fast, yet portable preemptive RTOS with SMP support.

Quick Presentation

picoRTOS is a small hard RTOS with as little overhead as humanly possible.

Table of contents

  1. Book of requirements
  2. How to use
  3. API Documentation
  4. Supported architectures
  5. Featured devices
  6. Working principle
  7. Inter-processus communication
  8. Shared priorities
  9. Interrupt management
  10. Staging tree
  11. Featured demos

Book of requirements

OpenPicoRTOS has been designed with these requirements in mind:

  • Compliance with "The Power Of 10" from the NASA/JPL (https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Developing_Safety-Critical_Code)
  • Compliance with MISRA C 2012
  • Limited use of inline assembly:
    • Inline assembly should be side-effect free (no use or modification of variables)
    • Inline assembly can be safely removed from the static analysis
  • Smallest footprint possible
  • Fully static
  • Fully predictable
  • High portability
  • Lowest overhead possible
  • Support for SMP
  • Less than 400 lines of code

More information here: https://github.com/jnaulet/OpenPicoRTOS/blob/main/etc/Requirements.md

How to use

Step1: Preparation of your project

To create a project compatible with OpenPicoRTOS you first need to add a specific kind of Makefile to your project.
You can find a very basic template here: https://github.com/jnaulet/OpenPicoRTOS/blob/v1.9.x/etc/Makefile.template

Step2: configuration of your project

Simply type:

# make menuconfig

screenshot

And configure your project according to your needs. You can find a lot of examples in the demo directory.

Step3: Compilation of your project

# make

Step4: Static analysis of your project

# make staticcheck

or, alternatively:

# make splint
# make cppcheck

Bonus: all availables targets

Using the template makefile automatically offers you access to a new set of targets for the OpenPicoRTOS build system, directly in your project directory:

Cleaning targets:
  clean           - Remove most generated files but keep the config and
                    enough build support to build external modules
  mrproper        - Remove all generated files + config + various backup files
  distclean       - mrproper + remove editor backup and patch files

Configuration targets:
  config          - Update current config utilising a line-oriented program
  nconfig         - Update current config utilising a ncurses menu based program
  menuconfig      - Update current config utilising a menu based program
  xconfig         - Update current config utilising a QT based front-end
  gconfig         - Update current config utilising a GTK based front-end
  oldconfig       - Update current config utilising a provided .config as base
  localmodconfig  - Update current config disabling modules not loaded
  localyesconfig  - Update current config converting local mods to core
  silentoldconfig - Same as oldconfig, but quietly, additionally update deps
  defconfig       - New config with default from ARCH supplied defconfig
  savedefconfig   - Save current config as ./defconfig (minimal config)
  allnoconfig     - New config where all options are answered with no
  allyesconfig    - New config where all options are accepted with yes
  allmodconfig    - New config selecting modules when possible
  alldefconfig    - New config with all symbols set to default
  randconfig      - New config with random answer to all options
  listnewconfig   - List new options
  oldnoconfig     - Same as silentoldconfig but set new symbols to n (unset)

Other generic targets:
  all             - Build target

Test targets:
  check           - Run static analysis on all basic platforms + unit tests

Static analysis targets:
  splint          - Run splint -checks on the source code
  cppcheck        - Run cppcheck --enable=all on the source code
  staticcheck     - Run both previous checks

  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build

API Documentation

HTML documentation of the complete API is available in the documentation directory and at the following address: https://jnaulet.github.io/OpenPicoRTOS

Supported architectures

Single core

  • ARM Cortex-M0+
  • ARM Cortex-M3
  • ARM Cortex-M4/F
  • ARM Cortex-M7
  • Atmel ATMega Series
  • Atmel TinyAVR Series
  • Intel 8051 / MCS51
  • MIPS M51xx / PIC32Mx
  • NXP/Freescale HC08/S08
  • RISC-V RV32IMAC
  • RISC-V RV32EC
  • PowerPC e200z4
  • PowerPC e200z7
  • TI C2000 / c28x

Multi-core SMP

  • PowerPC e200z4 SMP
  • PowerPC e200z7 SMP
  • RP2040 SMP

Simulation

  • POSIX threads / Linux
  • WIN32 threads / Windows

Featured devices

  • Atmel ATMega2560
  • Atmel ATMega328P
  • Atmel ATMega32u4
  • Atmel ATSAM3X8E
  • Atmel ATSAMD5x/E5x
  • Atmel ATtiny817
  • Atmel ATtiny88
  • Atmel ATtiny1607
  • Cypress CY7C6801xA / EZ-USB FX2
  • GigaDevice GD32VF103
  • LogicGreen LGT8F328P
  • Microchip PIC32MZ-EF
  • Nuvoton N76E003
  • NXP MC9S08PTxx series
  • NXP MPC574x series
  • NXP MPC577x series
  • Raspberry Pico RP2040
  • Renesas RA4M1
  • STC MCU STC12C5Axx series
  • STMicroelectronics STM32F10xxx series
  • STMicroelectronics STM32F401x series
  • STMicroelectronics STM32H743/750
  • Texas Instruments TMS320F2837xD
  • WCH CH32V003

Working principle

On every new cycle (tick), picoRTOS stops the execution of the current task and runs the highest priority task available.
A few criterias make a task available for scheduling, it has to be:

  • Ready (aka not sleeping/busy)
  • The tick modulo has to match the task sub-priority (see shared priorities)
  • In case of SMP, the task core mask has to match the current running core

Any syscall (picoRTOS_schedule, picoRTOS_sleep or picoRTOS_sleep_until) will allow picoRTOS to run the next highest priority task available until it reaches idle or a new tick occurs and the cycle starts over.

Task execution order goes from highest (0) to lowest (CONFIG_TASK_COUNT - 1) priority.

Example:

tick: prio0 -> prio1 -> prio2 -> ... (towards idle)   
tick: prio0 -> prio1 -> prio2 -> ... (towards idle)
...

No memory management is offered, everything is static, which makes the static analyzer's job much easier for critical applications.

Inter-processus communication

The following IPCs are provided:

  • futexes (require arch_test_and_set)
  • re-entrant mutexes (require arch_compare_and_swap)
  • conditions (require mutexes)
  • queues (requires futexes)

Shared priorities

Version 1.7 introduces shared priorities for tasks, a.k.a round-robin scheduling.

When several tasks share the same priority, the order of execution (highest to lowest priority) doesn't change, but these tasks will be executed alternatively, on a tick modulo basis.

Example with 2 tasks (B & C) sharing a priority of 1:

tick 0: taskA (prio 0) -> taskB (prio 1) -> taskD (prio 2) -> ...    
tick 1: taskA (prio 0) -> taskC (prio 1) -> taskD (prio 2) -> ...  
tick 2: taskA (prio 0) -> taskB (prio 1) -> taskD (prio 2) -> ...  
tick 3: taskA (prio 0) -> taskC (prio 1) -> taskD (prio 2) -> ...  
...

Interrupt management

Version 1.5 introduces contextual interrupt management as an experimental feature.

All architectures are supported (at least partially) at the moment.

This feature should be used with care, as interrupts tend to destroy the real-time part in "RTOS".

Staging tree

Version 1.8 introduces the staging tree.

This tree contains code that builds & fits the book of requirements but could not be tested for one reason or the other.

This code should be considered highly experimental until validation.

Featured demos

Basic demo code is provided for the following boards:

  • Adafruit ItsyBitsy M4 Express
  • Arduino Due
  • Arduino Mega2560
  • Arduino Nano v3 + LGT8Fx clone (staging)
  • Arduino Uno
  • Arduino Uno R4 Minima
  • ATtiny817-Xplained Mini
  • ATtiny1607 Curiosity Nano
  • Curiosity 2.0 PIC32 MZ EF
  • DevEBox STC-C51
  • DevEBox STM32H7xx_M
  • Infineon EZ-USB FX2LP
  • MH-Tiny / MH-Tiny88 (staging)
  • Nuvoton N76E003 / MCU-E003
  • NXP Devkit MPC5748G (dual-core SMP)
  • NXP MPC5775E-EVB (dual-core SMP) (staging)
  • NXP S08PT60-EVK (staging)
  • Sipeed Longan Nano
  • STMicro STM32F103C8T6 development board (staging)
  • STMicro STM32F401RCT6 development board (staging)
  • Texas Instruments Launchxl-f28379d
  • Raspberry Pi Pico (single core & SMP)
  • WCH CH32V003F4P6 eval board (staging)

A portability demo is available in demo/amigaball-lcd and works with the follwing boards (+0.96" LCD):

  • Adafruit ItsyBitsy M4 Express
  • Sipeed Longan Nano
  • Texas Instruments Launchxl-f28379d
  • Raspberry Pi Pico SMP
  • DevEBox STM32H7xx_M / STM32H743VIT6
  • Arduino Mega2560

Links:

openpicortos's People

Contributors

jnaulet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

openpicortos's Issues

Support for round-robin scheduling

I'm not a huge fan of this idea, but round-robin would be a nice feature.
The general idea would be to use some 2-step round-robin management.

First, create a round-robin task that would fit in the normal picoRTOS scheduling.
Second, provide this task a fixed-sized array of sub-tasks to run sequentially.

This way, the hi-speed, ultra-reliable low-latency standard picoRTOS scheduler stays unaffected.
Round-robin is more of an extension than a rewrite of the scheduler.

The API stays to be defined, maybe something like:
picoRTOS_round_robin_task_init(struct picoRTOS_rr_task *task, struct picoRTOS_task *array, size_t n);
picoRTOS_add_round_robin_task(struct picoRTOS_rr_task *task, picoRTOS_priority_t prio);

CONFIG_DEADLOCK_COUNT in the drivers is a bad idea !

A lot of drivers use CONFIG_DEADLOCK_COUNT as a way to avoid infinite loops. This doesn't work.
Depending on the CPU power or level of optimization, this could trigger an assert and make a perfectly good software stall.

The solution is not obvious... We can increase the countdown but take the risk to see it fail anyway or find a way to determine the max counter depending on the CPU frequency.
This one is available in the clock HAL, but this means the clocks must be initialized, which is not satisfying either.

SAMD51 clock system stalls in -O2 and above

This is related to issue #19
We might have to implement some variant of activate wait, like delay_us() or delay_ms() for every arch & every clock speed.

This is not that obvious withotu a massive refactoring, unless maybe arch_counter() might be used differently (as a freerunnning counter, similar to MIPS and RISC-V).

Define a decent HAL for flash that will allow the use of filesystems

For the moment the embryo of a flash HAL is only dedicated to tests.
For it to be more useful it has to be able to communicate with potential file systems & offer better interfaces.

The HAL should be able to communicate to the upper layers:

  • Its total size (in bytes ?)
  • Its erase size depending on the address/sector ? (erasable sectors might vary in size)
  • Its various or minimum available write size (page, qword, word, etc)
  • ECC, OOB ?

This has to be very practical and eliminate as much guess work as possible for the upper layers, so accessors might be a solution, like:

  • int flash_get_size(struct flash *ctx);
  • int flash_get_erase_size(struct flash *ctx, size_t addr);
  • int flash_get_write_size(struct flash *ctx, size_t addr);
  • int flash_get_block(struct flash *ctx, size_t addr) ?
  • ...

Otherwise, a flash_probe(ctx, &probe_info) can be a solution that offers the option to be easy to extend in the future, but will probably require to output a complete flash mapping, which might prove to be difficult with no dynamic memory allocation.

We still have the option to put this mapping statically in picoRTOS_device.h, though, but what about hypothetical external flashes ?

Ethernet support

Define a coherent HAL + a reference driver for Ethernet peripherals

Staging: support for TWI/I2C on GD32VF103

Test, debug and validate the twi driver on GD32VF103.
This one is probably not working right and the state machine might need to be adjusted to increase reliability and performance, so there's probably a decent amount of development to do during that phase.

Support for cache operations

Only a few platforms support hardware cache synchronisation but almost all of them support DMA operations.

This will become a problem with DMA and SMP at some point.

Cache invalidation and cache flush operations will have to be implemented, ideally in an optional way that won't force platforms with no caches to implement dummy calls.

Support for 8bit PIC MCUs

Port picoRTOS to 8bit PIC to see if it fits.

It's more of a challenge than anything else, but who knows ?

Staging: support for CAN on SAME5x

Test, debug and validate CAN driver on SAME5x.
This will require the support for a new device & a new demo, as picoRTOS only supports SAMD51 at the moment.

Support for KConfig

As more and more architecture and drivers are added, some configuration system similar to what can be found in the Linux kernel might become necessary.

SPI HAL: add a lsb_first field in spi_settings

Add something like:

bool lsb_first

or maybe better:

typedef enum {
SPI_ENDIANNESS_LSB_FIRST,
SPI_ENDIANNESS_MSB_FIRST,
SPI_ENDIANNESS_COUNT
} spi_endianness_t;

in struct spi_settings

Find a better cache management system

Right now, cache functions are ifdef-ed depending on the need (especially on the staging PowerPC archs).

This shouldn't be the case, a cache management function is a cache management function regardless if it's used or not, this should be handled at the drivers, scheduler or device level.

More or less any level except the current one.

HAL: remove all boolean fields from settings structures

For better readability, i suggest to remove all booleans from the xxx_setup() arguments.
This would make structure inits more readable for the casual reviewer, not having to guess what this "true/false" statement is all about.

This is a generalisation of issue #59

The raspberry pico doesn't boot anymore

After a quick investigation, the problem come from the latest arm-none-eabi-gcc update which inserts a gnu header before the .boot2 section.

Will be fixed ASAP

TI F28379D: explore the possibility of dual core emulation

The F28379D (and F2838x) series offer a dual CPU system that is not quite a dual-core system.
More a dual-MCU system.

Limitations are the following:

  • Each CPU/MCU has its own non-shared flash & internal memories (Mx Dx & LSx RAMs)
  • The shared memory (GSx RAM) has no arbitration, each cpu needs to take ownership of a section to be able to write or fetch
  • And God knows what else

With these limitations in mind, is it possible to run a software on both MCUs at the same time and make it act like it's a dual-core system ? At what cost ?

Improve rp2040 ipwm precision

Don't use the tick as a reference point for ipwm as the task using the ipwm might be run at any time during the scheduling.

Maybe use a separate timer or picoRTOS_get_tick() + arch_counter()

Make OpenPicoRTOS able to handle fixed exception vectors

On some projects, having fixed vectors is a prerequisite for safety reasons, ATSAM3X8E & ATSAME5x (and maybe PIC32MX) are a good example of that.

For the moment the trick is do copy the vectors to RAM before altering them. Not an ideal solution by any means.
As we don't want to provide init & linker files, we have to find a way to account for this.

Here's the idea:

  1. Add an entry in picoRTOS_device.h, something like DEVICE_HAS_FIXED_VECTORS
  2. Add a second entry in the form of ARCH_SYSTICK_HANDLER, which will point to the (hopefully) weak vector entry
  3. Add a final entry, ARCH_SYSCALL_HANDLER, same as above
  4. Include "picoRTOS_device.h" in the assembly files
  5. Replace arch_SYSTICK (or similar) in the ports by ARCH_SYSTICK_HANDLER
  6. Replace arch_SYSCALL by ARCH_SYSCALL_HANDLER
  7. Put ifdefs on DEVICE_HAS_VECTORS in the picoRTOS_port.c files to remove interrupt registration for tick & syscall

I don't like ifdefs but this one might be acceptable, as devices will work only one way or the other, testing will be done per device/project & not on a global scale.

Plus, this one will just remove stuff & not generate another use case so the complete code can be parsed by the static analyzer as long as DEVICE_HAS_FIXED_VECTORS is defined. Unit test only apply to the scheduler, not the ports anyway.

Add default support for MPU

Here's the basic idea for MPU:

  • Must be fully integrated to the scheduler
  • Every task will have its stack protected
  • IPCs will create an entry for all tasks
  • A new shared memory IPC will probably be required

Unsovled problems:

  • Drivers
  • Globals (maybe)

GPIO HAL: add gpio_setup()

To increase portability it might be useful to add a gpio_setup function allowing, for example, to invert the gpio output.

Periodic crash on rp2040 SMP (v1.8.0)

The raspberry-pico-SMP demo periodically crashes after a while with a HardFault exception.
The second core seems to crash on a context switch but it is hard to tell exactly the cause as things escalate quickly, core #0 cannot get the spinlock after that and the system freezes.

This is related to inter-core communication, either spinlocks or sio_fifo, as the bus seems quite sensitive to any kind of race condition. Pushing the system to 10Khz helps to highlight the problem (never seen it at 1Khz).

I removed the execute-in-place in this demo already cause it showed the same symptoms but i thought at the time it was due to both cores accessing the flash, called it a unsolvable issue & moved on. There might be more to it.

So maybe there's something we can do about it, maybe the rp2040 cannot tick that fast without having issues. Investigation needed.

Staging: support for DMA on RP2040

Test, debug and validate DMA driver for RP2040.
This one probably need a lot of adjustments, especially to interface with other drivers.

Complete the twi/i2c hal

As i2c is probably my least favorite peripheral to develop and test, a lot has been left out.

It requires at least one more interface in the form of twi_poll() for the slave part.

A simple not twi_poll(struct twi *ctx) that returns -EAGAIN, 0 (write) or 1 (read) should do the trick.

This will allow a slave to know if he’s addressed for a read or a write, allowing asynchronous read and writes.

this is already present in different state machines so it’s just moving code around, the big part of the work will be to re-test everything.

Regarding the setup, 10bit mode is missing, unbalanced scl hi/Lo is not supported, etc, etc and most of the drivers simply ignore basic errors like arbitration loss.

C28x: DMA copies to RAM but refuses to copy to SPITXBUF

dma-ti_f28x doesn't work properly, don't know if it is software or hardware (like configuration) related.

You can check it out in demo/amigaball-lcd, if you activate the (well needed) DMA, it doesn't work, SPITXBUF doesn't seem to received any word.

USB support

Offer support for USB device and host.

Define a coherent USB HAL + a reference driver. Rp2040 or SAM3x seem good candidates.

The USB HAL would ideally make a TinyUSB port to picoRTOS easy

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.