06.08.2013 Views

Embedding OS in AVR microcontrollers - DAIICT Intranet

Embedding OS in AVR microcontrollers - DAIICT Intranet

Embedding OS in AVR microcontrollers - DAIICT Intranet

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Embedd<strong>in</strong>g</strong> <strong>OS</strong> <strong>in</strong> <strong>AVR</strong> <strong>microcontrollers</strong><br />

Prof. Prabhat Ranjan<br />

(prabhat_ranjan@da-iict.org)<br />

DA-IICT, Gandh<strong>in</strong>agar


Operat<strong>in</strong>g System Fundamentals<br />

➲ The kernel is the core component with<strong>in</strong> an<br />

operat<strong>in</strong>g system<br />

➲ Operat<strong>in</strong>g systems such as L<strong>in</strong>ux employ<br />

kernels that allow users access to the computer<br />

seem<strong>in</strong>gly simultaneously<br />

➲ Multiple users can execute multiple programs<br />

apparently concurrently<br />

➲ Each execut<strong>in</strong>g program is a task under<br />

control of the operat<strong>in</strong>g system. If an operat<strong>in</strong>g<br />

system can execute multiple tasks <strong>in</strong><br />

this manner it is said to be multitask<strong>in</strong>g.


Why use multitask<strong>in</strong>g <strong>OS</strong>?<br />

➲ The use of a multitask<strong>in</strong>g operat<strong>in</strong>g system<br />

can simplify the design of what would otherwise<br />

be a complex software application:<br />

● The multitask<strong>in</strong>g and <strong>in</strong>ter-task communications<br />

features of the operat<strong>in</strong>g system allow the complex<br />

application to be partitioned <strong>in</strong>to a set of<br />

smaller and more manageable tasks.<br />

● The partition<strong>in</strong>g can result <strong>in</strong> easier software<br />

test<strong>in</strong>g, work breakdown with<strong>in</strong> teams, and code<br />

reuse.<br />

● Complex tim<strong>in</strong>g and sequenc<strong>in</strong>g details can be<br />

removed from the application code and become<br />

the responsibility of the operat<strong>in</strong>g system


Multitask<strong>in</strong>g Vs Concurrency<br />

➲ A conventional processor can only execute<br />

a s<strong>in</strong>gle task at a time - but by rapidly<br />

switch<strong>in</strong>g between tasks a multitask<strong>in</strong>g operat<strong>in</strong>g<br />

system can make it appear as if<br />

each task is execut<strong>in</strong>g concurrently.


Schedul<strong>in</strong>g<br />

➲ The scheduler is the part of the kernel responsible<br />

for decid<strong>in</strong>g which task should be<br />

execut<strong>in</strong>g at any particular time. The kernel<br />

can suspend and later resume a task many<br />

times dur<strong>in</strong>g the task lifetime.<br />

➲ The schedul<strong>in</strong>g policy is the algorithm used<br />

by the scheduler to decide which task to<br />

execute at any po<strong>in</strong>t <strong>in</strong> time. The policy of a<br />

(non real time) multi user system will most<br />

likely allow each task a "fair" proportion of<br />

processor time. The policy used <strong>in</strong> real time


Context Switch<strong>in</strong>g<br />

➲ As a task executes it utilizes the processor /<br />

microcontroller registers and accesses RAM<br />

and ROM just as any other program. These<br />

resources together (the processor registers,<br />

stack, etc.) comprise the task execution<br />

context<br />

➲ A task is a sequential piece of code - it does<br />

not know when it is go<strong>in</strong>g to get suspended<br />

or resumed by the kernel and does not<br />

even know when this has happened


➲ To prevent this type of error it is essential<br />

that upon resumption a task has a context<br />

identical to that immediately prior to its suspension.<br />

➲ Kernel is responsible for ensur<strong>in</strong>g this - and<br />

does so by sav<strong>in</strong>g the context of a task as it<br />

is suspended. When the task is resumed its<br />

saved context is restored by the operat<strong>in</strong>g<br />

system kernel prior to its execution.<br />

➲ Process of sav<strong>in</strong>g the context of a task be<strong>in</strong>g<br />

suspended and restor<strong>in</strong>g at resumption<br />

is called context switch<strong>in</strong>g.


Real Time Applications<br />

➲ Real time operat<strong>in</strong>g systems (RT<strong>OS</strong>'s) objectives<br />

are very different to those of non<br />

real time systems<br />

➲ The different objective is reflected <strong>in</strong> the<br />

schedul<strong>in</strong>g policy<br />

➲ Real time / embedded systems are designed<br />

to provide a timely response to real<br />

world events<br />

➲ Events occurr<strong>in</strong>g <strong>in</strong> the real world can have<br />

deadl<strong>in</strong>es before which the real time / embedded<br />

system must respond and the<br />

RT<strong>OS</strong> schedul<strong>in</strong>g policy must ensure these<br />

deadl<strong>in</strong>es are met.


Real Time Applications<br />

➲ To achieve this objective assign a priority to<br />

each task<br />

➲ The schedul<strong>in</strong>g policy of the RT<strong>OS</strong> is to ensure<br />

that the highest priority task (that is<br />

able to execute) is given process<strong>in</strong>g time<br />

➲ This may require shar<strong>in</strong>g process<strong>in</strong>g time<br />

"fairly" between tasks of equal priority if they<br />

are ready to run simultaneously


RT Example<br />

➲ Basic example of this is a real time system<br />

that <strong>in</strong>corporates a keypad and LCD.<br />

➲ A user must get visual feedback of each key<br />

press with<strong>in</strong> a reasonable period - if the<br />

user cannot see that the key press has<br />

been accepted with<strong>in</strong> this period the software<br />

product will at best be awkward to<br />

use.<br />

➲ If the longest acceptable period was 100ms<br />

- any response between 0 and 100ms<br />

would be acceptable.


➲ Now assume the real time system is also<br />

perform<strong>in</strong>g a control function that relies on a<br />

digitally filtered <strong>in</strong>put.<br />

➲ The <strong>in</strong>put must be sampled, filtered and the<br />

control cycle executed every 2ms.<br />

➲ For correct operation of the filter the temporal<br />

regularity of the sample must be accurate<br />

to 0.5ms.


FreeRT<strong>OS</strong> Features<br />

➲ Choice of RT<strong>OS</strong> schedul<strong>in</strong>g policy<br />

● Pre-emptive:<br />

Always runs the highest available task. Tasks of<br />

identical priority share CPU time (fully pre-emptive<br />

with round rob<strong>in</strong> time slic<strong>in</strong>g).<br />

● Cooperative:<br />

Context switches only occur if a task blocks, or explicitly<br />

calls taskYIELD().<br />

➲ Message queues<br />

➲ Semaphores [via macros]<br />

➲ Trace visualisation ability<br />

➲ Majority of source code common to all supported<br />

development tools


Design Philosophy<br />

➲ Nearly all the code is written <strong>in</strong> C, with only<br />

a few assembler functions where completely<br />

unavoidable.<br />

➲ The RT<strong>OS</strong> kernel uses multiple priority lists.<br />

This provides maximum application design<br />

flexibility. Any number of tasks can share<br />

the same priority.<br />

➲ Simple, Portable, Concise


Nam<strong>in</strong>g Conventions<br />

➲ Variables<br />

● Variables of type char are prefixed c<br />

● Variables of type short are prefixed s<br />

● Variables of type long are prefixed l<br />

● Variables of type float are prefixed f<br />

● Variables of type double are prefixed d<br />

● Enumerated variables are prefixed e<br />

● Other types (e.g. structs) are prefixed x<br />

● Po<strong>in</strong>ters have an additional prefixed p, for example<br />

a po<strong>in</strong>ter to a short will have prefix ps<br />

● Unsigned variables have an additional prefixed<br />

u, for example an unsigned short will have prefix<br />

us


➲ Functions<br />

● File private functions are prefixed with prv<br />

● API functions are prefixed with their return type,<br />

as per the convention def<strong>in</strong>ed for variables<br />

● Function names start with the file <strong>in</strong> which they<br />

are def<strong>in</strong>ed. For example vTaskDelete is def<strong>in</strong>ed<br />

<strong>in</strong> task.c<br />

➲ Data Types<br />

● Data types are not directly referenced with<strong>in</strong> the<br />

RT<strong>OS</strong> kernel source code<br />

● each port has it's own set of def<strong>in</strong>itions.<br />

● char type is #def<strong>in</strong>ed to portCHAR<br />

● short data type is #def<strong>in</strong>ed to portSHORT


Application Programm<strong>in</strong>g Interface(API)


Task Creation<br />

➲ xTaskCreate - Create a new task and add<br />

it to the list of tasks that are ready to run<br />

➲ vTaskDelete - Remove a task from the<br />

RT<strong>OS</strong> real time kernels management. The<br />

task be<strong>in</strong>g deleted will be removed from all<br />

ready, blocked, suspended and event lists


Task Control<br />

➲ vTaskDelay - Delay a task for a given number<br />

of ticks<br />

➲ vTaskDelayUntil - Delay a task until a specified<br />

time<br />

➲ ucTaskPriorityGet - Obta<strong>in</strong> the priority of<br />

any task<br />

➲ vTaskPrioritySet - Set the priority of any<br />

task<br />

➲ vTaskSuspend - Suspend any task<br />

➲ vTaskResume - Resumes a suspended<br />

task


Kernel Control<br />

➲ vTaskStartScheduler - Starts the real time<br />

kernel tick process<strong>in</strong>g. After call<strong>in</strong>g the kernel<br />

has control over which tasks are executed<br />

and when.<br />

➲ vTaskEndScheduler - Stops the real time<br />

kernel tick. All created tasks will be automatically<br />

deleted and multitask<strong>in</strong>g (either preemptive<br />

or cooperative) will stop. Execution<br />

then resumes from the po<strong>in</strong>t where<br />

vTaskStartScheduler() was called, as if<br />

vTaskStartScheduler() had just returned


➲ vTaskSuspendAll - Suspends all real time<br />

kernel activity while keep<strong>in</strong>g <strong>in</strong>terrupts (<strong>in</strong>clud<strong>in</strong>g<br />

the kernel tick) enabled<br />

➲ xTaskResumeAll - Resumes real time kernel<br />

activity follow<strong>in</strong>g a call to vTaskSuspendAll<br />

(). After a call to xTaskResumeAll ()<br />

the kernel will take control of which task is<br />

execut<strong>in</strong>g at any time


Task Utilities<br />

➲ xTaskGetTickCount - count of ticks s<strong>in</strong>ce<br />

vTaskStartScheduler was called<br />

➲ xTaskGetNumberOfTasks - number of tasks<br />

that the real time kernel is currently manag<strong>in</strong>g<br />

➲ vTaskList - Lists all the current tasks


Queue Management<br />

➲ xQueueCreate - Creates a new queue <strong>in</strong>stance<br />

➲ xQueueSend - Post an item on a queue<br />

➲ xQueueReceive - Receive an item from a<br />

queue<br />

➲ xQueueSendFromISR - Post an item on a<br />

queue(safe from iSR)<br />

➲ xQueueReceiveFromISR - Receive an item<br />

from a queue (safe from ISR)


Semaphores<br />

➲ vSemaphoreCreateB<strong>in</strong>ary<br />

➲ xSemaphoreTake<br />

➲ xSemaphoreGive<br />

➲ xSemaphoreGiveFromISR


Customization<br />

➲ FreeRT<strong>OS</strong>/Demo/<strong>AVR</strong>_ATMega323_W<strong>in</strong><br />

<strong>AVR</strong>/FreeRT<strong>OS</strong>Config.h<br />

portUSE_PREEMPTION 1<br />

portCPU_CLOCK_HZ ( ( unsigned portLONG )<br />

8000000 )<br />

portTICK_RATE_HZ ( ( portTickType ) 1000 )<br />

portMAX_PRIORITIES ( ( unsigned portCHAR )<br />

4 )


➲ configCPU_CLOCK_HZ<br />

● Enter the frequency <strong>in</strong> Hz at which the <strong>in</strong>ternal<br />

processor core will be execut<strong>in</strong>g. This value is<br />

required <strong>in</strong> order to correctly configure timer peripherals.(Xtal<br />

– 4300000)<br />

➲ configTICK_RATE_HZ<br />

● frequency of the RT<strong>OS</strong> tick <strong>in</strong>terrupt<br />

● tick <strong>in</strong>terrupt is used to measure time<br />

● a higher tick frequency means time can be measured<br />

to a higher resolution


TICK_RATE<br />

● high tick frequency -> kernel will use more CPU<br />

time so be less efficient<br />

● RT<strong>OS</strong> demo applications all use a tick rate of<br />

1000Hz. This is used to test the kernel and is<br />

higher than would normally be required.<br />

● More than one task can share the same priority.<br />

The kernel will share processor time between<br />

tasks of the same priority by switch<strong>in</strong>g between<br />

the tasks dur<strong>in</strong>g each RT<strong>OS</strong> tick.<br />

● A high tick rate frequency will therefore also<br />

have the effect of reduc<strong>in</strong>g the 'time slice' given<br />

to each task.


➲ configMAX_PRIORITIES<br />

● The number of priorities available to the application<br />

● Any number of tasks can share the same priority<br />

● Each available priority consumes RAM with<strong>in</strong> the<br />

kernel so this value should not be set any higher<br />

than actually required by your application


INCLUDE Parameters<br />

➲ The macros start<strong>in</strong>g 'INCLUDE' allow those<br />

components of the real time kernel not utilized<br />

by application to be excluded from<br />

build<br />

➲ Ensures the RT<strong>OS</strong> does not use any more<br />

ROM or RAM than necessary<br />

● #def<strong>in</strong>e INCLUDE_vTaskDelete 1<br />

(change to 0 to exclude)


DEMO APPLICATION


Source Directory Structure : conta<strong>in</strong>s real time<br />

kernel source code


Demo Dir Structure


Demo files<br />

➲ flash.c<br />

● Creates upto eight tasks, each of which flash an<br />

LED at a different rate. The first LED flashes every<br />

125ms, the second every 250ms, the third<br />

every 375ms, etc.<br />

● The LED flash tasks provide <strong>in</strong>stant visual feedback.<br />

They show that the scheduler is still operational.<br />

● On <strong>AVR</strong>, by default, PORT B is used


comtest.c<br />

● Creates two tasks that operate on an <strong>in</strong>terrupt<br />

driven serial port.<br />

● A loopback connector should be used so that<br />

everyth<strong>in</strong>g that is transmitted is also received.<br />

Rx/Tx should be shorted.<br />

● The first task repeatedly sends a str<strong>in</strong>g to a<br />

queue, character at a time.<br />

● The serial port <strong>in</strong>terrupt will empty the queue<br />

and transmit the characters.<br />

● The task blocks for a pseudo random period before<br />

resend<strong>in</strong>g the str<strong>in</strong>g.


lockQ.c<br />

➲ Creates six tasks that operate on three<br />

queues as follows:<br />

● The first two tasks send and receive an <strong>in</strong>crement<strong>in</strong>g<br />

number to/from a queue. One task acts<br />

as a producer and the other as the consumer.<br />

The consumer is a higher priority than the producer<br />

and is set to block on queue reads. The<br />

queue only has space for one item - as soon as<br />

the producer posts a message on the queue the<br />

consumer will unblock, preempt the producer,<br />

and remove the item.


● The second two tasks work the other way<br />

around. Aga<strong>in</strong> the queue used only has enough<br />

space for one item. This time the consumer has<br />

a lower priority than the producer. The producer<br />

will try to post on the queue block<strong>in</strong>g when the<br />

queue is full. When the consumer wakes it will<br />

remove the item from the queue, caus<strong>in</strong>g the<br />

producer to unblock, pre-empt the consumer,<br />

and immediately re-fill the queue.


● The last two tasks use the same queue producer<br />

and consumer functions. This time the queue<br />

has enough space for lots of items and the tasks<br />

operate at the same priority. The producer will<br />

execute, plac<strong>in</strong>g items <strong>in</strong>to the queue. The consumer<br />

will start execut<strong>in</strong>g when either the queue<br />

becomes full (caus<strong>in</strong>g the producer to block) or a<br />

context switch occurs (tasks of the same priority<br />

will time slice).


death.c<br />

● Create a s<strong>in</strong>gle persistent task which periodically<br />

dynamically creates another four tasks. The orig<strong>in</strong>al<br />

task is called the creator task, the four tasks<br />

it creates are called suicidal tasks.<br />

● Two of the created suicidal tasks kill one other<br />

suicidal task before kill<strong>in</strong>g themselves - leav<strong>in</strong>g<br />

just the orig<strong>in</strong>al task rema<strong>in</strong><strong>in</strong>g.


● The creator task must be spawned after all of<br />

the other demo application tasks as it keeps a<br />

check on the number of tasks under the scheduler<br />

control. The number of tasks it expects to<br />

see runn<strong>in</strong>g should never be greater than the<br />

number of tasks that were <strong>in</strong> existence when the<br />

creator task was spawned, plus one set of four<br />

suicidal tasks. If this number is exceeded an error<br />

is flagged.


flop.c<br />

● Creates eight tasks, each of which loops cont<strong>in</strong>uously<br />

perform<strong>in</strong>g an (emulated) float<strong>in</strong>g po<strong>in</strong>t<br />

calculation.<br />

● All the tasks run at the idle priority and never<br />

block or yield. This causes all eight tasks to time<br />

slice with the idle task.<br />

● Runn<strong>in</strong>g at the idle priority means that these<br />

tasks will get pre-empted any time another task<br />

is ready to run or a time slice occurs.<br />

● More often than not the pre-emption will occur<br />

mid calculation, creat<strong>in</strong>g a good test of the<br />

schedulers context switch mechanism - a calculation<br />

produc<strong>in</strong>g an unexpected result could be a<br />

symptom of a corruption <strong>in</strong> the context of a task.


<strong>in</strong>teger.c<br />

➲ This does the same as flop.c, but uses variables<br />

of type long <strong>in</strong>stead of type double.<br />

➲ As with flop.c, the tasks created <strong>in</strong> this file<br />

are a good test of the scheduler context<br />

switch mechanism.<br />

➲ The processor has to access 32-bit variables<br />

<strong>in</strong> two or four chunks (depend<strong>in</strong>g on<br />

the processor).<br />

➲ The low priority of these tasks means there<br />

is a high probability that a context switch<br />

will occur mid calculation.


pollQ.c<br />

● This is a very simple queue test.<br />

● BlockQ.c is a more comprehensive version.<br />

● Creates two tasks that communicate over a s<strong>in</strong>gle<br />

queue.<br />

● One task acts as a producer, the other a consumer.


ma<strong>in</strong>.c<br />

➲ It creates all the various tasks<br />

➲ One task check keeps a track of all the<br />

tasks and stops flash<strong>in</strong>g the LED, if any<br />

task gives error<br />

➲ LED 0-2, flashes as per tasks <strong>in</strong> flash.c<br />

➲ LED 4-5 flashes as per serial communication<br />

Tx/Rx<br />

➲ Comment various tasks and try to see the<br />

effect.<br />

➲ Try to create a new task by yourself


Thank you

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!