0% found this document useful (0 votes)
837 views

FreeRTOS Tutorial - Embedded Systems Learning Academy

This document provides an introduction to using FreeRTOS, an open source real-time operating system kernel for embedded systems. It describes FreeRTOS tasks, queues for inter-task communication, and semaphores. Examples are provided for simple tasks, queue usage, and controlling task execution.

Uploaded by

MohamedHassan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
837 views

FreeRTOS Tutorial - Embedded Systems Learning Academy

This document provides an introduction to using FreeRTOS, an open source real-time operating system kernel for embedded systems. It describes FreeRTOS tasks, queues for inter-task communication, and semaphores. Examples are provided for simple tasks, queue usage, and controlling task execution.

Uploaded by

MohamedHassan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

FreeRTOSTutorial

FromEmbeddedSystemsLearningAcademy

Contents
1Introduction
1.1Screencast
2WhatisanOS
3FreeRTOSmain()andTasks
3.1TheMAINFunction
3.2WhatisStackMemory?
3.3TaskStackSize
3.4ControllingTasks
3.5SimpleTask
3.6TerminalTask
4FreeRTOSIntertaskCommunication
4.1QueueCommunication
4.1.1Explanation
4.1.2PracticalExample
4.2Semaphores
4.2.1Mutex
4.2.2BinarySemaphore
4.2.3CountingSemaphore
5FAQ
6GoingBeyond

Introduction
ThisarticleisaboutlearningFreeRTOS.TheFreeRTOSsampleprojectrunningonSJOneBoardisusedas
reference,butanyFreeRTOSprojectonanycontrollercanbenefitfromthisarticle.
NotesabouttheFreeRTOSSampleProject:
TheDevelopmentPackageZIPFilecontainstheFreeRTOSsampleproject,however,thelatestcopycan
alwaysbedownloadedfrom:https://sourceforge.net/projects/armdevpkg/files
ThisarticleassumesyouknowhowtocompileandloadasampleprojecttotheSJOneBoard.

Screencast
IcreatedsomescreencaststoquicklygothroughFreeRTOS,however,IHIGHLYencourageyoutoreadthis
articleinfullfirst.
TasksandQueues
FreeRTOStasksandQueues(http://www.youtube.com/watch?v=8lIpI30Tjg)
FreeRTOSQueues(http://www.youtube.com/watch?v=yHfDO_jiIFw)

Semaphores:
FreeRTOSMutex(http://www.youtube.com/watch?v=PjDHn_G078k)
FreeRTOSBinarySemaphore(http://www.youtube.com/watch?v=grXuVMttVuU)
FreeRTOSInterruptProcessingusingBinarySemaphore(http://www.youtube.com/watch?
v=06TH2NgrKkA)
C++WrapperforFreeRTOStasks(http://www.youtube.com/watch?v=4gawgXminv4)
UsethistutorialaftermasteringthebasicFreeRTOSconcepts
ThesourcecodeisincludedinSJSU_Devdevelopmentpackage.

WhatisanOS
AnEmbeddedOperatingSystemlikeFreeRTOSisnothingbutsoftwarethatprovidesmultitaskingfacilities.
FreeRTOSallowstorunmultipletasksandhasasimpleschedulertoswitchbetweentasks.Herearesomeofthe
FreeRTOSfeatures:
Prioritybasedmultitaskingcapability
Queuestocommunicatebetweenmultipletasks
Semaphorestomanageresourcesharingbetweenmultipletasks
UtilitiestoviewCPUutilization,stackutilizationetc.

FreeRTOSmain()andTasks
TheMAINFunction
ThemainfunctioninFreeRTOSbasedprojectisnothingbutafunctionthatcreatestasks.FreeRTOSwillletyou
multitaskbasedonyourtasksandtheirpriority.Rememberthata"task"issimplya"function"nameoftype:void
my_task(void*p)

WhatisStackMemory?
Beforeyoucreateatask,youneedtoknowwhatisstackmemory.Everyvariableyoudeclareusesmemoryonthe
stack.Thismemoryisgenerallypreferredoverheapallocatedmemorythatcomesfrommallocornewoperators.
WhatusesStackMemory?
LocalVariablesofthetask.
Functioncalls(functionparameters+functionreturnaddress)
Localvariablesoffunctionsyourtaskcalls.
Howisstackmanaged?
Everytimeyoudeclareavariable,stackpointermovesdown.
Ifyoudeclareanint,yourassemblycodewillgenerate:SUBSP,1
Ifyoudeclarecharmem[128]yourassemblycodewillgenerate:SUBSP,32assuming32bitmachine
Thatiswhyyoushouldusecurlybracesandlimitthescopeofvariablesasmuchaspossible.Thisway,

everytimeavariablegoesoutofscope,youwillseesomethinglike:ADDSP,##indicatingmemory
released.
ThisiswhystackmemoryispreferredoverheapbecausestackusesjusttwoADDandSUBinstructionsto
managememorywhereasheapusesratherexpensivemallocoperations.Furthermore,mallocfragmentsyour
memoryandinasmallersystem,fragmentedmemorymayresultinmallocreturningNULLpointers.
Let'sstartwithexamplesonhowtoestimateyourstackmemory:
voidhello_world_task(void*p)
{
charmem[128];
while(1){
}
}
//Thetaskaboveuses128bytesofstack.

voidhello_world_task(void*p)
{
charmem[128];
intint_mem[128];//4bytesperint
while(1){
}
}
//Thetaskaboveuses128+(128*4)bytesofstack.

voidhello_world_task(void*p)
{
charmem[128];
while(1){
foo();//Assumefoouses128bytesofstack.
}
}
//Thetaskaboveuses128+128bytesofstack.

voidhello_world_task(void*p)
{
charmem[128];
while(1){
if(...){
charmem_one[128];
}
else(...){
charmem_two[256];
}
}
}
/*Thetaskaboveuses128+256bytesofstack.
*Notethatitisnot128+128+256,becauseonlyonebranchstatement
*willexecuteandintheworstcase,branchtwo'scodewillendup
*using128+256bytesofstack.
*/

voidhello_world_task(void*p)

{
char*mem=char*malloc(128);
while(1){
}
}
//Thetaskaboveusesjust4bytesofstack(toholdmempointer)
//TheactualmemorycomesfromHEAP,whichisnotpartofthestack.

TaskStackSize
Thestacksizeofataskdependsonthememoryconsumedbyitslocalvariablesandfunctioncalldepth.Please
notethatifyourtask(orfunction)usesprintf,itconsumesaround1024bytesofstack.Atminimumhowever,you
wouldneedatleast512bytes+yourestimatedstackspaceabove.Ifyoudon'tallocateenoughstackspace,
yourCPUwillruntoanexceptionand/orfreeze.
Youshoulddefinitelyreadthefollowingarticletostudythememorylayout:
StackHeapWalkthrough

ControllingTasks
InFreeRTOS,youhaveprecisecontrolofwhentaskswillusetheCPU.Therulesaresimple:
Taskwithhighestprioritywillrunfirst,andnevergiveuptheCPUuntilitsleeps
If2ormoretaskswiththesameprioritydonotgiveuptheCPU(theydon'tsleep),thenFreeRTOSwill
sharetheCPUbetweenthem(timeslice).
HerearesomeofthewaysyoucangiveuptheCPU:
vTaskDelay()Thissimplyputsthetaskto"sleep"youdecidehowmuchyouwanttosleep.
xQueueSend()IftheQueueyouaresendingtoisfull,thistaskwillsleep(block).
xQueueReceive()IftheQueueyouarereadingfromisempty,thistaskwillsleep(block).
xSemaphoreTake()Youwillsleepifthesemaphoreistakenbysomebodyelse.

Rememberthateachfunctiongivenabovetakesaparameterthatdecideshowlongyouarewillingtosleep.You
couldusethisparameterasatimeout.Forexample,yourlogicmaybe:"I'mgoingtowait1secondtoreceive
somethingfromthequeue,otherwiseIwill<dowhatever>".

SimpleTask
Belowisasimpletaskexamplethatprintsamessageonceasecond.NotethatvTaskStartScheduler()never
returnsandFreeRTOSwillbeginservicingthetasksatthispoint.Alsonotethateverytaskmusthaveaninfinite
loopandNEVEREXIT.
voidhello_world_task(void*p)
{
while(1){
puts("HelloWorld!");
vTaskDelay(1000);
}
}

intmain()
{

xTaskCreate(hello_world_task,(signedchar*)"task_name",STACK_BYTES(2048),0,1,0);
vTaskStartScheduler();

return1;
}

TerminalTask
TheFreeRTOSsampleprojectcreates"terminal"taskthatallowsyoutointeractwiththeserialport.Youcantype
"help"andpressenterinHerculesprogramtoseethecommandssupportedbytheterminaltask.Youcan,of
course,addmorecommandstoit.Youshouldnowpausereadingthisarticleandnowlookathowtheterminal
taskworks.Hereisascreenshotofterminaltaskinteraction:TODO:Addscreenshot

FreeRTOSIntertaskCommunication
QueueCommunication
YoucancommunicatebetweentasksbyusingQueuesorSemaphores.Let'screateanexampletocommunicate
betweentwotasksbasedontheSoftwareFrameworkinthesampleproject.Here'ssomesamplecode:
//GlobalQueueHandle
QueueHandle_tqh=0;

voidtask_tx(void*p)
{
intmyInt=0;
while(1)
{
myInt++;
if(!xQueueSend(qh,&myInt,500)){
puts("Failedtosenditemtoqueuewithin500ms");
}
vTaskDelay(1000);
}
}

voidtask_rx(void*p)
{
intmyInt=0;
while(1)
{
if(!xQueueReceive(qh,&myInt,1000)){
puts("Failedtoreceiveitemwithin1000ms");
}
else{
printf("Received:%u\n",myInt);
}
}
}

intmain()
{
qh=xQueueCreate(1,sizeof(int));

xTaskCreate(task_tx,(signedchar*)"t1",STACK_BYTES(2048),0,1,0);
xTaskCreate(task_rx,(signedchar*)"t2",STACK_BYTES(2048),0,1,0);
vTaskStartScheduler();


return1;
}

Explanation
Notethefollowingitems:
Inmain(),wecreatetheQueuebeforecreatingtasks,otherwisesendingtouninitializedQueuewillcrash
thesystem.
Intask_tx(),wesendoneitemeverysecond,andifthequeueisfull,weprintafailuremessage.
Intask_rx(),wereceiveoneitem,andwedonotusevTaskDelay().Thisisbecauseifthereisnothinginthe
queue,FreeRTOSwillsleep(orblock)thistaskfromrunning.ThetimeoutitselfinxQueueReceive()allows
ustosleepfor1000msbutwakeupifanitemisavailableinthequeueearlier.
Ifthepriorityofthereceivingqueue(task_rx())ishigher,FreeRTOSwillswitchtasksthemoment
xQueueSend()happens,andthenextlineinsidetask_tx()willnotexecutesinceCPUwillbeswitchedover
totask_rx().

PracticalExample
Apracticalexampleofaqueuemaybetostartanothertasktostartdoingitsworkwhiletheprimarytaskcontinues
doingitsownworkindependently.Inthefollowingexample,wedemonstratehowaterminaltaskcankickoff
anothertasktobeginplayinganmp3songwhileitoperatesindependentlytohandlethenextcommandfroma
terminal(userinput).
voidterminal_task(void*p)
{
//Assumeyougotausercommandtoplayanmp3:
xQueueSend(song_name_queue,"song_name.mp3",0);

...
}

voidmp3_play_task(void*p)
{
charsong_name[32];
while(1){
if(xQueueReceive(song_name_queue,&song_name[0],portMAX_DELAY)){
//Starttoplaythesong.
}
}
}

Semaphores
Semaphoresaremeanttolimitaccesstoresources,buttherearemanyapplications.Therearealsomanytypesof
semaphoresandthetextbelowdiscussessomeofthemandtheirapplication.
Mutex

Oneofthebestexampleofamutexistoguardaresourceoradoorwithakey.Forinstance,let'ssayyouhavean
SPIBUS,andonlyonetaskshoulduseitatatime.Mutexprovidesmutualexclusionwithpriorityinversion
mechanism(http://en.wikipedia.org/wiki/Priority_inversion).MutexwillonlyallowONEtasktogetpast
xSemaphoreGet()operationandothertaskswillbeputtosleepiftheyreachthisfunctionatthesametime.
//Inmain(),initializeyourMutex:
SemaphoreHandle_tspi_bus_lock=xSemaphoreCreateMutex();

voidtask_one()
{
while(1){
if(xSemaphoreGet(spi_bus_lock,1000)){
//UseGuardedResource

//GiveSemaphoreback:
xSemaphoreGive(spi_bus_lock);
}
}
}
voidtask_two()
{
while(1){
if(xSemaphoreGet(spi_bus_lock,1000)){
//UseGuardedResource

//GiveSemaphoreback:
xSemaphoreGive(spi_bus_lock);
}
}
}

Inthecodeabove,onlyONEtaskwillenteritsxSemaphoreGet()branch.Ifbothtasksexecutethestatementatthe
sametime,onewillgetthemutex,theothertaskwillsleepuntilthemutexisreturnedbythetaskthatwasableto
obtainitinthefirstplace.
BinarySemaphore
Binarysemaphorecanalsobeusedlikeamutex,butbinarysemaphoredoesn'tprovidepriorityinversion
mechanism.Binarysemaphoresarebettersuitedforhelpertasksforinterrupts.Forexample,ifyouhavean
interruptandyoudon'twanttodoalotofprocessinginsidetheinterrupt,youcanuseahelpertask.Toaccomplish
this,youcanperformasemaphoregiveoperationinsidetheinterrupt,andadedicatedaskwillsleeporblockon
xSemaphoreGet()operation.
//Somewhereinmain():
SemaphoreHandle_tevent_signal;
vSemaphoreCreateBinary(event_signal);//Createthesemaphore
xSemaphoreTake(event_signal,0);//Takesemaphoreaftercreatingit.

voidSystem_Interrupt()
{
xSemaphoreGiveFromISR(event_signal);
}

voidsystem_interrupt_task()
{
while(1){
if(xSemaphoreTake(event_signal,9999999)){
//Processtheinterrupt
}

}
}

Theabovecodeshowsexampleofadeferredinterruptprocessing.Theideaisthatyoudon'twanttoprocessthe
interruptinsideSystem_Interrupt()becauseyou'dbeinacriticalsectionwithsysteminterruptsgloballydisabled,
therefore,youcanpotentiallylockupthesystemordestroyrealtimeprocessingiftheinterruptprocessingtakes
toolong.
Anotherwaytousebinarysemaphoreistowakeuponetaskfromanothertaskbygivingthesemaphore.Sothe
semaphorewillessentiallyactlikeasignalthatmayindicate:"Somethinghappened,nowgodotheworkin
anothertask".Inthesampleproject,binarysemaphoreisusedtoindicatewhenanI2Creadoperationisdone,and
theinterruptgivesthissemaphore.NotethatwhenyoucreateabinarysemaphoreinFreeRTOS,itisreadyto
betaken,soyoumaywanttotakethesemaphoreafteryoucreateitsuchthatthetaskwaitingonthis
semaphorewillblockuntilgivenbysomebody.
CountingSemaphore
Countingsemaphoresaresuitedforapplicationsinwhichmorethanoneuserisallowedaccesstoaresource.For
example,ifyouhaveaparkinggarageof10cars,youcanallow10semaphoreaccess.Eachcarenteringagarage
willtake1semaphoreuntil10carstake10semaphoresandnomorecarswillbeallowedaccesstothegarage.

FAQ
IwrotemyownversionofQueue,Idon'twanttouseFreeRTOSqueuesinceitisnotefficient
Becarefulhere.FreeRTOSqueuesmaybemoreexpensive,buttheyprovidebenefitsyourqueuemay
notprovide.FreeRTOS'squeuescanswitchtasksuponQueuesendandreceive,andyourtaskswillbe
managedbetterandsleepasappropriatewhereasyourownversionlikelydoesn'tintegratewellwith
FreeRTOS.Forexample,FreeRTOSmayswitchcontextinsideofxQueueSend()ifitfindsthat
someonewithhigherprioritywaswaitingforaniteminthisqueue.
WhatifIsendanitemonFreeRTOSqueueandmyitemgoesoutofscope?
FreeRTOScopiesvalueoftheitemyousend,sothisisperfectlyokay.
IfIusedeferredinterruptprocessing,butstillwanttoprocessinterruptquickly,whatcanIdo?
Youcansetthepriorityofthedeferredinterrupttaskashighest,andassoonasinterruptgivesthe
binarysemaphoreandexit,FreeRTOSwillswitchcontexttoyourinterrupttask.
Ihavealotoflittletasksbutendupusingalotofstackmemoryforeachtask.WhatcanIdo?
First,thinkaboutconsolidatingtasks.Ifyourtasksdoabunchofthingseverysecond,thencombine
theprocessingintoasingletask.Ifyouhaveanumberofthingshappeningperiodically,consider
usingaFreeRTOStimer.FreeRTOStimersusecommonstackbutprovideindependenttimers.
HowmuchstackspaceamIreallyusing?
UseFreeRTOS's:vTaskList()functiontogetameasureofthestackspace.Thesampleprojectsare
specificallymodifiedsuchthatthisfunctionwillreportstackfreeinbytes,alongwithCPUutilization
ofeachtask.

I'musingadelayfunctionandCPUutilizationisveryhigh
Yourdelayfunctionisprobablyabusywaitloop.UseFreeRTOS'svTaskDelay(),whichisactually
smartenoughtoputthetasktosleepandwakeituppreciselywhenthetimeoutisdone.Ifataskuses
littleprocessingeverysecondandyouusevTaskDelay(1000)yourCPUutilizationwillbenearzero
percent.
Idon'tunderstandthedifferencebetweenvTaskDelay()andvTaskDelayUntil()
vTaskDelay()willdelaybythedefinedamount,andifyouwantedapreciseperiodicprocessingofone
second,thisfunctionmightnotworkasyou'dexpect.Intheexamplebelow,evenifyouwantedsensor
updateofonceper1000ms,youractualratewouldbeanywherefrom1005to1050msbecause
update_sensor()function'sprocessingtimecanvary.Inthisexample,ifweswitchoverto
vTaskDelayUntil(),wewillbeupdatingsensorsexactlyonceper1000ms.
voidmy_task(void*p)
{
while(1){
update_sensors();//Assumethisfunctioncantake550ms
vTaskDelay(1000);
}
}

GoingBeyond
ThebasictasksshowyouaroundFreeRTOScentricsystemandthisisjustthestartingpoint.Forexample,ifyou
arecreatingarelayswitchthatgetsturnedonbasedonthelightlevel,youmaywanttocreateatask,getthelight
readingfromthelightsensor,andcontroltherelay.Logicallythinking,youmaywanttomonitorthelightreading
onceasecond,sodon'tforgettousevTaskDelay().
Asyourprojectgetsmorecomplex,youwilldeterminebyexperiencethatwhichtaskscanbeputtolowerpriority
andwhichtasksneedhighpriority.Byprioritizingthetasks,youcancreateadeterministicsystemandguarantee
realtimeoperationofcriticaltaskswhilecompleting"background"processingusinglowerprioritytasks.
ValuableReads:
Read2012SJOneHelloWorldSampleProjecttogetnewbieorienteddetailsabouthowtoreadsensor
valuesofyourSJOneBoard.
ReadFreeRTOSAPI(http://www.freertos.org/a00106.html)tounleashthepowerofthisOS.
Retrievedfrom"http://www.socialledge.com/sjsu/index.php?title=FreeRTOS_Tutorial&oldid=5620"
Thispagewaslastmodifiedon5March2014,at09:29.
Thispagehasbeenaccessed75,924times.
ContentisavailableunderPublicDomain.

You might also like