distortos - object-oriented C++ RTOS for microcontrollers - Page 1
Forum section: electronics / general

author: Freddie Chopin
author_rank: Regular Contributor
timestamp: May 05, 2019, 06:26:27 pm
content: With the release of distortos 0.7.0 I decided to share my project here in the hope that it may be useful to someone. Or at least that it will be a good start to the endless debate on "why using C++ on a microcontroller is just impossible and should never be tried" (; It shoud be a good controversy starter, as it has (almost) all of the things "loved" so much by C++-haters - templates, inheritance, virtual functions, ... - and yet it works correctly, reliably and fits into flash and RAM (; And you can create threads with as many arguments of whatever types you want, all of that type-checked statically during compilation. Or do the same for virtual timers. Or use RAII for locking mutexes. Or pass non-trivial objects via queues. Or just any of those things which are quite normal in C++, but yet so extremely hard to do in all of these C-only RTOSes (assuming they are possible at all, given the level of support such C-only RTOSes offer to object-oriented design).http://distortos.org/Code:#include "distortos/board/leds.hpp"#include "distortos/chip/ChipOutputPin.hpp"#include "distortos/ThisThread.hpp"int main(){while (1){distortos::board::leds.set(!distortos::board::leds.get());distortos::ThisThread::sleepFor(std::chrono::milliseconds{500});}}This is a COMPLETE file, which uses one thread, as main() is a thread (why wouldn't it be?).Code:#include "distortos/board/leds.hpp"#include "distortos/chip/ChipOutputPin.hpp"#include "distortos/DynamicThread.hpp"#include "distortos/ThisThread.hpp"int main(){auto lambda = [](distortos::devices::OutputPin& led, const std::chrono::milliseconds milliseconds){while (1){led.set(!led.get());distortos::ThisThread::sleepFor(milliseconds);}};const auto thread0 = distortos::makeAndStartDynamicThread({512, 1},lambda, std::ref(distortos::board::leds), std::chrono::milliseconds{500});const auto thread1 = distortos::makeAndStartDynamicThread({512, 1},lambda, std::ref(distortos::board::leds), std::chrono::milliseconds{1234});const auto thread2 = distortos::makeAndStartDynamicThread({512, 1},lambda, std::ref(distortos::board::leds), std::chrono::milliseconds{333});const auto thread3 = distortos::makeAndStartDynamicThread({512, 1},lambda, std::ref(distortos::board::leds), std::chrono::milliseconds{10});while (1)distortos::ThisThread::sleepFor(std::chrono::seconds{1});}Here's another one (assuming the board has 4 LEDs), with 4 additional threads, each built with a lambda which expects 2 arguments - a reference to LED which will be blinked and the duration of one "blink". Try to do the same with a C-only RTOS (;

author: mark03
author_rank: Frequent Contributor
timestamp: May 06, 2019, 10:03:31 pm
content: Have you seenhttp://kvasir.io/? The advanced template stuff is above my pay grade, unfortunately, but I like the concept. Better performance than C with vastly improved compile-time checks.

author: Freddie Chopin
author_rank: Regular Contributor
timestamp: May 07, 2019, 06:30:23 am
content: Quote from: mark03 on May 06, 2019, 10:03:31 pmYes, I've seen it, however it seems that this project is dead. modm project seems to be active and doing basically the same thing -https://github.com/modm-io/modm.Personally I don't like the idea of using templates for EVERYTHING, because - as implemented in such libs - you then have two completely separate classes for things which are really similar - for example with the approach used by kvasir and libs like that, USART1 and USART2 are two completely unrelated things which cannot be used interchangeably with regular functions. This leads to proliferation of the pattern, because if you want to write a function which operates on any UART, then you have to make this function a template too - the UART type has to be the template argument. As long as you need only one LED, one serial port, one SPI, one ADC and one everything, the template approach is fine and optimal, but the moment you will need to use two similar peripherals the idea leads to doubling the executable size. That's why I personally prefer "regular" polymorphism and virtual interfaces, using templates for things like generic algorithms and stuff like that. Obviously the `distortos::StaticThread` class implemented in distortos is a template class too (just like - for example - queues), so it's not that I don't use them at all (;