Introduction
OpenSwarm is an embedded operating system designed for miniature robots. It provides time-sliced pre-emptive threads for computational intensive tasks and events to execute short run-to-completion tasks. The use of event is a basic feature of OpenSwarm. Events are used for inter-process communication mechanism and provide a defined interface between functions. OpenSwarm also provides a hardware-independent environment to develop user applications.
As it can be seen in this figure, OpenSwarm is an operating system that executed user processes and provided a variety of hardware-independent function. Each process is single threaded and executed in a non-protected memory-space. Consequently, in OpenSwarm, a process shares the same properties as a thread and can be used interchangeably.
OpenSwarm consists of three parts:
- Hardware Abstraction Layer (HAL): It manages hardware signals and data. It converts hardware-independent into hardware-specific values/data and applies them on the I/O Devices. Similarly, values received from hardware are converted into hardware-independent data and send as events to subscribed processes.
- Event Module: This is a central element of OpenSwarm. It defines how events are processed and provides functions to create, register of, subscribe to, or delete events.
- Process Manager: It defines how processes are scheduled, created, suspended, released, and terminated.
Deploying on a New Robot
To deploy OpenSwarm on a new robot, only parts of the Process Manager and Hardware Abstraction Layer has to be reimplemented. Other functions can be used on any device.
A detailed description of “How to deploy OpenSwarm” will be added shortly. If you want to use OpenSwarm already, please contact us and we will give you all the information that you need.
Starting with OpenSwarm
If OpenSwarm has been deployed on your robot, you can start writing your first application.
OpenSwarm can be started and used by writing the following main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include "system.h" //this contains OpenSwarm int main(void){ Sys_Init_Kernel();//First, initialise OpenSwarm /* * Here you can start programs, register events, subscribe handler to events, etc. */ //Finally, you can start OpenSwarm -> this will execute all threads and I/O Sys_Start_Kernel(); while(1){ //Do something/nothing } } |
Create and Run a Thread
A thread can be defined as a simple function with no return value:
1 |
void thread_name(void); |
To start a thread just have to write a code that is similar to this main.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "system.h" //this contains OpenSwarm void thread_name(); int main(void){ Sys_Init_Kernel();//First, initialise OpenSwarm Sys_Start_Process(thread_name); Sys_Start_Kernel(); while(1){ //Do something/nothing } } void thread_name(){ //do something } |
Note that creating a thread requires a significant amount of time and memory. As a result, creating threads that return quickly are inefficient and the programmer should think of using event handler instead. After the thread returns, the process is terminated and deleted. It is recommended but not required to tell the operating system which threads are executed before the kernel starts.
How to Use Events
Events can be used in different ways (for process communication/synchronisation or to execute event handlers asynchronously). Before a event can be used, event has to be registered to tell OpenSwarm that this event can happen: (The event ID in this example is 0x12)
1 2 3 |
#define USER_EVENT_TEST 0x12 Sys_Register_Event(USER_EVENT_TEST); |
Following that, events with ID “USER_EVENT_TEST"
can be sent and received. To send an event, you can use:
1 |
Sys_Send_Event(USER_EVENT_TEST, (void *) data, (uint16) length_of_data); |
To receive an event, you have two options. You can subscribe an event handler, which gets executed asynchronously by occurrence of the event. Alternatively, you can block a thread until an event occurs (synchronously). In any case, you can define a condition function. Only if the condition function return true, the event is processed. For instance, an event-handler should only be executed when the event occurred is 250 times or the event has to reach a certain threshold.
The following code illustrates how to use events:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include "system.h" #define USER_EVENT_TEST 0x12 void thread_name(); bool condition(void *data); bool event_handler(uint16 pid, uint16 eventID, sys_event_data *data); int main(void){ Sys_Init_Kernel();//First, initialise OpenSwarm Sys_Start_Process(thread_name); Sys_Register_Event(USER_EVENT_TEST); //event_handler() gets executed every time USER_EVENT_TEST event occurs Sys_Subscribe_to_Event(USER_EVENT_TEST, SYS_PID, event_handler, condition); Sys_Start_Kernel();//start all threads, I/O devices, and manage events while(true){ //Do something/nothing sys_event_data *data = Sys_Wait_For_Condition(USER_EVENT_TEST, &condition);//block the system thread till the condition is met and return its value Sys_Clear_EventData(data);//free the memory that is consumed by the event } } void thread_name(){ uint16 value = 0; while(true){ //Send value as an event. (It uses 2 bytes) Send_Event( USER_EVENT_TEST, &value, 2); value++; } } bool condition(void *data){//wait till the event occurred 250x static uint8 counter = 1; if(counter < 250){ counter++; return false; //don't execute the event handler } counter = 1; return true; // execute the event handler } bool event_handler(uint16 pid, uint16 eventID, sys_event_data *data){ //do something } |
Want to read more?
If you want to know more about OpenSwarm (how to use and extend it), have a look at the documentation.