Skip to content

Commit

Permalink
Merge pull request #1 from MannyPeterson/develop
Browse files Browse the repository at this point in the history
Development changes for release 0.2.2
  • Loading branch information
MannyPeterson authored Aug 8, 2020
2 parents ab3be35 + c5501b5 commit 963156e
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 51 deletions.
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/MannyPeterson/HeliOS/blob/master/LICENSE.md) ![GitHub last commit](https://img.shields.io/github/last-commit/MannyPeterson/HeliOS) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/MannyPeterson/HeliOS)
# Overview
HeliOS is an embedded operating system that is free for anyone to use. While called an operating system for simplicity, HeliOS is better described as a multitasking kernel for embedded systems. HeliOS is very small. In fact, it is small enough to run on most 8-bit microcontrollers including the popular AVR based Arduino Uno. Written entirely in C, HeliOS runs on a variety of microcontrollers and integrates easily into any project. HeliOS is also easy to learn with an Application Programming Interface (API) consisting of only 20 function calls. HeliOS contains the following key features:
* Cooperative Multitasking (Runtime Balanced)
HeliOS is an embedded operating system that is free for anyone to use. While called an operating system for simplicity, HeliOS is better described as a multitasking kernel for embedded systems. HeliOS is very small. In fact, it is small enough to run on most 8-bit microcontrollers including the popular AVR based Arduino Uno. Written entirely in C, HeliOS runs on a variety of microcontrollers and integrates easily into any project. HeliOS is also easy to learn with an Application Programming Interface (API) consisting of only 21 function calls. HeliOS contains the following key features:
* Cooperative Multitasking (Run-time Balanced)
* Event Driven Multitasking
* Task Notification/Messaging
* Timers
* Managed Memory
* Non-Preemptive (no mutexs! no deadlocks! no race conditions! no headaches!)

The HeliOS scheduler implements two types of multitasking: cooperative and event driven. Unlike many cooperative multitasking embeded operating systems, which use a round-robin scheduling strategy. HeliOS's scheduler implements a runtime balanced strategy which ensures tasks with shorter runtimes are scheduled for execution more frequently than tasks with longer runtimes. This way all running tasks receive approximately equal total runtime without using context switching. The other option in HeliOS is event driven multitasking, which uses the wait/notify and timer interfaces. Mixing cooperative and event driven tasks is not a problem.
As noted in the key features, HeliOS supports two types of multitasking: cooperative and event driven. Cooperative multitasking embedded operating systems and task schedulers often use a round-robin scheduling strategy. However, HeliOS uses a run-time balanced strategy which ensures tasks with shorter run-times are prioritized over tasks with longer run-times. This ensures all running tasks receive approximately equal total run-time without using context switching. The other multitasking option available in HeliOS is event driven multitasking, which uses the wait/notify and timer interfaces. Mixing cooperative and event driven tasks in HeliOS is not a problem.
# Why HeliOS?
There are already so many great and proven RTOS and scheduler options available, then why HeliOS? That is certainly a valid question. HeliOS was never intended to replace or compete with the other options already available today (if you have not checked out FreeRTOS - you should, it is nothing short of an amazing RTOS for embedded and is more accessible today than ever before through the Arduino Library Manager). HeliOS, however, due to its size and simplicity, is intended to play in the space between RTOS's and task schedulers. HeliOS is tiny (smaller than FreeRTOS), easy to use and a great place to start for enthusiasts, hobbyists and researchers.
# Getting Started
## Arduino
Because HeliOS is compliant with the Arduino 1.5 (rev. 2.2) Library Specification, getting up and running is quick and easy. HeliOS can be installed directly from the Arduino Library Manager or downloaded and installed manually. Both options are described [here](https://www.arduino.cc/en/Guide/Libraries#toc3). Once up and running, check out one of the example sketches or refer to the HeliOS Programmer's Guide in the Documentation section.
Expand Down Expand Up @@ -53,9 +55,9 @@ void taskBlink(int id_) {

void setup() {
xHeliOSSetup();

pinMode(LED_BUILTIN, OUTPUT);

int id = xTaskAdd("TASKBLINK", &taskBlink);
xTaskWait(id);
xTaskSetTimer(id, 1000000);
Expand All @@ -67,16 +69,17 @@ void loop() {
```
# Releases
All releases, including the current release, can be found [here](https://github.com/MannyPeterson/HeliOS/releases).
* 0.2.1 - The first official release.
* 0.2.2 - Additional function calls, minor fixes and documentation enhancements
* 0.2.1 - The first official release
# Contributing
While all contributions are welcome, contributions are needed most in the following areas:
* HeliOS Programmer's Guide
* Performance Enhancements
* Stability Enhancements
* Testing
Please contact the author through GitHub if you are interested in contributing.
To contribute, please create an issue and indicate how you would like to contribute. Please fork from the **develop** branch as **master** is kept even with the current release.
# License
HeliOS is copyrighted open source software licensed under the Free Software Foundation's GNU General Public License Version 3. The license can be found [here](/LICENSE.md).
# Important
HeliOS is **not** certified for use in safety-critical applications. The HeliOS source code, whether in full or in part, must **never** be used in applications where a risk to life exists.
HeliOS is **not** certified for use in safety-critical applications. The HeliOS source code, whether in full or in part, must **never** be used in applications where a risk to life exists.
242 changes: 237 additions & 5 deletions extras/HeliOS_Programmers_Guide.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,243 @@
# HeliOS Programmer's Guide
This guide contains documentation of HeliOS and its Application Programming Interface (API). This is a work in progress.
This guide contains documentation of HeliOS and its Application Programming Interface (API). This guide a work in progress.
# Multitasking
HeliOS provides two types of multitasking: cooperative and event driven multitasking. Both types can be used together. This section provides an explanation of and how to use each.
## Cooperative Multitasking
The most straightforward type of multitasking in HeliOS is cooperative multitasking. Cooperative multitasking is best used in cases where continuous polling of a sensor or other device is required.

Any task with a state of **running** is scheduled cooperatively by the HeliOS scheduler. The **xTaskStart()** function call sets the state of any task, provided it is not in an **errored** state, to **running**. However, just because a task is in a **running** state, does not guarantee the scheduler will schedule the task for execution. A task in a **running** state will only be scheduled for execution if (1) it is the only task in a **running** state, or (2) it is the task with the least total run-time.

This cooperative multitasking strategy is called **balanced run-time**. This strategy allows the HeliOS scheduler to ensure that all tasks in a **running** state will receive approximately the same amount of run-time within any given period. The total run-time of a task can be obtained using the **xTaskGetInfo()** function call and inspecting the **totalRuntime** member of the **xTaskGetInfoResult** structure.

As a practical example of how the balanced run-time strategy works, imagine a microcontroller with two tasks. Both tasks are in a **running** state and each task's run-time differs from the other. Task "A" has a 5 microsecond run-time and task "B" has a 50 microsecond run-time. Assuming each task's run-time remains constant, Task "A" will be executed 10 times for every one time task "B" executed. This ensures that task "A" receives approximately the same total run-time as task "B" without using priorities or context switching.

If the run-time of either task "A" or "B" were to change during run-time, the HeliOS scheduler would dynamically adjust the schedule to ensure the total run-times of both tasks would remain approximately equal.

It is important to note that the use of function calls like **delay()** must be avoided. If specific timing requirements exists, then event driven multitasking must be used. See the section on **Event Driven Multitasking** for further details.

Below is an Arduino example of how two tasks are added to HeliOS and scheduled cooperatively.

```C
#include <HeliOS_Arduino.h>

/*
* Create the first task "A"
*/
void taskA(int id_) {
// DO SOMETHING
}

/*
* Create the second task "B"
*/
void taskB(int id_) {
// DO SOMETHING
}

void setup() {
/*
* xHeliOSSetup() must be the first function call
* made to initialize HeliOS and its data structures
*/
xHeliOSSetup();

/*
* Declare and initialize an int to temporarily hold the
* task id.
*/
int id = 0;

/*
* Pass the task friendly name and function to xTaskAdd()
* to add the task to HeliOS. xTaskAdd() will return a
* task id greater than zero if the task is added unsuccessfully.
*/
id = xTaskAdd("TASKA", &taskA);

/*
* Pass the task id of the task to set its state from stopped
* to running.
*/
xTaskStart(id);

/*
* Pass the task friendly name and function to xTaskAdd()
* to add the task to HeliOS. xTaskAdd() will return a
* task id greater than zero if the task is added unsuccessfully.
*/
id = xTaskAdd("TASKB", &taskB);

/*
* Pass the task id of the task to set its state from stopped
* to running.
*/
xTaskStart(id);
}

void loop() {
/*
* Pass control to the the HeliOS scheduler. xHeliOSLoop() should
* be the only code inside the microcontroller project's
* main loop.
*/
xHeliOSLoop();
}
```
## Event Driven Multitasking
# Notification & Timers
## Notification
## Timers
The other type of multitasking supported by HeliOS is event driven multitasking. Event driven works as its name suggests. The HeliOS scheduler will only schedule an event driven task for execution when an event is raised. Any tasking in a **waiting** state is considered to be using event driven multitasking. To place a task in the **waiting** state, the **xTaskWait()** function call must be called. The HeliOS scheduler supports two types of events. The first is a notification event and the second is a timer event. Both types are covered in more detail below.
### Notification
A notification occurs when the **xTaskNotify()** function call occurs. All tasks in the **waiting** state will respond to notification events, even tasks configured with a timer. Calling the **xTaskNotify()** function call on tasks in a **stopped** or **running** state has no affect. When calling **xTaskNotify()** the notification bytes and value must be specified along with the id of the receiving task. A notification value is a small character buffer (default size is 16 bytes). The notification bytes is the size of the notification value contained in the character buffer (or notification value). For example, **xTaskNotify(3, 5, "ABCDE")** would send task 3 a 5 byte notification value of "ABCDE". When task 3 receives the notification, it will use the notification bytes to determine the number of bytes to read from the notification value. It is the task notification bytes and value feature of HeliOS that allows inter-task messaging as part of the wait/notify functionality.
Below is an Arduino example of two tasks. Task "A" continuously sends notifications to task "B".
```C
#include <HeliOS_Arduino.h>
/*
* Create the first task "A"
*/
void taskA(int id_) {
/*
* Obtain the task id of task "B" using its friendly name
* since it should not be assumed that task "B" will always
* have a task id of 2. Then pass then send a 5 byte notification
* value with "HELLO" in the character buffer.
*/
xTaskNotify(xTaskGetId("TASKB"), 5, "HELLO");
}
/*
* Create the second task "B"
*/
void taskB(int id_) {
/*
* Obtain the notification bytes and value from the xTaskGetInfoResult
* structure by first making a call to the xTaskGetInfo() function call
* using the task's id stored in id_.
*/
struct xTaskGetInfoResult* res = xTaskGetInfo(id_);
/* Because xTaskInfo() can return a null pointer, always check
* that the structure's pointer is not null before accessing
* its members.
*/
if(res) {
/*
* res->notificationBytes contains the notification bytes
* res->notificationValue contains the notification value
*/
}
/* Always call xMemFree() to free the managed memory allocated by
* xTaskGetInfo();
*/
xMemFree(res);
}
void setup() {
/*
* xHeliOSSetup() must be the first function call
* made to initialize HeliOS and its data structures
*/
xHeliOSSetup();
/*
* Declare and initialize an int to temporarily hold the
* task id.
*/
int id = 0;
/*
* Pass the task friendly name and function to xTaskAdd()
* to add the task to HeliOS. xTaskAdd() will return a
* task id greater than zero if the task is added unsuccessfully.
*/
id = xTaskAdd("TASKA", &taskA);
/*
* Pass the task id of the task to set its state from stopped
* to running.
*/
xTaskSart(id);
/*
* Pass the task friendly name and function to xTaskAdd()
* to add the task to HeliOS. xTaskAdd() will return a
* task id greater than zero if the task is added unsuccessfully.
*/
id = xTaskAdd("TASKB", &taskB);
/*
* Pass the task id of the task to set its state from stopped
* to waiting.
*/
xTaskWait(id);
}
void loop() {
/*
* Pass control to the the HeliOS scheduler. xHeliOSLoop() should
* be the only code inside the microcontroller project's
* main loop.
*/
xHeliOSLoop();
}
```

### Timer
The other event type is a timer event. It functions like an egg timer for tasks. After a certain duration has passed, the HeliOS scheduler schedules the task for execution. Like all tasks using event driven multitasking, the task state must be **waiting**. To configure a task's timer, the **xTaskSetTimer()** function call must be called which specifies the duration, in microseconds, that must elapse before HeliOS executes the task. HeliOS will automatically reset the timer every time it elapses. The timer can also be reset by calling the **xTaskresetTimer()** function call. Task timers are recommended over free running tasks that are cooperatively scheduled because they offer greater control over the timing of microcontroller operations. Below is an example of an event driven task on Arduino. In this example, task "A" will be executed every 1,000,000 microseconds (1 second).

```C
#include <HeliOS_Arduino.h>

/*
* Create the first task "A"
*/
void taskA(int id_) {
// DO SOMETHING
}

void setup() {
/*
* xHeliOSSetup() must be the first function call
* made to initialize HeliOS and its data structures
*/
xHeliOSSetup();

/*
* Declare and initialize an int to temporarily hold the
* task id.
*/
int id = 0;

/*
* Pass the task friendly name and function to xTaskAdd()
* to add the task to HeliOS. xTaskAdd() will return a
* task id greater than zero if the task is added unsuccessfully.
*/
id = xTaskAdd("TASKA", &taskA);

/*
* Pass the task id of the task to set its state from stopped
* to waiting.
*/
xTaskWait(id);

/*
* Set the timer on the task to 1,000,000 microseconds.
*/
xTaskSetTimer(id, 1000000);
}

void loop() {
/*
* Pass control to the the HeliOS scheduler. xHeliOSLoop() should
* be the only code inside the microcontroller project's
* main loop.
*/
xHeliOSLoop();
}
```
# Critical Blocking
HeliOS implements cricitcal blocking which prevents some functions from being called that may alter the state of HeliOS during critical operations. Critical blocking is in effect while the scheduler is running and prevents functions like xTaskAdd() and xTaskRemove() from altering the state of the HeliOS. Thus, you cannot, for example, remove a task using xTaskRemove() while inside a running task. Functions that do not alter the state of HeliOS may be called during critical blocking. For example, function calls like xTaskGetInfo() may be called during critical blocking as they do not update the state of HeliOS.
# Data Types
Expand Down Expand Up @@ -148,4 +380,4 @@ None
### int TaskListSeek(int)
### struct xTaskGetListResult* xTaskGetList(int*)
### void xTaskSetTimer(int, int)
### void xTaskResetTimer(int)
### void xTaskResetTimer(int)
50 changes: 26 additions & 24 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,43 @@
# Datatypes (KEYWORD1)
#######################################

xTaskState KEYWORD1
xTaskState KEYWORD1

#######################################
# Functions (KEYWORD2)
#######################################

xHeliOSGetInfo KEYWORD2
xHeliOSLoop KEYWORD2
xHeliOSSetup KEYWORD2
xMemAlloc KEYWORD2
xMemFree KEYWORD2
xMemGetSize KEYWORD2
xMemGetUsed KEYWORD2
xTaskAdd KEYWORD2
xTaskClear KEYWORD2
xTaskGetId KEYWORD2
xTaskGetInfo KEYWORD2
xTaskGetList KEYWORD2
xTaskNotify KEYWORD2
xTaskNotifyClear KEYWORD2
xTaskRemove KEYWORD2
xTaskResetTimer KEYWORD2
xTaskSetTimer KEYWORD2
xTaskStart KEYWORD2
xTaskStop KEYWORD2
xTaskWait KEYWORD2
xHeliOSGetInfo KEYWORD2
xHeliOSLoop KEYWORD2
xHeliOSSetup KEYWORD2
xMemAlloc KEYWORD2
xMemFree KEYWORD2
xMemGetSize KEYWORD2
xMemGetUsed KEYWORD2
xTaskAdd KEYWORD2
xTaskClear KEYWORD2
xTaskGetId KEYWORD2
xTaskGetInfo KEYWORD2
xTaskGetList KEYWORD2
xTaskGetNotif KEYWORD2
xTaskNotify KEYWORD2
xTaskNotifyClear KEYWORD2
xTaskRemove KEYWORD2
xTaskResetTimer KEYWORD2
xTaskSetTimer KEYWORD2
xTaskStart KEYWORD2
xTaskStop KEYWORD2
xTaskWait KEYWORD2

#######################################
# Structures (KEYWORD3)
#######################################

xHeliOSGetInfoResult KEYWORD3
xTaskGetInfoResult KEYWORD3
xTaskGetListResult KEYWORD3
xTaskGetInfoResult KEYWORD3
xTaskGetListResult KEYWORD3
xTaskGetNotifResult KEYWORD3

#######################################
# Constants (LITERAL1)
#######################################
#######################################
8 changes: 4 additions & 4 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name=HeliOS
version=0.2.1
version=0.2.2
author=Manny Peterson
maintainer=Manny Peterson
sentence=The free embedded operating system.
paragraph=HeliOS is an embedded operating system that is free for anyone to use. While called an operating system for simplicity, HeliOS is better described as a multitasking kernel for embedded systems. HeliOS is very small. In fact, it is small enough to run on most 8-bit microcontrollers including the popular AVR based Arduino Uno. Written entirely in C, HeliOS runs on a variety of microcontrollers and integrates easily into any project. HeliOS is also easy to learn with an Application Programming Interface (API) consisting of only 20 function calls.
category=Uncategorized
paragraph=HeliOS is an embedded operating system that is free for anyone to use. While called an operating system for simplicity, HeliOS is better described as a multitasking kernel for embedded systems. HeliOS is very small. In fact, it is small enough to run on most 8-bit microcontrollers including the popular AVR based Arduino Uno. Written entirely in C, HeliOS runs on a variety of microcontrollers and integrates easily into any project. HeliOS is also easy to learn with an Application Programming Interface (API) consisting of only 21 function calls.
category=Timing
url=https://github.com/MannyPeterson/HeliOS
architectures=*
includes=HeliOS_Arduino.h
includes=HeliOS_Arduino.h
Loading

0 comments on commit 963156e

Please sign in to comment.