Announcing CoRTOS - A minimalist Cooperative RTOS

Go To Last Post
28 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

CoRTOS - The world's simplest RTOS (?) is available under GPL V3

 

(Please see below for the V1a update)

 

It is fully documented, with a 30 page pdf manual and fully commented source code.

 

The intended audience includes:

    •    Those needing a small footprint RTOS for moderately complex products such as IOT, appliances, industrial controls, sensors, and toys;
    •    Students learning about Real Time techniques;
    •    Makers wanting to program ‘close to the metal.’

 

CoRTOS has the following features:

    •    Small kernel size of 16 lines of C, making it fast and reliable;
    •    Simplified task design as there is no interference from preemption;
    •    Full featured with add-on modules for delays and other time related functions, messaging, mutexes and signaling;
    •    Designed and written in a straight-forward way, making it easy to understand and expand.

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

Last Edited: Tue. Mar 14, 2017 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nolindan wrote:
Simplified task design as there is no interference from preemption

 

Of course, the lack of preemption can bring its own set of complications to task design ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Of course, the lack of preemption can bring its own set of complications to task design ...

 

As the IBM salesman said to the customer: "It's not a bug, it's a feature!"

 

The right RTOS for the job is the one that removes the most complications.  Sometimes that is a preemptive system, sometimes a cooperative system and sometimes no system at all.

 

There is no one-size-fits-all RTOS - one-size-fits-all equals one-size-fits-none.

 

I've been designing embedded RTOS kernels and dragging client organizations into the the light for 35 years.  To gain acceptance an RTOS must fit the client's goals, and, funnily, also fit the client's organizational structure.  Very top down organizations really like preemption; laissez-faire organizations are happiest with the most innocuous of task switchers.  When I first read about the relationship between the organization of the employees and the organization of the software they write in "The Mythical Man-Month," I thought to myself "What piffle!"  But I have found it to be true, and not surprising - employees do best in an organization that mimics the organization of their psyche.

Nicholas O. Lindan

Cleveland Engineering Design, LLC

Last Edited: Tue. Mar 7, 2017 - 02:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, it's always fun to study a new RTOS! 

 

Jim

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It's worth flagging up, as I can't see it mentioned in the documentation or source, that for the AVR this will only work when using GCC. For any other compiler you'll need to rewrite the context switch.

"This forum helps those that help themselves."

"How have you proved that your chip is running at xxMHz?" - Me

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are the names of the filenames really enhanced by having CoRTOS* as a prefix on each? Makes it more difficult to split the wood from the trees in my umble opinion. Surely you just put all this in a CoRTOS directory and then name the files "normally"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
for the AVR this will only work when using GCC

 

Good point - I should add the development environment to the manual.  For the AVR I imagine it would be the stack pointer reference, possibly the punctuation in the pushall/popall in-line assembler macros and the timer ISR syntax that would be sensitive to the development environment.

 

clawson wrote:
Are the names of the filenames really enhanced by having CoRTOS* as a prefix on each?

 

No, they are not, it's a pain in the pitooty.  Please feel free to rename them and chuck the *MSP.* and *PIC.*.  Over the years I have written so many different OSs that I need the prefix/suffix to keep things organized.  Experience has told me that twenty files all named timer.c and all different is recipe for disaster and a scramble for the backups.  When developing I use the obvious "kernel.c" and separate directories.

 

The goal was to make something simple enough that anyone can modify it easily as they see fit.  Please feel free.

Nicholas O. Lindan

Cleveland Engineering Design, LLC

Last Edited: Wed. Mar 8, 2017 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should switch to C++. You handle all this with "namespace" (or just the class name) so you can have as many SetTimer()s or whatever as you like as they are likely either SomeClass::SetTimer() or SomeNamespace::SetTimer()

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nolindan wrote:

For the AVR I imagine it would be the stack pointer reference, ...The goal was to make something simple enough that anyone can modify it easily as they see fit.  Please feel free.

 

Codevision uses a 2 stack model with the hardware stack used as the call stack and Y used to implement a data stack so it's not quite as straight forwards as GCC but it's not too bad. Oh, and different registers need to be saved across a function call.

"This forum helps those that help themselves."

"How have you proved that your chip is running at xxMHz?" - Me

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

nolindan wrote:

For the AVR I imagine it would be the stack pointer reference, ...The goal was to make something simple enough that anyone can modify it easily as they see fit.  Please feel free.

 

Codevision uses a 2 stack model with the hardware stack used as the call stack and Y used to implement a data stack so it's not quite as straight forwards as GCC but it's not too bad. Oh, and different registers need to be saved across a function call.

 

Imagecraft is also a two stack model, similar to CV.

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++/Two Stack/....

 

Thanks for the suggestions but the goal here is simplicity.  How simply can one make a usable RTOS?

 

To that end there are no #ifdefs in the source, no configuration files, the source is (hopefully) intelligently commented, the manual (hopefully) understandable, the system is created with the chip maker's standard IDE, and feature creep is the user's responsibility.

 

I hope that it is easy to understand and easy to customize.  Are there any suggestions to that end?

 

There are no end of good elaborate systems out there; CoRTOS isn't going head-to-head with them but standing apart.

Nicholas O. Lindan

Cleveland Engineering Design, LLC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Attached is a minor update to CoRTOS.

 

CoRTOS now works with interrupts enabled at all times.

 

CoRTOS is not a task scheduler.  

 

CoRTOS works like any other RTOS.  Tasks schedule themselves, picking up where they left off after making a call to the OS.

Please feel free to send questions to nolindan@ix.netcom.com

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

Last Edited: Tue. Mar 14, 2017 - 03:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A very minor update:

 

Sending signals to the same counter by two interrupts of different priorities on RISC processors will need an interrupt enable/disable when incrementing the counter.  Many RISC processors can not atomically increment memory values.

 

Hows that for obscure...

 

 

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you Nicholas for sharing this work. I'll be using it as somewhat of an applied "teaching tool" for a group of folks inexperienced with real time operating systems, and control systems in general. It's interesting to read the expert comments to your posting of this nice work. It's true that many here have gone far beyond simple approaches to 8-bit projects. I wouldn't dare entertain converting this "bare metal" work to C++, as referenced above. I applaud that you stick with GCC and that environment. I've recently read code that gave me a headache because of the "if IAR..." conditionals. I look forward to using this "KISS" RTOS and will let you know the results.

-Ken

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just a random assortment of issues I came across when skimming the code.

 

The code is GPL, hence any application will also be GPL as is statically links against the code. Maybe that's intended, I just wanted to point that out.

 

#include <avr\io.h>
#include <avr\interrupt.h>

That's wrong.  Even under MS-ish hosts, directory separator is /.

 

 

CoRTOSsignal.h and other files use status_t, uint8_t and mode without defining these.  This might lead to errors if you don't follow include orders, and you must always know the header dependencies when using them.

 

 

void rtos_int_disable (void)
{
	...
	TIMSK1 &= ~bit1;
}

Glitch. Changing a bit of TIMSK1 is non-atomic, and in some ISR you are setting TIMSK1.  Presumably, the code is just intended as an example, but users will follow it.  Examples are excellent multiplicators for bugs :-)

 

typedef unsigned char uint8_t;
// typedef char int8_t; AVR include file collides
typedef unsigned int uint16_t;
typedef int int16_t;
#define true 1
#define false 0
#define NULL ((void *)0)

Don't do this; that's realm of the standard.  Use stdint.h, stdbool.h (you are implying C99 anyway) and stddef.h or whatever brings stuff specified by the language.  This is particularly nasty because avr/io.h and friends include stdint.h as they also use uint8_t and friends.

 

 

Some of the files serve as examples, make this clear by using other naming convention for the files, not "CoRTOS*" as a file name.  Similar naming conventions might be useful for objects / types / macros introduced by the OS.  When reading the code it's unclear which are from user code and which from OS.  Examples for different architectures would go into their own "example/arch" (sub) folder.

 

 

Numer of tasts must be statically known.

Same applies for stack used by /each/ task.

Same applies for "resource queue" for each task.

Same applies for "message queue"s.

 

It's unclear which system resources (timers) are occupied by the OS. It's unclear what amout of memory is needed (e.g. amount of memory occupied as formula in number of tasks, queues, stacks, etc.).  Rough estimation of WCET (worst case execution time) for critical OS functions would be nice — just to credit the "RT" in CoRTOS.

 

 

 

 

Naming convention is confusing as to what are macros (ALLCAPS is common) and functions (alllowercase or CamelCase are common).  For example, popall() gives the wrong impression that's a function, but it's a function-like macro.

 

	cli ();
	SP = starting_stack[current_task];
	sei ();

This is hack.  If it works, then just by accident.  You are writing C, hence the compiler is on control of SP.  If all of the "OS" boils down to this one function, switch to asm (not: inline asm) and you are the master of stack.

	OCR1AH = 0x04;
	OCR1AL = 0xe2;

Nope.  Just "OCR1A = value".

 

#define bit0 0x01
#define bit1 0x02
#define bit2 0x04
#define bit3 0x08
#define bit4 0x10
#define bit5 0x20
#define bit6 0x40
#define bit7 0x80
#define bit8 0x0100
#define bit9 0x0200
#define bit10 0x0400
#define bit11 0x0800
#define bit12 0x1000
#define bit13 0x2000
#define bit14 0x4000
#define bit15 0x8000

non sunt multiplicanda entia sine necessitate...

static uint8_t resource_owner [number_of_resources];
...
static uint8_t resource_queue_add_index [number_of_resources];
static uint8_t resource_queue_remove_index [number_of_resources];
static uint8_t resource_queue_n [number_of_resources];

...whereas this cries for a resource_t. This might even improve code quality when traversing the resources, as you would have one address per resource (with different offsets for components like .owner), avoiding the need to compute again and again address into each of the unrelated arrays.

 

/*	RTOS data defining tasks and the size of their stacks.

	number_of_tasks can be found in CoRTOStask.h. */

#include "CoRTOScomdefs.h"

task task0 (void);
task task1 (void);
task task2 (void);
task task3 (void);

task_address_type start_addresses [number_of_tasks] = ...

Sample that just won't compile. "task" is not defined and only sensible definition would be "void".  If CoRTOStask.h is needed then include it, otherwise potential users will get impression of "exercise left to the reader, I just don't care enough to do it properly".

 

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi SprinterSB,

Wow, You are obviously a very good critic. I was very excited about using this small and easy to understand RTOS for a training class for newbies. How about I use the one that you've written instead?

-Ken

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note mr sprinter is heavily involved in the development of avr-gcc. Ignore his comments at your own peril!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KenwickVS wrote:
I was very excited about using this small and easy to understand RTOS for a training class for newbies. How about I use the one that you've written instead?

 

Was that sarcastic? If so, then you're definitively barking up the wrong tree.

 

FYI SprinterSB (Georg-Johann Lay) is heavily active in developing the AVR-specific parts of GCC. It is my opinion that without him we would definitively not have such a good open-source compiler available and maintained. E.g. a substantial number of the bugs discovered over the past years have been reported and fixed by SprinterSB, and he has also contributed with new functionality.

 

If SprinterSB critiques something it is wise to read it through and consider it seriously.

 

Which of his points are you not agreeing with?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I ported "CoRTOSsuperblinkyAVR.c" to an E70xpd board. 

Attached is the Atmel Studio 7.0.1417 Template.

 

I added __set_APSR() to  "core_cmFunc.h".

 

based the port on the ASF "Getting_started" example.

added a LED on PC31. So the 2 LEDs are PC8 (on board) & PC31 off board.

 

Made other changes, like uint32_t for uint16_t.

 

Use the systick timer interrupt.

increased the task stack size.

 

haven't extensively tested or commented.

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jstampfl wrote:
an E70xpd board.

You mean a SAM E70 ?

 

So Cortex-M7 with 2M Flash and 384K RAM

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes SAM E70 Xplained

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, forgot to mention, baudrate is 250000

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I updated "CoRTOStimer.c" & "CoRTOStimer.h"  changed uint16_t to uint32_t

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A minor update to CoRTOS is available - mostly a cleanup of the documentation and source file comments.

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think a preemptive RTOS is usually to much overhead / complication for small uC's such as AVR's

A cooperative RTOS might be usefull to me.

But most of my applications tend to be written in a simple for(;;){} loop.

This has the added bonus for me that I have 100% procent control over interrupt latency.

 

I once had the idea to look into protothreads. They seem a pretty simple alternative to implement an RTOS-ish behaviour but I never got around to it to dive into that.

 

I had a peek at the manual of CoRTOS as I was hoping this was based on coroutines but it apparently uses ASM to switch between tasks.

I have never used Co-Routines, hardly know what they are, but I have a slight inkling they are extremely usefull for a small coorperative RTOS kernel:

https://en.wikipedia.org/wiki/Co...

 

Co-Routines also seem to be added to the C++17 standard.

See milestones at:

https://isocpp.org/std/status

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cortos V1d has been released.

 

Major changes:

  • Support for Cortex M0+
  • Simplified file structure

 

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

GPL3 is all well and good but you realise this is a barrier to this OS ever being used in any commercial product? Do you have an alternate licencing plan for commercial use? No commercial developer is going to openly publish their own intellectual property.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

GPL3 is all well and good but you realize this is a barrier to this OS ever being used in any commercial product?

 

I should be so lucky...  If an organization wants to purchase a commercial license then one can be arranged.

 

A minor update - mostly for the MSP430 "blinky" program, but also some minor changes to the manual.  Not really worth the bandwidth...

 

Attachment(s): 

Nicholas O. Lindan

Cleveland Engineering Design, LLC

Last Edited: Thu. May 24, 2018 - 04:17 AM