Showing posts with label rtos. Show all posts
Showing posts with label rtos. Show all posts

Wednesday, January 27, 2016

Understanding Blinky - part 2


This post will discuss the FreeRTOS itself. One of its main capabilities is to simulate a multitasking. We know each processor core can only be processing one task at a time, but when you change the task being processed quickly enough, you can pretend that all are being processed at the same time. FreeRTOS does that with the use of the scheduler, which is basically the piece of code that will choose which task will run. Every once in a while, the scheduler will stop the current task execution and handle the processor's control, along with the task's stack, to another task, that eventually will be stopped (or will hold its own execution, i.e. through a delay) and another will be assigned and so on.

http://www.freertos.org/implementation/a00004.html

Stack

Each task usually needs some memory to store some variables. This memory, on bare metal projects, is usually the RAM itself, with a well defined address within it. When talking about an RTOS, the RAM is divided into pieces, called stacks [1], and each piece will hold the task's memory (the size of the piece is defined when the task is created, on xCreateTask()'s parameters). This piece will also hold a few more information relevant to the task, such as the point where the code was stopped the last time, the processor's registers values, etc, thus it needs a minimal size, which is defined, in Blinky project, as configMINIMAL_STACK_SIZE. The developer should always think well how much memory the task needs in order not to have problems. The stack is usually bigger than it actually needs, as you better spare memory and don't have a stack overflow problem. Other points to be reviewed before determining the size are [2]:

  • The function call nesting depth
  • The number and size of function scope variable declarations
  • The number of function parameters

Priorities

Imagine you have three tasks running the whole time doing what they're were meant to do. When one task execution is stopped, how does the scheduler choose which task will run next? If the tasks have different priorities (defined on xCreateTask()'s parameters), then the highest priority will run [3]. Care must be taken in this situation, otherwise, one task may never run (imagine two tasks that never stop executing by they're own have higher priority than another: when one task is running, the other is always waiting in front of the line, so that the lowest priority is always in the back and never runs). The lowest priority is defined by tskIDLE_PRIORITY and the higher the number, the higher the priority.

Task states

I've talked about a few of the states, like when the task is blocked (for example, when the Sender stops for a delay), running or waiting to be executed, so let's check those states thoroughly [4]. The tasks can be in 4 states: Running (it is using the processor), Ready (it is waiting to be processed), Blocked (it is waiting for some event, temporal - such as a delay - or external - such as a queue or semaphore event; in this case, it is not running nor waiting to be processed) or Suspended (it explicitly entered this state through the function vTaskSuspend() and can only exit by another explicit call of the function xTaskResume(); in this state, it is also not running nor waiting to be processed).
The task will enter the Ready state when it is created, when the scheduler stops its execution, when the event that was blocking it occurs or when it exits the Suspended state. It will only enter the Running state when the scheduler says so.

http://www.freertos.org/RTOS-task-states.html

Idle Task

If there are no tasks on Ready state (waiting to run), there is always one simple task, with lowest priority level possible that will use the processor: the Idle Task [5]. Basically, what it does is to free the memory from deleted tasks (if there are any and if your application allow that). When at least one task has the priority as the Idle, it is possible to tell the Idle task to yield the execution as soon as possible when these other tasks are in a Ready state [6]. It is possible to run some code whenever the Idle Task is called by the use of the Idle Task Hook, although it is imperative that the function doesn't block the task (for instance, using a vTaskDelay() or waiting for a semaphore), if that is the case, you should write a task with the Idle Task priority (this will use more RAM, but will permit more flexibility).

configASSERT()

This function is quite important during the development phase. It is often used to check if the task execution is OK and can continue. For instance, when the Sender and Receiver tasks check whether the parameters are right, it does so with the use of the configASSERT() [7]. This function will call another function when there is a problem: vAssertCalled(), which, in this project, will stop the execution and place the application on a loop. This function should be written by the developer in order to facilitate the debug of the code. When the project is mature enough, it can be suppressed to avoid code overhead.


[1] http://www.freertos.org/Stacks-and-stack-overflow-checking.html
[2] http://www.freertos.org/FAQMem.html#StackSize
[3] http://www.freertos.org/RTOS-task-priority.html
[4] http://www.freertos.org/RTOS-task-states.html
[5] http://www.freertos.org/RTOS-idle-task.html
[6] http://www.freertos.org/a00110.html#configIDLE_SHOULD_YIELD
[7] http://www.freertos.org/a00110.html#configASSERT

Wednesday, January 13, 2016

First thoughts about RTOS

First of all, what is RTOS?
RTOS, as the name stands for, is a Real Time Operating System, on the same words on a different order, is a operating system with real time capabilities. As Jack the Ripper, let's think in parts (in Portuguese that's a good pun).



OS?
Imagine you're sitting on your chair, enjoying a nice IPA beer, reading a Ken Follett's book while listening to Pink Floyd in front of the warmth of the fire place. You're doing this 4 things at the same time, while some other automatic things are happening (you're breathing, your heart is pumping, your stomach is asking for help to digest the second pint of that strong beer, your liver is filtering your blood trying to get the alcohol away, etc). In order to do that, your brain has to manage everything at the same time, and it does, because it has a lot of parallel processing for the automatic things, but not so much for the non-automatic (drinking beer, read, etc). That's why we can't drive and talk to the phone without almost crashing or saying weird stuff. We can only concentrate well enough to do one thing at a time (some people say women can, but they can't, for me, that's rubbish).
The Operating System is like our brain, but a little better: it handles tasks by letting each be processed by a small amount of time and so it seems that everything is being processed at the same time. Think about your computer: all at the same time, you can move your mouse while typing and listening to music (ok, you can do much more than that). Today our processors have several cores (parallel processors), but a few year ago, there was only one processor to do all those things. So time was divided into small pieces, there was a task to read the keyboard, a task to read the mouse movements, a task to play music, a task to show something on the screen, etc, and each one used the processor for a piece and handed over to the next task, and so on. The Operating System decides which task will process at each piece of time, it will adjust the memory for that task and when the piece finishes, it will do it all over again, forever and ever.
There is actually a bit more to it, with all the drivers and stuff, but if you think about it, drivers are just tasks that talk to hardware more closely.


RT?
Imagine you're baking a nice sourdough bread [1], with that crispy outside and open crumb, your house is already smelling like a bakery, your neighbors are looking through the windows hoping you give them at least a piece of it, when you decide it's ready and you want to take it out of the oven. But you forgot the gloves, so you think "I can do it!". You quickly take the loaf of bread with your bare hands, throw it away on the kitchen floor and go straight to the sink to wash your hands while feeling very dumb and now the tip of your fingers are filled with bubbles. Of course you couldn't do it. The bread was too hot and by the time it started burning your fingers, you had to throw it away instantly. Now imagine your reaction didn't occur quickly enough and it took you 1.5 seconds more to throw the bread away. Your hands would be burned too, instead of just your fingers.
The real time factor means that the tasks will be processed and that they will be processed in a known period of time. For instance, you can configure your RTOS to run a task whenever a button is pressed and you know it won't take more than 30 ms to the task to be processed (the 30 ms is just an example and usually can be configured). On a common OS, this time can vary up to a few seconds and is usually not easily configurable.


Why should I use a RTOS?

If you just want to blink a LED or turn a Triac on, then you probably could go with a bare metal solution. Or even when the application is complex, but the memory restrains are severe, the RTOS overhead may be too much. But if you have to manage an HMI, with a custom keyboard and a screen, while writing some stuff to a SDCard and control some process, then the use of the OS can help you a lot. Not only can you abstract the time factor (you can pretend that everything is running at the same time), it's easier to test each task individually, since all the task needs should be constrained within its code. The code maintenance, scalability [2] and modularization are also facilitated, as you can develop to other platform and then just Ctrl+C Ctrl+V the code to your RTOS. The availability of code libraries also enhances the experience.

[1] http://yumarama.com/968/starter-from-scratch-intro/
[2] http://coverclock.blogspot.com.br/2012/04/all-interesting-problems-are.html