Code Monkey home page Code Monkey logo

cocoos's Introduction

cocoOS

A cooperative operating system based on coroutines

cocoOS is a free, open source, cooperative task scheduler, based on coroutines targeted for embedded microcontrollers like AVR, MSP430 and STM32.

Task procedures scheduled by cooperative kernels are so called RTC's, run to completion tasks. They execute from the first line of the procedure to the last line.

The use of coroutines enables us to implement task procedures that does not have to execute all the way down to the last line of code. Instead execution can end in the middle e.g waiting for a semaphore to be released. When execution is resumed, it continues at that line.

With coroutines, this can be done without having to save the complete task context when switching to another task.

Also, task procedures can be outlined in the same style as when using a traditional preemptive RTOS.

cocoOS is extremely portable to any target which makes it a perfect choice during early phases in the development when which OS to use is still an open issue. You can even run it under Linux or Windows.

##Performance For example: porting on PIC16Fxx chip,compile with XC8 V1.4, the cost: RAM 1.9k,ROM 2.3K

Getting Started

Configuration

To setup cocoOS you have to define 6 macros. They can be setup in os_defines.h, or as defined as compiler flags, e.g. -DN_TASKS=2... If not defines as flags, they will be set to default values according to the list below:

- N_TASKS: maximum number of tasks            (0-254, default=1)
- N_QUEUES: maxmimum number of message queues (0-254, default=0)
- N_SEMAPHORES: maximum number of semaphores  (0-254, default=0)
- N_EVENTS: maximum number of events          (0-254, default=0)
- ROUND_ROBIN: should round robin scheduling be used ? (0)
- Mem_t: address type, e.g. uint32_t          (uint32_t)

Asserts will fire if the maximum numbers are violated during runtime.

To save RAM it is recommended to keep these values as low as possible.

System setup - application main function

As usual you have to setup your system, ports, clocks etc in the beginning of your main function.

Then you setup the cocoOS kernel with a call to os_init() and proceeds with

creating all tasks, semaphores and events.

int main(void) {
  /* Setup ports, clock... */
  system_init();
  

  /* Initialize cocoOS */

  os_init();

  /* Create kernel objects */
  task_create( taskProc, &taskData, 1, NULL, 0, 0 );
  mySem = sem_bin_create( 1 );

 

  os_start();
  
  /* Will never end up here */
  return 0;
}

This is the preferred order of initialization. The os_start() function will call os_enable_interrupts() that can be used to enable the clock interrupt driving the os_tick().

Time

cocoOS keeps track of time by counting ticks. You must feed the counting with a call to os_tick() periodically from the clock tick ISR.

A system of one main clock and several sub clocks is used in cocoOS. The main clock is controlled by the os_tick() function and decrements the timers used for task_wait(), msg_post_in() and msg_post_every(). If your application does not need more than a single time base, the main clock fed by the os_tick() call is all you need. The main clock is typically realized using one of the hardware timers within your target microcontroller.

But if your application has to react to events in another time resolution than what is provided by the main clock, you can use the sub clocks. The sub clocks are typically not associated with a hardware timer, but is instead "ticked" by calling os_sub_tick(id) from within your application code.

Sub clocks can also be advanced with a step greater than one using os_sub_nTick(id, nTicks).

There is one task function associated with the sub clocks: task_wait_id(id,ticks). id is a value in the range 1-255 assigned by the application, and ticks is the number of ticks to wait.

An example of the use of sub clocks could be a task that should be run after 64 bytes has been received on the UART. The task starts the wait by calling task_wait_id( 1, 64 ). And in the UART rx ISR os_sub_tick(1) is called for each received character.

Tasks

An application is built up by a number of tasks. Each task is a associated with a (preferably short) procedure with a well defined purpose.

The execution of the tasks, is managed by the os kernel, by letting the highest priority task among all execution ready tasks to execute.

All tasks have to make at least one blocking call to a sheduling kernel function. This gives lower priority tasks a chance to execute.

The task procedure must enclose its code with the task_open() and task_close() macros, as shown below.

static void task(void) {
  task_open();
  ...
  ...
  task_close();
}

Such a task will be executed once only. If a task is intended to be executed "for ever", an endless loop must be implemented:

static void hello_task(void) {
  task_open();
    for(;;) {
      uart_send_string("Hello World!");
      task_wait( 20 );
    }
  task_close();
}

 

int main(void) {
  /* Setup ports, clock... */
  system_init();
  

  os_init();

  /* Create kernel objects */
  task_create( hello_task, &taskData, 1, NULL, 0, 0 ); 


  os_start();
  
  /* Will never end up here */
  return 0;
}

Scheduling

When a task has finished it gives the CPU control to another task by calling one of the scheduling macros:

- task_wait()

- task_wait_id()
- event_wait()

- event_wait_timeout()
- event_wait_multiple()
- event_signal()
- sem_wait()
- sem_signal()
- msg_q_get()
- msg_q_give()

- msg_post()

- msg_post_in()

- msg_post_every()

- msg_receive()

Normally the scheduler will give the cpu to the highest priority task ready for execution. It is possible to choose a round robin scheduling algorithm by putting the following line in os_defines.h:

ROUND_ROBIN

When round robin is used, the scheduler to scan the list of tasks and run the next found task in the ready state ignoring the prio level of the tasks.

event_wait() and event_wait_ex()

A task can be set to wait for an event to be signaled, by calling event_wait(). If the event is signaled from another task, everything works as expected: when the event is signaled, the waiting task is ready for execution again.

void task() {
  task_open();
  for (;;) {
    event_wait(anEvt);
    do_something();
  }
  task_close();

However, if the event is signaled from an interrupt, a race condition can occur during execution of event_wait() which can result in an inconsistent state of the task. The task will wait forever and never receive the event. This can happen if the interrupt is enabled and gets triggered during the event_wait() call.

The solution is to do the following:

  • disable the interrupt from start, and also in the isr, so it is not automatically re-enabled.
  • use event_wait_ex() instead and provide it with a callback
  • in the callback: enable the interrupt
void myCallback(void) {
  doStuffBeforeWait(); // this is a perfect place to e.g turn off radio power before entering wait
  enableEventSignalingInterrupt();
}

void task() {
  task_open();
  for(;;) {
    event_wait_ex(anEvt, myCallback);
    do_something();
  }
  task_close();
}

cocoos's People

Contributors

cocoos avatar ivankravets avatar matteofranceschini avatar nodtem66 avatar ptrxt avatar purplealien avatar zanoz 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cocoos's Issues

Pic16 & Pic18 example need

I see that almost all of the issues for xc8.
You are using cocoOS and writing this cocoOS project but why don't you prepare a sample project for pic16 & Pic18.
An example project for xc8 can increase the popularity of cocoOS as much as you expect.
One example is very important for new learners and those looking for a new RTOS like me.
Rather than say : do that like that..
Could someone add a sample project that how to use cocoOS for Pic16& Pic18 mcu.
Regards

Error when using `msg_post`

Upon usage of msg_post within my project, I get a compiler error indicating:
inc/cocoos.h:89:29: error: case label '10060' not within a switch statement

The line looks like this:
case (__LINE__+ofs):

Any suggestion on how to get past this error?

Unable to compile using SDCC

Compiling os_msgqueue.c gives the error :-

/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:153: syntax error: token -> 'uint8_t' ; column 8
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:157: syntax error: token -> 'uint16_t' ; column 9
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:155: error 20: Undefined identifier 'head'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:162: error 20: Undefined identifier 'msgSz'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:163: error 20: Undefined identifier 'dst'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:163: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:163: error 20: Undefined identifier 'src'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:163: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:166: error 20: Undefined identifier 'head'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:168: warning 85: in function queue_push unreferenced function argument : 'msg'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:184: syntax error: token -> 'uint8_t' ; column 11
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:195: syntax error: token -> 'uint16_t' ; column 12
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:201: syntax error: token -> 'uint8_t' ; column 15
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:209: syntax error: token -> 'uint8_t' ; column 15
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:186: error 20: Undefined identifier 'tail'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:198: error 20: Undefined identifier 'tail'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:198: error 20: Undefined identifier 'tail'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:199: error 20: Undefined identifier 'tail'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:199: error 20: Undefined identifier 'msgSz'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:202: error 20: Undefined identifier 'msgSz'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:203: error 20: Undefined identifier 'dst'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:203: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:207: error 20: Undefined identifier 'msgSz'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:212: error 20: Undefined identifier 'messageTimedOut'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:214: error 20: Undefined identifier 'messagePeriodic'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:220: error 20: Undefined identifier 'messageTimedOut'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:220: error 20: Undefined identifier 'messagePeriodic'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:220: error 20: Undefined identifier 'messageTimedOut'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:221: error 20: Undefined identifier 'dst'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_msgqueue.c:221: error 20: Undefined identifier 'msgSz'

And os_task.c give the error :-

/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:74: syntax error: token -> 'tcb' ; column 7
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:77: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:77: error 47: indirections to different types assignment   
from type 'struct tcb near* fixed'
  to type 'int fixed'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:78: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:78: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:79: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:79: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:83: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:83: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:84: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:84: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:85: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:85: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:86: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:86: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:87: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:87: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:88: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:88: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:89: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:89: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:90: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:90: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:93: error 20: Undefined identifier 'task'
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:93: error 27: Pointer required
/Users/adityaxavier/Development/STM/CocoOS/Libraries/cocoOS/src/os_task.c:93: error 27: Pointer required

continuous testing for compilation

I see people trying to use this project with c compilers other than gcc, while the main author only supports gcc.
Should we set up the continuous testing for at least the successful gcc compilation?
The project solves some pain. Naturally, people will try to add more compiler supports to use it in their projects.

new PR for easy porting

I made a PR that allow to define os_enable_interrupt() and os_disable_interrupt() macros using compiler flags (-D). This make more easy to port cocoOS to any architecture whit out modify the os_port.h header file.

@cocoOS take a look and feedback please.

Add example folder

I have done some simple projects using cocoOS. I was thinking about adding a folder of examples to the project with several. Of course well documented and grouped by platform.
Tell me @cocoOS, What do you think about this?

Function prototypes

There are several functions that do not have correct prototypes in the headers (missing void when function takes no parameters) and strict-prototypes is used in GCC. I made a pull request that fixes them.

compile problem of reentrant in XC8

Dear:
I have compile the cocoos in xc8, , the original version is ok,
and it report an error, after I add the os_tick() into timer ISR.
the error said that there are reentrant issue, and blablabla.... when I "\" the os_tick(), it will fine.
this is the error:"os_task.c:478: advisory: (1510) non-reentrant function "_os_task_clear_wait_queue" appears in multiple call graphs and has been duplicated by the compiler"

I know the different if reentrant function and usual function. But I am not sure it is right or not to add reentrant before every function in the code...
I don't know why you guys works well. maybe the compiler is different...
I use mplabx and xc8 v1.44
Thanks for any following..

BR
Zona.W

EventQueue_t size issue

Hi!
I'm working with xc8 v2.05 on a PIC16, with 9 tasks and 12 events.

I noticed that in os_event.h at line 89 the #ifdef checks the N_TOTAL_EVENTS definition, but it looks like my compiler (and maybe others?) do not find N_TOTAL_EVENTS during compilation, therefore defining EVENT_QUEUE_SIZE equals to 1.

In case of more than 8 events, this will overflow the event queue into the task data pointer. In the picture below, i have assigned to task 9 an event with id 11: as you can see it goes directly into the wrong memory area.

image

By fixing this line of code, the result is as the second picture here: the eventlist has now two bytes of space in memory and does not overflow anymore.

image

hope this helps!

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.