RTOS
The operating system, or RTOS (real-time operating system) as they're often called in the microcontroller world, is a system that can switch back and forth between different programs seemingly simultaneously, to give the illusion that more than one is running at a time. This means you can write each of the elements of your programs separately, making it much easier to create more sophisticated programs.
Do I want to use an RTOS?
Not always. Sometimes you need more precise control than an operating system can offer.The base element of time in the RTOS is called the tick. Each time a tick rolls around, the RTOS checks to see if there's a task with higher priority than the current task and then switches to that task. If a task blocks (sleeps), then the RTOS gives processor time to a lower priority task.
By default on the Make Controller, the RTOS tick is 1 millisecond. For most communications and control applications, this is just fine. However, in some sensing applications you need microsecond timing. So why not just make the RTOS tick shorter? Well, you can definitely do that but it takes the processor some small amount of time to switch between tasks. Once you get down much shorter than a millisecond, you're just spending most of your time switching between tasks, and not as much time running tasks.
So, ultimately it depends on your application whether or not you want to use the RTOS. Currently, most of the Make Controller API is based on the assumption that an RTOS is being used.
Tasks
The most important part of the RTOS is a task. You can have many tasks happening simultaneously although, as you might imagine, it's best to be as efficient as possible with your use of them. A task is just a function, really, except it allows you to sit inside it forever, sleeping when you need to wait for something. It's important to always sleep at some point - otherwise, the processor will never give time to any of the other tasks. All tasks have the same signature - they look like:void MyTask( void* parameter );
When you create a task, you need to specify a couple of things:
- its name (arbitrary)
- its priority - how important this task is relative to other tasks.
- the amount of memory to allocate it - this is a little touchy-feely, and is discussed in the Memory section of this tutorial.
TaskCreate( MyTask, "Mine", 1000, 0, 1 ); // create the task, called "Mine, withCheck the Task API at firwmareref...
void MyTask( void* parameter )
{
// initialization here
while( 1 ) // now loop forever
{
// do your task
}
}
Priority
When tasks are created, they are assigned a priority - from 0 to 5. Higher priority tasks will always run instead of tasks with lower priorities. And tasks that have the same priority take turns in a round robin process. The only time lower priority tasks get to run in a system with tasks with different priorities is when the higher priority tasks either sleep or are waiting for input from something.
It is a common source of problems to create a high priority task and then forget to sleep, allowing lower priority tasks to run. In Heavy the Blink task is run with the lowest priority, so if the Controller status LED stops blinking it might be an indication that some task is hogging the system.
Communication between tasks
When all your code is in one task, you never have to worry about different tasks accessing data and resources simultaneously. When you have multiple tasks, however, you do. The problem comes when you do an operation that has multiple parts. Task A starts working on the operation, but runs out of time. The operating system switches over to the other task, which then starts working on the same data. When the operating system switches back to the first task, it proceeds unaware of what might have happened. Disaster frequently results. Tasks sometimes need to communicate with each other. This is done with message queues and semaphores.
Message queues are a feature that allows tasks to safely send and receive data amongst themselves. A task can sit waiting for a message, using no processor time at all. Another task can post a message to the queue and the first will be woken up and will be given the message.
Semaphores are a way to serialize access to a resource in a thread-safe way.
Check the Semaphores and Queues sections for details on how to use these.
Shopping Cart