You are on page 1of 14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

FreeRTOS
ChristopherSvec

FreeRTOS(pronounced"freearrtoss")isanopensourcerealtimeoperatingsystem(RTOS)forembedded
systems.FreeRTOSsupportsmanydifferentarchitecturesandcompilertoolchains,andisdesignedtobe
"small,simple,andeasytouse".
FreeRTOSisunderactivedevelopment,andhasbeensinceRichardBarrystartedworkonitin2002.Asforme,
I'mnotadeveloperoforcontributortoFreeRTOS,I'mmerelyauserandafan.Asaresult,thischapterwill
favorthe"what"and"how"ofFreeRTOS'sarchitecture,withlessofthe"why"thanotherchaptersinthisbook.
Likealloperatingsystems,FreeRTOS'smainjobistoruntasks.MostofFreeRTOS'scodeinvolvesprioritizing,
scheduling,andrunninguserdefinedtasks.Unlikealloperatingsystems,FreeRTOSisarealtimeoperating
systemwhichrunsonembeddedsystems.
BytheendofthischapterIhopethatyou'llunderstandthebasicarchitectureofFreeRTOS.MostofFreeRTOS
isdedicatedtorunningtasks,soyou'llgetagoodlookatexactlyhowFreeRTOSdoesthat.
Ifthisisyourfirstlookunderthehoodofanoperatingsystem,Ialsohopethatyou'lllearnthebasicsabouthow
anyOSworks.FreeRTOSisrelativelysimple,especiallywhencomparedtoWindows,Linux,orOSX,butall
operatingsystemssharethesamebasicconceptsandgoals,solookingatanyOScanbeinstructiveand
interesting.

3.1.Whatis"Embedded"and"RealTime"?
"Embedded"and"realtime"canmeandifferentthingstodifferentpeople,solet'sdefinethemasFreeRTOS
usesthem.
Anembeddedsystemisacomputersystemthatisdesignedtodoonlyafewthings,likethesysteminaTV
remotecontrol,incarGPS,digitalwatch,orpacemaker.Embeddedsystemsaretypicallysmallerandslower
thangeneralpurposecomputersystems,andarealsousuallylessexpensive.Atypicallowendembedded
systemmayhavean8bitCPUrunningat25MHz,afewKBofRAM,andmaybe32KBofflashmemory.A
higherendembeddedsystemmayhavea32bitCPUrunningat750MHz,aGBofRAM,andmultipleGBof
flashmemory.
Realtimesystemsaredesignedtodosomethingwithinacertainamountoftimetheyguaranteethatstuff
happenswhenit'ssupposedto.
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

1/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Apacemakerisanexcellentexampleofarealtimeembeddedsystem.Apacemakermustcontracttheheart
muscleattherighttimetokeepyoualiveitcan'tbetoobusytorespondintime.Pacemakersandotherreal
timeembeddedsystemsarecarefullydesignedtoruntheirtasksontime,everytime.

3.2.ArchitectureOverview
FreeRTOSisarelativelysmallapplication.TheminimumcoreofFreeRTOSisonlythreesource( .c )filesand
ahandfulofheaderfiles,totallingjustunder9000linesofcode,includingcommentsandblanklines.Atypical
binarycodeimageislessthan10KB.
FreeRTOS'scodebreaksdownintothreemainareas:tasks,communication,andhardwareinterfacing.
Tasks:AlmosthalfofFreeRTOS'scorecodedealswiththecentralconcerninmanyoperatingsystems:
tasks.AtaskisauserdefinedCfunctionwithagivenpriority. tasks.c and task.h doalltheheavy
liftingforcreating,scheduling,andmaintainingtasks.
Communication:Tasksaregood,buttasksthatcancommunicatewitheachotherareevenbetter!Which
bringsustothesecondFreeRTOSjob:communication.About40%ofFreeRTOS'scorecodedealswith
communication. queue.c and queue.h handleFreeRTOScommunication.Tasksandinterruptsuse
queuestosenddatatoeachotherandtosignaltheuseofcriticalresourcesusingsemaphoresand
mutexes.
TheHardwareWhisperer:Theapproximately9000linesofcodethatmakeupthebaseofFreeRTOSare
hardwareindependentthesamecoderunswhetherFreeRTOSisrunningonthehumble8051orthenewest,
shiniestARMcore.About6%ofFreeRTOS'scorecodeactsashimbetweenthehardwareindependent
FreeRTOScoreandthehardwaredependentcode.We'lldiscussthehardwaredependentcodeinthenext
section.

HardwareConsiderations
ThehardwareindependentFreeRTOSlayersitsontopofahardwaredependentlayer.Thishardwaredependent
layerknowshowtotalktowhateverchiparchitectureyouchoose.Figure3.1showsFreeRTOS'slayers.

Figure3.1:FreeRTOSsoftwarelayers
FreeRTOSshipswithallthehardwareindependentaswellashardwaredependentcodeyou'llneedtogeta
systemupandrunning.Itsupportsmanycompilers(CodeWarrior,GCC,IAR,etc.)aswellasmanyprocessor
architectures(ARM7,ARMCortexM3,variousPICs,SiliconLabs8051,x86,etc.).SeetheFreeRTOSwebsite
foralistofsupportedarchitecturesandcompilers.
FreeRTOSishighlyconfigurablebydesign.FreeRTOScanbebuiltasasingleCPU,barebonesRTOS,
supportingonlyafewtasks,oritcanbebuiltasahighlyfunctionalmulticorebeastwithTCP/IP,afilesystem,
andUSB.
Configurationoptionsareselectedin FreeRTOSConfig.h bysettingvarious #defines .Clockspeed,heap
size,mutexes,andAPIsubsetsareallconfigurableinthisfile,alongwithmanyotheroptions.Hereareafew
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

2/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

examplesthatsetthemaximumnumberoftaskprioritylevels,theCPUfrequency,thesystemtickfrequency,
theminimalstacksizeandthetotalheapsize:
#defineconfigMAX_PRIORITIES((unsignedportBASE_TYPE)5)
#defineconfigCPU_CLOCK_HZ(12000000UL)
#defineconfigTICK_RATE_HZ((portTickType)1000)
#defineconfigMINIMAL_STACK_SIZE((unsignedshort)100)
#defineconfigTOTAL_HEAP_SIZE((size_t)(4*1024))

HardwaredependentcodelivesinseparatefilesforeachcompilertoolchainandCPUarchitecture.Forexample,
ifyou'reworkingwiththeIARcompileronanARMCortexM3chip,thehardwaredependentcodelivesinthe
FreeRTOS/Source/portable/IAR/ARM_CM3/ directory. portmacro.h declaresallofthehardwarespecific
functions,while port.c and portasm.s containalloftheactualhardwaredependentcode.Thehardware
independentheaderfile portable.h #include 'sthecorrect portmacro.h fileatcompiletime.FreeRTOS
callsthehardwarespecificfunctionsusing #define 'dfunctionsdeclaredin portmacro.h .
Let'slookatanexampleofhowFreeRTOScallsahardwaredependentfunction.Thehardwareindependentfile
tasks.c frequentlyneedstoenteracriticalsectionofcodetopreventpreemption.Enteringacriticalsection
happensdifferentlyondifferentarchitectures,andthehardwareindependent tasks.c doesnotwanttohaveto
understandthehardwaredependentdetails.So tasks.c callstheglobalmacro portENTER_CRITICAL() ,glad
tobeignorantofhowitactuallyworks.Assumingwe'reusingtheIARcompileronanARMCortexM3chip,
FreeRTOSisbuiltwiththefile FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h whichdefines
portENTER_CRITICAL() likethis:
#defineportENTER_CRITICAL()vPortEnterCritical()
vPortEnterCritical() isactuallydefinedin FreeRTOS/Source/portable/IAR/ARM_CM3/port.c .The
port.c fileishardwaredependent,andcontainscodethatunderstandstheIARcompilerandtheCortexM3
chip. vPortEnterCritical() entersthecriticalsectionusingthishardwarespecificknowledgeandreturnsto

thehardwareindependent tasks.c .
The portmacro.h filealsodefinesanarchitecture'sbasicdatatypes.Datatypesforbasicintegervariables,
pointers,andthesystemtimertickdatatypearedefinedlikethisfortheIARcompileronARMCortexM3chips:
#defineportBASE_TYPElong//Basicintegervariabletype
#defineportSTACK_TYPEunsignedlong//Pointerstomemorylocations
typedefunsignedportLONGportTickType//Thesystemtimerticktype

Thismethodofusingdatatypesandfunctionsthroughthinlayersof #defines mayseemabitcomplicated,


butitallowsFreeRTOStoberecompiledforacompletelydifferentsystemarchitecturebychangingonlythe
hardwaredependentfiles.AndifyouwanttorunFreeRTOSonanarchitectureitdoesn'tcurrentlysupport,you
onlyhavetoimplementthehardwaredependentfunctionalitywhichismuchsmallerthanthehardware
independentpartofFreeRTOS.
Aswe'veseen,FreeRTOSimplementshardwaredependentfunctionalitywithCpreprocessor #define macros.
FreeRTOSalsouses #define forplentyofhardwareindependentcode.Fornonembeddedapplicationsthis
frequentuseof #define isacardinalsin,butinmanysmallerembeddedsystemstheoverheadforcallinga
functionisnotworththeadvantagesthat"real"functionsoffer.

3.3.SchedulingTasks:AQuickOverview
TaskPrioritiesandtheReadyList
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

3/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Eachtaskhasauserassignedprioritybetween0(thelowestpriority)andthecompiletimevalueof
configMAX_PRIORITIES1 (thehighestpriority).Forinstance,if configMAX_PRIORITIES issetto5,then
FreeRTOSwilluse5prioritylevels:0(lowestpriority),1,2,3,and4(highestpriority).
FreeRTOSusesa"readylist"tokeeptrackofalltasksthatarecurrentlyreadytorun.Itimplementstheready
listasanarrayoftasklistslikethis:
staticxListpxReadyTasksLists[configMAX_PRIORITIES]/*Prioritisedreadytasks.*/
pxReadyTasksLists[0] isalistofallreadypriority0tasks, pxReadyTasksLists[1] isalistofallready

priority1tasks,andsoon,allthewayupto pxReadyTasksLists[configMAX_PRIORITIES1] .

TheSystemTick
TheheartbeatofaFreeRTOSsystemiscalledthesystemtick.FreeRTOSconfiguresthesystemtogeneratea
periodictickinterrupt.Theusercanconfigurethetickinterruptfrequency,whichistypicallyinthemillisecond
range.Everytimethetickinterruptfires,the vTaskSwitchContext() functioniscalled.
vTaskSwitchContext() selectsthehighestpriorityreadytaskandputsitinthe pxCurrentTCB variablelike
this:
/*Findthehighestpriorityqueuethatcontainsreadytasks.*/
while(listLIST_IS_EMPTY(&(pxReadyTasksLists[uxTopReadyPriority])))
{
configASSERT(uxTopReadyPriority)
uxTopReadyPriority
}
/*listGET_OWNER_OF_NEXT_ENTRYwalksthroughthelist,sothetasksofthesame
prioritygetanequalshareoftheprocessortime.*/
listGET_OWNER_OF_NEXT_ENTRY(pxCurrentTCB,&(pxReadyTasksLists[uxTopReadyPriority]))

Beforethewhileloopstarts, uxTopReadyPriority isguaranteedtobegreaterthanorequaltothepriorityof


thehighestpriorityreadytask.Thewhile()loopstartsatprioritylevel uxTopReadyPriority andwalksdown
throughthe pxReadyTasksLists[] arraytofindthehighestprioritylevelwithreadytasks.
listGET_OWNER_OF_NEXT_ENTRY() thengrabsthenextreadytaskfromthatprioritylevel'sreadylist.
Now pxCurrentTCB pointstothehighestprioritytask,andwhen vTaskSwitchContext() returnsthe
hardwaredependentcodestartsrunningthattask.
ThoseninelinesofcodearetheabsoluteheartofFreeRTOS.Theother8900+linesofFreeRTOSarethereto
makesurethoseninelinesareallthat'sneededtokeepthehighestprioritytaskrunning.
Figure3.2isahighlevelpictureofwhatareadylistlookslike.Thisexamplehasthreeprioritylevels,withone
priority0task,nopriority1tasks,andthreepriority2tasks.Thispictureisaccuratebutnotcompleteit's
missingafewdetailswhichwe'llfillinlater.

file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

4/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Figure3.2:BasicviewofFreeRTOSReadyList
Nowthatwehavethehighleveloverviewoutoftheway,let'sdiveintothedetails.We'lllookatthethreemain
FreeRTOSdatastructures:tasks,lists,andqueues.

3.4.Tasks
Themainjobofalloperatingsystemsistorunandcoordinateusertasks.Likemanyoperatingsystems,the
basicunitofworkinFreeRTOSisthetask.FreeRTOSusesaTaskControlBlock(TCB)torepresenteachtask.

TaskControlBlock(TCB)
TheTCBisdefinedin tasks.c likethis:
typedefstructtskTaskControlBlock
{
volatileportSTACK_TYPE*pxTopOfStack/*Pointstothelocationof
thelastitemplacedon
thetasksstack.THIS
MUSTBETHEFIRSTMEMBER
OFTHESTRUCT.*/

xListItemxGenericListItem/*Listitemusedtoplace
theTCBinreadyand
blockedqueues.*/
xListItemxEventListItem/*Listitemusedtoplace
theTCBineventlists.*/
unsignedportBASE_TYPEuxPriority/*Thepriorityofthetask
where0isthelowest
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

5/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

priority.*/
portSTACK_TYPE*pxStack/*Pointstothestartof
thestack.*/
signedcharpcTaskName[configMAX_TASK_NAME_LEN]/*Descriptivenamegiven
tothetaskwhencreated.
Facilitatesdebugging
only.*/
#if(portSTACK_GROWTH>0)
portSTACK_TYPE*pxEndOfStack/*Usedforstackoverflow
checkingonarchitectures
wherethestackgrowsup
fromlowmemory.*/
#endif
#if(configUSE_MUTEXES==1)
unsignedportBASE_TYPEuxBasePriority/*Theprioritylast
assignedtothetask
usedbythepriority
inheritancemechanism.*/
#endif
}tskTCB

TheTCBstorestheaddressofthestackstartaddressin pxStack andthecurrenttopofstackin


pxTopOfStack .Italsostoresapointertotheendofthestackin pxEndOfStack tocheckforstackoverflowif
thestackgrows"up"tohigheraddresses.Ifthestackgrows"down"toloweraddressesthenstackoverflowis
checkedbycomparingthecurrenttopofstackagainstthestartofstackmemoryin pxStack .
TheTCBstorestheinitialpriorityofthetaskin uxPriority and uxBasePriority .Ataskisgivenapriority
whenitiscreated,andatask'sprioritycanbechanged.IfFreeRTOSimplementspriorityinheritancethenit
uses uxBasePriority toremembertheoriginalprioritywhilethetaskistemporarilyelevatedtothe"inherited"
priority.(Seethediscussionaboutmutexesbelowformoreonpriorityinheritance.)
EachtaskhastwolistitemsforuseinFreeRTOS'svariousschedulinglists.Whenataskisinsertedintoalist
FreeRTOSdoesn'tinsertapointerdirectlytotheTCB.Instead,itinsertsapointertoeithertheTCB's
xGenericListItem or xEventListItem .These xListItem variableslettheFreeRTOSlistsbesmarter
thaniftheymerelyheldapointertotheTCB.We'llseeanexampleofthiswhenwediscusslistslater.
Ataskcanbeinoneoffourstates:running,readytorun,suspended,orblocked.Youmightexpecteachtaskto
haveavariablethattellsFreeRTOSwhatstateit'sin,butitdoesn't.Instead,FreeRTOStrackstaskstate
implicitlybyputtingtasksintheappropriatelist:readylist,suspendedlist,etc.Thepresenceofataskina
particularlistindicatesthetask'sstate.Asataskchangesfromonestatetoanother,FreeRTOSsimplymoves
itfromonelisttoanother.

TaskSetup
We'vealreadytouchedonhowataskisselectedandscheduledwiththe pxReadyTasksLists arraynowlet's
lookathowataskisinitiallycreated.Ataskiscreatedwhenthe xTaskCreate() functioniscalled.FreeRTOS
usesanewlyallocatedTCBobjecttostorethename,priority,andotherdetailsforatask,thenallocatesthe
amountofstacktheuserrequests(assumingthere'senoughmemoryavailable)andremembersthestartofthe
stackmemoryinTCB's pxStack member.
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

6/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Thestackisinitializedtolookasifthenewtaskisalreadyrunningandwasinterruptedbyacontextswitch.This
waytheschedulercantreatnewlycreatedtasksexactlythesamewayasittreatstasksthathavebeenrunning
forawhiletheschedulerdoesn'tneedanyspecialcasecodeforhandlingnewtasks.
Thewaythatatask'sstackismadetolooklikeitwasinterruptedbyacontextswitchdependsonthe
architectureFreeRTOSisrunningon,butthisARMCortexM3processor'simplementationisagoodexample:
unsignedint*pxPortInitialiseStack(unsignedint*pxTopOfStack,
pdTASK_CODEpxCode,
void*pvParameters)
{
/*Simulatethestackframeasitwouldbecreatedbyacontextswitchinterrupt.*/
pxTopOfStack/*OffsetaddedtoaccountforthewaytheMCUusesthestackon
entry/exitofinterrupts.*/
*pxTopOfStack=portINITIAL_XPSR/*xPSR*/
pxTopOfStack
*pxTopOfStack=(portSTACK_TYPE)pxCode/*PC*/
pxTopOfStack
*pxTopOfStack=0/*LR*/
pxTopOfStack=5/*R12,R3,R2andR1.*/
*pxTopOfStack=(portSTACK_TYPE)pvParameters/*R0*/
pxTopOfStack=8/*R11,R10,R9,R8,R7,R6,R5andR4.*/

returnpxTopOfStack
}

TheARMCortexM3processorpushesregistersonthestackwhenataskisinterrupted.
pxPortInitialiseStack() modifiesthestacktolookliketheregisterswerepushedeventhoughthetask
hasn'tactuallystartedrunningyet.KnownvaluesarestoredtothestackfortheARMregisters xPSR,PC,LR,
and R0 .Theremainingregisters R1 R12 getstackspaceallocatedforthembydecrementingthetopof
stackpointer,butnospecificdataisstoredinthestackforthoseregisters.TheARMarchitecturesaysthat
thoseregistersareundefinedatreset,soa(nonbuggy)programwillnotrelyonaknownvalue.
Afterthestackisprepared,thetaskisalmostreadytorun.Firstthough,FreeRTOSdisablesinterrupts:We're
abouttostartmuckingwiththereadylistsandotherschedulerstructuresandwedon'twantanyoneelse
changingthemunderneathus.
Ifthisisthefirsttasktoeverbecreated,FreeRTOSinitializesthescheduler'stasklists.FreeRTOS'sscheduler
hasanarrayofreadylists, pxReadyTasksLists[] ,whichhasonereadylistforeachpossibleprioritylevel.
FreeRTOSalsohasafewotherlistsfortrackingtasksthathavebeensuspended,killed,anddelayed.These
areallinitializednowaswell.
Afteranyfirsttimeinitializationisdone,thenewtaskisaddedtothereadylistatitsspecifiedprioritylevel.
Interruptsarereenabledandnewtaskcreationiscomplete.

3.5.Lists
Aftertasks,themostusedFreeRTOSdatastructureisthelist.FreeRTOSusesitsliststructuretokeeptrackof
tasksforscheduling,andalsotoimplementqueues.

file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

7/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Figure3.3:FullviewofFreeRTOSReadyList
TheFreeRTOSlistisastandardcirculardoublylinkedlistwithacoupleofinterestingadditions.Here'salist
element:
structxLIST_ITEM
{
portTickTypexItemValue/*Thevaluebeinglisted.Inmostcases
thisisusedtosortthelistin
descendingorder.*/
volatilestructxLIST_ITEM*pxNext/*PointertothenextxListIteminthe
list.*/
volatilestructxLIST_ITEM*pxPrevious/*PointertothepreviousxListItemin
thelist.*/
void*pvOwner/*Pointertotheobject(normallyaTCB)
thatcontainsthelistitem.Thereis
thereforeatwowaylinkbetweenthe
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

8/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

objectcontainingthelistitemand
thelistitemitself.*/
void*pvContainer/*Pointertothelistinwhichthislist
itemisplaced(ifany).*/
}

Eachlistelementholdsanumber, xItemValue ,thatistheusuallythepriorityofthetaskbeingtrackedora


timervalueforeventscheduling.Listsarekeptinhightolowpriorityorder,meaningthatthehighestpriority
xItemValue (thelargestnumber)isatthefrontofthelistandthelowestpriority xItemValue (thesmallest
number)isattheendofthelist.
The pxNext and pxPrevious pointersarestandardlinkedlistpointers. pvOwner isapointertotheownerof
thelistelement.Thisisusuallyapointertoatask'sTCBobject. pvOwner isusedtomaketaskswitchingfast
in vTaskSwitchContext() :oncethehighestprioritytask'slistelementisfoundin pxReadyTasksLists[] ,
thatlistelement's pvOwner pointerleadsusdirectlytotheTCBneededtoschedulethetask.
pvContainer pointstothelistthatthisitemisin.Itisusedtoquicklydetermineifalistitemisinaparticular
list.Eachlistelementcanbeputinalist,whichisdefinedas:
typedefstructxLIST
{
volatileunsignedportBASE_TYPEuxNumberOfItems
volatilexListItem*pxIndex/*Usedtowalkthroughthelist.Pointsto
thelastitemreturnedbyacallto
pvListGetOwnerOfNextEntry().*/
volatilexMiniListItemxListEnd/*Listitemthatcontainsthemaximum
possibleitemvalue,meaningitisalways
attheendofthelistandistherefore
usedasamarker.*/
}xList

Thesizeofalistatanytimeisstoredin uxNumberOfItems ,forfastlistsizeoperations.Allnewlistsare


initializedtocontainasingleelement:the xListEnd element. xListEnd.xItemValue isasentinelvalue
whichisequaltothelargestvalueforthe xItemValue variable: 0xffff when portTickType isa16bit
valueand 0xffffffff when portTickType isa32bitvalue.Otherlistelementsmayalsohavethesame
valuetheinsertionalgorithmensuresthat xListEnd isalwaysthelastiteminthelist.
Sincelistsaresortedhightolow,the xListEnd elementisusedasamarkerforthestartofthelist.Andsince
thelistiscircular,this xListEnd elementisalsoamarkerfortheendofthelist.
Most"traditional"listaccessesyou'veusedprobablydoalloftheirworkwithinasinglefor()looporfunctioncall
likethis:
for(listPtr=listStartlistPtr!=NULLlistPtr=listPtr>next){
//DosomethingwithlistPtrhere...
}

FreeRTOSfrequentlyneedstoaccessalistacrossmultiplefor()andwhile()loopsaswellasfunctioncalls,and
soituseslistfunctionsthatmanipulatethe pxIndex pointertowalkthelist.Thelistfunction
listGET_OWNER_OF_NEXT_ENTRY() does pxIndex=pxIndex>pxNext andreturns pxIndex .(Ofcourseit
doestheproperendoflistwraparounddetectiontoo.)Thiswaythelistitselfisresponsibleforkeepingtrackof
"whereyouare"whilewalkingitusing pxIndex ,allowingtherestofFreeRTOStonotworryaboutit.
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

9/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Figure3.4:FullviewofFreeRTOSReadyListafterasystemtimertick
The pxReadyTasksLists[] listmanipulationdonein vTaskSwitchContext() isagoodexampleofhow
pxIndex isused.Let'sassumewehaveonlyoneprioritylevel,priority0,andtherearethreetasksatthat
prioritylevel.Thisissimilartothebasicreadylistpicturewelookedatearlier,butthistimewe'llincludeallof
thedatastructuresandfields.
AsyoucanseeinFigure3.3, pxCurrentTCB indicatesthatwe'recurrentlyrunningTaskB.Thenexttime
vTaskSwitchContext() runs,itcalls listGET_OWNER_OF_NEXT_ENTRY() togetthenexttasktorun.This
functionuses pxIndex>pxNext tofigureoutthenexttaskisTaskC,andnow pxIndex pointstoTaskC's
listelementand pxCurrentTCB pointstoTaskC'sTCB,asshowninFigure3.4.
Notethateach structxListItem objectisactuallythe xGenericListItem objectfromtheassociatedTCB.

3.6.Queues
FreeRTOSallowstaskstocommunicateandsynchronizewitheachotherusingqueues.Interruptservice
routines(ISRs)alsousequeuesforcommunicationandsynchronization.
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

10/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

Thebasicqueuedatastructureis:
typedefstructQueueDefinition
{
signedchar*pcHead/*Pointstothebeginningofthequeue
storagearea.*/
signedchar*pcTail/*Pointstothebyteattheendofthe
queuestoragearea.Onemorebyteis
allocatedthannecessarytostorethe
queueitemsthisisusedasamarker.*/
signedchar*pcWriteTo/*Pointstothefreenextplaceinthe
storagearea.*/
signedchar*pcReadFrom/*Pointstothelastplacethataqueued
itemwasreadfrom.*/

xListxTasksWaitingToSend/*Listoftasksthatareblockedwaiting
topostontothisqueue.Storedin
priorityorder.*/
xListxTasksWaitingToReceive/*Listoftasksthatareblockedwaiting
toreadfromthisqueue.Storedin
priorityorder.*/
volatileunsignedportBASE_TYPEuxMessagesWaiting/*Thenumberofitemscurrently
inthequeue.*/
unsignedportBASE_TYPEuxLength/*Thelengthofthequeue
definedasthenumberof
itemsitwillhold,notthe
numberofbytes.*/
unsignedportBASE_TYPEuxItemSize/*Thesizeofeachitemsthat
thequeuewillhold.*/

}xQUEUE

Thisisafairlystandardqueuewithheadandtailpointers,aswellaspointerstokeeptrackofwherewe'vejust
readfromandwrittento.
Whencreatingaqueue,theuserspecifiesthelengthofthequeueandthesizeofeachitemtobetrackedbythe
queue. pcHead and pcTail areusedtokeeptrackofthequeue'sinternalstorage.Addinganitemintoa
queuedoesadeepcopyoftheitemintothequeue'sinternalstorage.
FreeRTOSmakesadeepcopyinsteadofstoringapointertotheitembecausethelifetimeoftheiteminserted
maybemuchshorterthanthelifetimeofthequeue.Forinstance,consideraqueueofsimpleintegersinserted
andremovedusinglocalvariablesacrossseveralfunctioncalls.Ifthequeuestoredpointerstotheintegers'
localvariables,thepointerswouldbeinvalidassoonastheintegers'localvariableswentoutofscopeandthe
localvariables'memorywasusedforsomenewvalue.
Theuserchooseswhattoqueue.Theusercanqueuecopiesofitemsiftheitemsaresmall,likeinthesimple
integerexampleinthepreviousparagraph,ortheusercanqueuepointerstotheitemsiftheitemsarelarge.
NotethatinbothcasesFreeRTOSdoesadeepcopy:iftheuserchoosestoqueuecopiesofitemsthenthe
queuestoresadeepcopyofeachitemiftheuserchoosestoqueuepointersthenthequeuestoresadeep
copyofthepointer.Ofcourse,iftheuserstorespointersinthequeuethentheuserisresponsibleformanaging
thememoryassociatedwiththepointers.Thequeuedoesn'tcarewhatdatayou'restoringinit,itjustneedsto
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

11/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

knowthedata'ssize.
FreeRTOSsupportsblockingandnonblockingqueueinsertionsandremovals.Nonblockingoperationsreturn
immediatelywitha"Didthequeueinsertionwork?"or"Didthequeueremovalwork?"status.Blockingoperations
arespecifiedwithatimeout.Ataskcanblockindefinitelyorforalimitedamountoftime.
AblockedtaskcallitTaskAwillremainblockedaslongasitsinsert/removeoperationcannotcompleteand
itstimeout(ifany)hasnotexpired.IfaninterruptoranothertaskmodifiesthequeuesothatTaskA'soperation
couldcomplete,TaskAwillbeunblocked.IfTaskA'squeueoperationisstillpossiblebythetimeitactually
runsthenTaskAwillcompleteitsqueueoperationandreturn"success".However,bythetimeTaskAactually
runs,itispossiblethatahigherprioritytaskorinterrupthasperformedyetanotheroperationonthequeuethat
preventsTaskAfromperformingitsoperation.InthiscaseTaskAwillcheckitstimeoutandeitherresume
blockingifthetimeouthasn'texpired,orreturnwithaqueueoperation"failed"status.
It'simportanttonotethattherestofthesystemkeepsgoingwhileataskisblockingonaqueueothertasks
andinterruptscontinuetorun.Thiswaytheblockedtaskdoesn'twasteCPUcyclesthatcouldbeused
productivelybyothertasksandinterrupts.
FreeRTOSusesthe xTasksWaitingToSend listtokeeptrackoftasksthatareblockingoninsertingintoa
queue.Eachtimeanelementisremovedfromaqueuethe xTasksWaitingToSend listischecked.Ifataskis
waitinginthatlistthetaskisunblocked.
Similarly, xTasksWaitingToReceive keepstrackoftasksthatareblockingonremovingfromaqueue.Each
timeanewelementisinsertedintoaqueuethe xTasksWaitingToReceive listischecked.Ifataskiswaiting
inthatlistthetaskisunblocked.

SemaphoresandMutexes
FreeRTOSusesitsqueuesforcommunicationbetweenandwithintasks.FreeRTOSalsousesitsqueuesto
implementsemaphoresandmutexes.

What'sTheDifference?
Semaphoresandmutexesmaysoundlikethesamething,butthey'renot.FreeRTOSimplementsthem
similarly,butthey'reintendedtobeusedindifferentways.Howshouldtheybeuseddifferently?Embedded
systemsguruMichaelBarrsaysitbestinhisarticle,"MutexesandSemaphoresDemystified":
Thecorrectuseofasemaphoreisforsignalingfromonetasktoanother.Amutexismeanttobetakenand
released,alwaysinthatorder,byeachtaskthatusesthesharedresourceitprotects.Bycontrast,tasksthat
usesemaphoreseithersignal["send"inFreeRTOSterms]orwait["receive"inFreeRTOSterms]notboth.
Amutexisusedtoprotectasharedresource.Ataskacquiresamutex,usesthesharedresource,thenreleases
themutex.Notaskcanacquireamutexwhilethemutexisbeingheldbyanothertask.Thisguaranteesthat
onlyonetaskisallowedtouseasharedresourceatatime.
Semaphoresareusedbyonetasktosignalanothertask.ToquoteBarr'sarticle:
Forexample,Task1maycontaincodetopost(i.e.,signalorincrement)aparticularsemaphorewhenthe
"power"buttonispressedandTask2,whichwakesthedisplay,pendsonthatsamesemaphore.Inthis
scenario,onetaskistheproduceroftheeventsignaltheothertheconsumer.
Ifyou'reatallindoubtaboutsemaphoresandmutexes,pleasecheckoutMichael'sarticle.

Implementation
FreeRTOSimplementsanNelementsemaphoreasaqueuethatcanholdNitems.Itdoesn'tstoreanyactual
dataforthequeueitemsthesemaphorejustcareshowmanyqueueentriesarecurrentlyoccupied,whichis
trackedinthequeue's uxMessagesWaiting field.It'sdoing"puresynchronization",astheFreeRTOSheader
file semphr.h callsit.Thereforethequeuehasaitemsizeofzerobytes( uxItemSize==0 ).Each
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

12/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

file semphr.h callsit.Thereforethequeuehasaitemsizeofzerobytes( uxItemSize==0 ).Each


semaphoreaccessincrementsordecrementsthe uxMessagesWaiting fieldnoitemordatacopyingis
needed.
Likeasemaphore,amutexisalsoimplementedasaqueue,butseveralofthe xQUEUE structfieldsare
overloadedusing #defines :
/*EffectivelymakeaunionoutofthexQUEUEstructure.*/
#defineuxQueueTypepcHead
#definepxMutexHolderpcTail

Sinceamutexdoesn'tstoreanydatainthequeue,itdoesn'tneedanyinternalstorage,andsothe pcHead and


pcTail fieldsaren'tneeded.FreeRTOSsetsthe uxQueueType field(reallythe pcHead field)to 0 tonote
thatthisqueueisbeingusedforamutex.FreeRTOSusestheoverloaded pcTail fieldstoimplementpriority
inheritanceformutexes.
Incaseyou'renotfamiliarwithpriorityinheritance,I'llquoteMichaelBarragaintodefineit,thistimefromhis
article,"IntroductiontoPriorityInversion":
[Priorityinheritance]mandatesthatalowerprioritytaskinheritthepriorityofanyhigherprioritytaskpending
onaresourcetheyshare.Thisprioritychangeshouldtakeplaceassoonasthehighprioritytaskbeginsto
penditshouldendwhentheresourceisreleased.
FreeRTOSimplementspriorityinheritanceusingthe pxMutexHolder field(whichisreallyjusttheoverloaded
by #define pcTail field).FreeRTOSrecordsthetaskthatholdsamutexinthe pxMutexHolder field.
Whenahigherprioritytaskisfoundtobewaitingonamutexcurrentlytakenbyalowerprioritytask,FreeRTOS
"upgrades"thelowerprioritytasktothepriorityofthehigherprioritytaskuntilthemutexisavailableagain.

3.7.Conclusion
We'vecompletedourlookattheFreeRTOSarchitecture.Hopefullyyounowhaveagoodfeelforhow
FreeRTOS'stasksrunandcommunicate.Andifyou'veneverlookedatanyOS'sinternalsbefore,Ihopeyou
nowhaveabasicideaofhowtheywork.
ObviouslythischapterdidnotcoverallofFreeRTOS'sarchitecture.Notably,Ididn'tmentionmemoryallocation,
ISRs,debugging,orMPUsupport.ThischapteralsodidnotdiscusshowtosetuporuseFreeRTOS.Richard
Barryhaswrittenanexcellentbook,UsingtheFreeRTOSRealTimeKernel:APracticalGuide,whichdiscusses
exactlythatIhighlyrecommenditifyou'regoingtouseFreeRTOS.

3.8.Acknowledgements
IwouldliketothankRichardBarryforcreatingandmaintainingFreeRTOS,andforchoosingtomakeitopen
source.Richardwasveryhelpfulinwritingthischapter,providingsomeFreeRTOShistoryaswellasavery
valuabletechnicalreview.
ThanksalsotoAmyBrownandGregWilsonforpullingthiswholeAOSAthingtogether.
Lastandmost(theoppositeof"notleast"),thankstomywifeSarahforsharingmewiththeresearchandwriting
forthischapter.LuckilysheknewIwasageekwhenshemarriedme!

ThisworkismadeavailableundertheCreativeCommonsAttribution3.0Unportedlicense.Pleaseseethefull
descriptionofthelicensefordetails.
Backtotop
file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

13/14

28/12/2015

TheArchitectureofOpenSourceApplications(Volume2):FreeRTOS

BacktoTheArchitectureofOpenSourceApplications.

file:///D:/documents/0_A_LinuxKernel/The%20Architecture%20of%20Open%20Source%20Applications%20(Volume%202)_%20FreeRTOS.html

14/14

You might also like