Home

µC/OS-III User`s Manual (v3.05) - Doc

image

Contents

1. OSTaskSemPend _ f OSTaskSemPost i N C sr i iii R a d sar alia eal Figure Semaphore built into a Task There is a variety of operations to perform on task semaphores summarized in the table below Copyright 2015 Micrium Inc 262 uC OS III User s Manual Function Name Operation OSTaskSemPend Wait on a task semaphore OSTaskSemPendAbort Abort the wait on a task semaphore OSTaskSemPost Signal a task OSTaskSemSet Force the semaphore count to a desired value Table Task Semaphore API summary Pending i e Waiting on a Task Semaphore When a task is created it automatically creates an internal semaphore with an initial value of zero 0 Waiting on a task semaphore is quite simple as shown in the listing below void MyTask void p_arg OS_ERR err CPU_TS ts while DEF_ON OSTaskSemPend 10 1 OS_OPT_PEND_ BLOCKING 2 amp ts 3 amp err 4 Check err Listing Pending or waiting on Task s internal semaphore 1 A task pends or waits on the task semaphore by calling OSTaskSemPend There is no need to specify which task as the current task is assumed The first argument is a timeout specified in number of clock ticks The actual timeout obviously depends on the tick rate If the tick rate see os_cfg_app h is set to 1000 a timeout of 10 ticks represents 10 milliseconds Specifying a timeout of
2. Source The directory containing the CPU independent source code for uC OS III All files in this directory should be included in the build Features that are not required will be compiled out based on the value of define constants in os_cfg h and os_cfg_app h os_cfg_app c declares variables and arrays based on the values in os_cfg_app h os_core c contains core functionality for uC OS II such as osInit to initialize uC OS III oSSched for the task level scheduler oSIntExit for the interrupt level scheduler pend list or wait list management see Pend Lists ready list management see Ready List in General Statistics Run Time and more os_dbg c contains declarations of constant variables used by a kernel aware debugger or uC Probe Copyright 2015 Micrium Inc 39 uC OS III User s Manual Copyright 2015 Micrium Inc os_flag c contains the code for event flag management See Synchronization for details about event flags os_int c contains code for the interrupt handler task which is used when OS_CFG_ISR_POST_DEFERRED_EN see os_cfg h is set to DEF_ENABLED See Interrupt Management for details regarding the interrupt handler task os_mem c contains code for the wC OS III fixed size memory manager see Memory Management API Changes os_msg c contains code to handle messages uC OS III provides message queues and task specific message queues os_msg c provides common code for these two services See Message Pa
3. 2 Initialize the tick timer to generate interrupts every millisecond CPU_INT_EN 3 Enable interrupts S OSStart amp err 1 You need to setup the interrupt vector for the tick ISR Where this is done greatly depends on the CPU architecture On some processors you would simply insert a pointer to BSP_OS_TickISR in the interrupt vector table while on others you would need to call a function to install the vector in a RAM table Copyright 2015 Micrium Inc 378 uC OS III User s Manual 2 You can setup the timer you will use to generate interrupts here You need to make sure that the interrupt will not occur immediately but instead 1 millisecond after the timer is initialized You may recall that I told you to always initialize the tick interrupt from the first task that executes when we start multitasking However since we are testing the port it s safe to initialize the timer here since we have control over when the first interrupt will actually occur 3 This macro is used to enable global CPU interrupts It s assumed that the startup code runs with interrupts disabled and thus those need to be explicitly enabled At this point you need to remove all breakpoints you inserted to test the task level context switch code and insert the following breakpoints You should note that the C like code should actually be replaced with assembly language instructions for your processor OSIntCtxSw lt Set BREA
4. 1 0 2 0 Figure Ready List after calling OSInit TailPtr Entries 1 HeadPtr OSRdyList OS PRIO MAX 1 The tick task and the other three optional tasks have their own priority level as shown Typically you would set the priority of the tick task higher than the timer task and the timer task higher in priority than the statistic task Both the tail and head pointers point to the same TCB when there is only one TCB at a given priority level 133 uC OS III User s Manual Adding Tasks to the Ready List Tasks are added to the ready list by a number of uC OS III services The most obvious service is OSTaskCreate which always creates a task in the ready to run state and adds the task to the ready list As shown in Figure 6 6 we created a task and specified a priority level where tasks already existed two in this example in the ready list at the desired priority level OSTaskCreate will then insert the new task at the end of the list of tasks at that priority level fro PrevPtrNextPtr Other Fields PrevPtr NextPtr Other Fields HeadPtr BOAS OSRdyList prio Entries 2 TailPtr BEFORE 1 3 n x HeadPtr aay OSRdyList prio Entries 3 TailPr AFTER 3 3 4 N f x f 7 x S1 PrevPtr NextPtr Other Fields 3 0 lt 3 Figure Inserting a newly created task in the
5. Unilateral Rendez Vous The figure below shows that a task can be synchronized with an ISR or another task by using a semaphore In this case no data is exchanged however there is an indication that the ISR or the task on the left has occurred Using a semaphore for this type of synchronization is called a unilateral rendez vous Copyright 2015 Micrium Inc 249 uC OS III User s Manual N Timeout OSSemPost gt E OSSemPend N Timeout Figure Unilateral Rendezvous A unilateral rendez vous is used when a task initiates an I O operation and waits i e call OSSemPend for the semaphore to be signaled posted When the I O operation is complete an ISR or another task signals the semaphore i e calls OSSemPost and the task is resumed This process is also shown on the timeline of the figure below and described below The code for the ISR and task is shown in the listing follows the figure below ISR 7 t pC O5 III la 6 A as TE ee a Task CO a a me oeaiei LP Task e Figure Unilateral Rendezvous Timing Diagram 1 A high priority task is executing The task needs to synchronize with an ISR i e wait for the ISR to occur and call OSSemPend 2 3 Since the ISR has not occurred the task will be placed in the waiting list for the semaphore until the event occurs The scheduler in wC OS II will then select the next Copyright 2015 Micrium Inc 250 uC OS III User s Ma
6. OS_SEM OS_MUTEX OS FLAG GRP os_Q NamePtr NamePtr TailPtr TailPtr HeadPtr HeadPtr NamePtr TailPtr HeadPtr MsgQ TS w e OwnerTCBPtr Flags TS OwnerNestingCtr Ts Figure OS_PEND_OBJ at the beginning of certain kernel objects The table below shows that the Type field of each of the above objects is initialized to contain four ASCII characters when the respective object is created This allows the user to identify these objects when performing a memory dump using a debugger Kernel Object Type Semaphore S E M SA Mutual Exclusion Semaphore M UV TP X Event Flag Group p o e g Message Queue Q Ur Ee U Table Kernel objects with initialized Type field A pend list does not actually point to a task s 0S_TCB but instead points to OS_PEND_DATA objects as shown in the figure below Also an 0S_PEND_DATA structure is allocated dynamically on the current task s stack when a task is placed on a pend list This implies that a task stack needs to be able to allocate storage for this data structure Copyright 2015 Micrium Inc 180 uC OS III User s Manual OS_PEND_DATA PrevPtr TCBPtr PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS Figure Pend Data PrevPtr Is a pointer to an OS_PEND_DATA entry in the pend list This pointer points to a higher or equal priority task waiting on the kernel object NextPtr Is a pointer to an OS_PEND_DATA entry in the pend list This pointe
7. Task Messages uC OS III allows an ISR or a task to send messages directly to a task This Copyright 2015 Micrium Inc 22 uC OS III User s Manual avoids having to create and use a message queue and also results in better performance Task registers Each task can have a user definable number of task registers Task registers are different than CPU registers Task registers can be used to hold errno type variable IDs interrupt disable time measurement on a per task basis and more Error checking uC OS III verifies that NULL pointers are not passed that the user is not calling task level services from ISRs that arguments are within allowable range that options specified are valid that a pointer to the proper object is passed as part of the arguments to services that manipulate the desired object and more Each uC OS III API function returns an error code concerning the outcome of the function call Built in performance measurements uC OS III has built in features to measure the execution time of each task stack usage of each task number of times a task executes CPU usage ISR to task and task to task response time peak number of entries in certain lists interrupt disable and scheduler lock time on a per task basis and more Can easily be optimized C OS II was designed so that it could easily be optimized based on the CPU architecture Most data types used in uC OS III can be changed to make better use of th
8. That knowledge should extend to CPU instructions interrupts I O devices RAM and ROM or Flash memory addresses and stack pointers It is also expected that the reader will have a good working knowledge of the C programming language and assembly language The uC OS Story The uC OS story started when in 1989 I joined Dynalco Controls in Fort Lauderdale Florida and began working on the design of a new microprocessor based ignition control system for a large industrial reciprocating engine Given that I had experience using a kernel I was convinced that an operating system would substantially benefit this project and other planned projects at Dynalco Time to market was of paramount importance for this ignition control system and I knew that a kernel would help meet scheduling requirement I also knew that new features would be added to this product in the future and a preemptive operating system would allow for such updates without negatively impacting system responsiveness The kernel that I initially considered was one that had served me well in the past However it carried a hefty price tag and my budget was somewhat meager The alternative was a kernel that I had not used before but it was five times cheaper than my original choice Ultimately I decided that the financial benefits of using the unfamiliar operating system outweighed the potential advantages that its higher priced counterpart could offer I quickly re
9. uC OS III User s Manual This field works with the PendDataTb1Ptr and indicates the number of objects a task is pending on at the same time TS This field is used to store a time stamp of when an event that the task was waiting on occurred When the task resumes execution this time stamp is returned to the caller SemCtr This field contains a semaphore counter associated with the task Each task has its own built in semaphore An ISR or another task can signal a task using this semaphore SemCtr is therefore used to keep track of how many times the task is signaled SemCtr is used by OSTaskSem services TickRemain This field contains the number of ticks remaining before the task is removed from either the delayed or timeout list As of V3 04 00 the value of this field is relative it used to be absolute since these lists are now implemented as delta lists In other words this field does not contain absolute time remaining until the delay or timeout expires TickCtrPrev This field is used to keep track of the previous value of OSTickCtr in order to be able to implement the periodic mode for OSTimeD1ly TimeQuanta and TimeQuantaCtr These fields are used for time slicing When multiple tasks are ready to run at the same priority TimeQuanta determines how much time in ticks the task will execute until it is preempted by wC OS III so that the next task at the same priority gets a chance to execute TimeQuant
10. 10 amp err amp AppTaskStartTCB 3 App Task Start OS_TASK_PTR AppTaskStart void OS_PRIO CPU_STK APP_TASK_START_PRIO amp AppTaskStartStk CPU_STK_SIZE APP_TASK_START_STK_SIZE 10 CPU_STK_SIZE APP_TASK_START_STK_SIZE OS_MSG_QTY OS_TICK void OS_OPT OS_ERR Check for err OsStart amp err Check for err Copyright 2015 Micrium Inc 0 0 OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR amp err Listing app c 2nd Part 59 uC OS III User s Manual 2 3 Creating a mutex is simply a matter of calling OSMutexCreate You need to specify the address of the oS_MUTEX object that will be used for the mutex Resource Management provides additional information about mutual exclusion semaphores You can assign an ASCII name to the mutex which is useful when debugging You create the message queue by calling osQcreate and specify the address of the 0s_Q object Message Passing provides additional information about message queues You can assign an ASCII name to the message queue which can also be useful during debugging You need to specify how many messages the message queue is allowed to receive This value must be greater than zero If the sender sends messages faster than they can be consumed by the receiving task messages will be lost This can be corrected by either increasing the size of the message qu
11. 4 amp err 5 Check err Listing Creating a Semaphore Copyright 2015 Micrium Inc 257 uC OS III User s Manual 1 2 3 4 5 The application must declare a variable of type os_sem This variable will be referenced by other semaphore services You create a semaphore by calling OSSemCreate and pass the address to the semaphore allocated in 1 You can assign an ASCII name to the semaphore which can be used by debuggers or uC Probe to easily identify this semaphore You need to initialize the semaphore to zero 0 when using a semaphore as a signaling mechanism OSSemCreate returns an error code based on the outcome of the call If all arguments are valid err will contain OS_ERR_NONE OSSemCreate performs a check on the arguments passed to this function assuming OS_CFG_ARG_CHK_EN is set to DEF_ENABLED in os_cfg h and only initializes the contents of the variable of type 0S_SEM used for signaling A task waits for a signal from an ISR or another task by calling OSSemPend as shown in the listing below see Appendix A uC OS III API Reference for details regarding the arguments void MyTask void p_arg Copyright 2015 Micrium Inc OS_ERR err CPU_TS ts while DEF_ON OSSemPend amp MySem 1 OS_OPT_PEND_BLOCKING amp ts amp err Check err 2 Listing Pending or waiting on a Semaphore When called oSSemPend s
12. NbrEntries This field contains the current number of 0S_MSGs in the queue NbrEntriesMax This field contains the highest number of 0S_MSGs existing in the queue at any given time A number of internal functions are used by uC OS III to manipulate the free list and messages Specifically 0S_MsgQPut inserts an OS_MSG in an OS_MSG_Q OS_MsgQGet extracts an OS_MSG from an 0S_MSG_Q and 0S_MsgQFreeA11 returns all OS_MSGs in an OS_MSG_Q to the pool of free os_MSGs There are other 0S_MsgQ functions in os_msg c that are used during initialization The figure below shows an example of an 0S_MSG_Q when four 0S_MSGs are inserted Copyright 2015 Micrium Inc 304 uC OS III User s Manual OS_MSG_Q NbrEntriesSize 10 NbrEntries 4 NbrEntriesMax 4 OS_MSG OS_MSG OS_MSG OS_MSG Data Data Data Data Figure OS_MSG_Q with four OS_MSGs OS_MSG_Qs are used inside two additional data structures OS_Q and OS_TCB Recall that an os_Q is declared when creating a message queue object An 0S_TCB is a task control block and as previously mentioned each 0S_TCB can have its own message queue when the configuration constant OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h The figure below shows the contents of an 0S_Q and partial contents of an 0S_TCB containing an OS_MSG_Q The 0S_MSG_Q data structure is shown as an exploded view to emphasize the structure within the structure OS_MSG_Q NbrEntriesMax
13. OS_MSG_Q Pee ae NbrEntriesMax Figure OS_Q and OS_TCB each contain an OS_MSG_Q 305 Copyright 2015 Micrium Inc uC OS III User s Manual Pending on Multiple Objects In Pend Lists we saw how multiple tasks can pend or wait on a single kernel object such as a semaphore mutual exclusion semaphore event flag group or message queue In this chapter we will see how tasks can pend on multiple objects However uwC OS HI only allows for pend on multiple semaphores and or message queues In other words it is not possible to pend on multiple event flag groups or mutual exclusion semaphores As shown in the figure below a task can pend on any number of semaphores or message queues at the same time The first semaphore or message queue posted will make the task ready to run and compete for CPU time with other tasks in the ready list As shown a task pends on multiple objects by calling oSPendMulti and specifies an optional timeout value The timeout applies to all of the objects If none of the objects are posted within the specified timeout the task resumes with an error code indicating that the pend timed out Semaphore OSSemPost gt gt Semaphore OSSemPost gt Message Queue OSPendMulti OSQPost gt Message Semaphore OSSemPost Figure Task pending on multiple objects The listing below shows the function prototype of OSPendMulti an
14. OS_TICK e void Gn OS_OPT OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR OS_ERR amp err if err OS_ERR_NONE The task didn t get created Lookup the value of the error code in os h for the meaning of the error OsStart amp err if err OS_ERR_NONE Your code is NEVER supposed to come back to this point Listing app c 2nd Part Copyright 2015 Micrium Inc 1 2 3 4 5 6 7 8 9 18 11 12 z ys 13 yf 52 uC OS III User s Manual 1 2 3 4 5 Copyright 2015 Micrium Inc The startup code for the compiler will bring the CPU to main main then starts by calling a BSP function that disables all interrupts On most processors interrupts are disabled at startup until explicitly enabled by application code However it is safer to turn off all peripheral interrupts during startup OSInit is the called to initialize wC OS HI osInit initializes internal variables and data structures and also creates between two 2 and five 5 internal tasks Unless otherwise specified in the configuration file os_cfg h at a minimum uC OS III creates the idle task 0S_IdleTask which executes when no other task is ready to run uC OS III also creates the tick task which is responsible for keeping track of time Depending on the value of define constants wC OS III will create the statistic task OS_StatTask the timer
15. TailPtr 3 Entries 0 HeadPtr 0 TailPtr 4 Entries 0 0 HeadPtr 0 TailPtr 5 Entries 0 0 art 0 TailPtr 0 OSRdyList OS_CFG PRIO_MAX 1 Entries 0 0 ea Figure Empty Ready List Assuming all internal uC OS III s tasks are enabled the figure below shows the state of the ready list after calling osInit i e wC OS III s initialization It is assumed that each uC OS III task had a unique priority With uC OS III this does not have to be the case There is only one entry in OSRdyList 0S_CFG_PRIO_MAX 1 the idle task The list points to OS_TCBs Only relevant fields of the TCB are shown The PrevPtr and NextPtr are used to form a doubly linked list of 0S_TCBs associated to tasks at the same priority For the idle task these fields always point to NULL Priority is reserved to the ISR handler task when OS_CFG_ISR_DEFERRED_EN is set to DEF_ENABLED in os_cfg h In this case this is the only task that can run at priority 0 uC OS III User s Manual 1 2 Copyright 2015 Micrium Inc OSRdyList OS_CFG_TICK_TASK_PRIO OSRdyList OS CFG STAT TASK_PRIO OS_RDY LIST OSRdyList OS_PRIO MAX TailPtr Entries 1 e HeadPtr 3 OSIntQTaskTCB PrevPtr NextPtr Other Fields OSRdyList 0 TailPtr Entries 1 HeadPtr 4 0 0 OSRdyList OS CFG TMR TASK PRIO TailPtr bd Entries 1 4 HeadPtr OSStatTaskTCB 4 i 5 OSIdleTaskTCB
16. This field is therefore placed as the first entry in the structure making access easier from assembly language code it will be at offset zero in the data structure ExtPtr This field contains a pointer to a user definable data area used to extend the TCB as needed This pointer is provided as an argument passed in OSTaskCreate This pointer is easily accessible from assembly language since it always follows the StkPtr ExtPtr can be used to add storage for saving the context of a FPU Floating Point Unit if the processor you are using has a FPU StkLimitPtr Copyright 2015 Micrium Inc The field contains a pointer to a location in the task s stack to set a watermark limit for stack growth and is determined from the value of the stk_limit argument passed to OSTaskCreate Some processors have special registers that automatically check the value of the stack pointer at run time to ensure that the stack does not overflow StkLimitPtr may be used to set this register during a context switch Alternatively if the processor does not have such a register this can be simulated in software However this is not as reliable as a hardware solution If this feature is not used then you can set the value of stk_limit can be set to when calling OSTaskCreate See also Detecting Task Stack Overflows 97 uC OS III User s Manual Stack RAM Low Memory StkBasePtr StkLimitPtr StkSize StkPtr Stack G
17. This variable indicates the RAM footprint in number of bytes of an 0S_MSG_Q data type ROM Variable Data Type Value OSDbg_MutexEn CPU_INT 8U OS_CFG_MUTEX_EN When 1 this variable indicates that wC OS III s mutual exclusion semaphore management services are available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_MutexDelEn CPU_INT 8U OS_CFG_MUTEX_DEL_EN Copyright 2015 Micrium Inc 402 uC OS III User s Manual When 1 this variable indicates that the function OSMutexDel is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_MutexPendAbortEn CPU_INT 8U OS_CFG_MUTEX_PEND_ABORT_EN When 1 the variable indicates that the function OSMutexPendAbort is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg MutexSize CPU_INT16U sizeof OS_MUTEX This variable indicates the RAM footprint in number of bytes of an 0S_MUTEX data type ROM Variable Data Type Value OSDbg_ObjTypeChkEn CPU_INT 8U OS_CFG_OBJ_TYPE_CHK_EN When 1 this variable indicates that uC OS III will check for valid object types at run time wC OS III will make sure the application is accessing a semaphore if calling OSSem functions accessing a message queue when calling 0SQ functions etc This value is set in os_cfg h ROM Variable Data Type Value OSDbg_ PendMultiEn CPU_INT 8U OS_CFG_PEND_MULTI_EN When 1 this
18. a OSSemSet merg OSSemPend gt gt er N x OSSemPost Timeout Figure C OS III Semaphore Services Copyright 2015 Micrium Inc 248 uC OS III User s Manual There are a number of operations to perform on semaphores as summarized in the table below and the figure above However in this chapter we will only discuss the three functions used most often OSSemCreate OSSemPend and OSSemPost The other functions are described in uC OS III API Reference Also note that every semaphore function is callable from a task but only OSSemPost can be called by an ISR Function Name Operation OSSemCreate Create a semaphore OSSemDel Delete a semaphore OSSemPend Wait on a semaphore OSSemPendAbort Abort the wait on a semaphore OSSemPost Signal a semaphore OSSemSet Force the semaphore count to a desired value Table Semaphore API summary When used for synchronization a semaphore keeps track of how many times it was signaled using a counter The counter can take values between 0 and 255 65 535 or 4 294 967 295 depending on whether the semaphore mechanism is implemented using 8 16 or 32 bits respectively For wC OS III the maximum value of a semaphore is determined by the data type OS_SEM_CTR see os_type h which is changeable as needed assuming access to uC OS III s source code Along with the semaphore s value wC OS III keeps track of tasks waiting for the semaphore to be signaled
19. of the event flags corresponding to each task to be set 4 When all waiting tasks are ready the task that will synchronize the waiting task issues a broadcast to the semaphore Copyright 2015 Micrium Inc 282 uC OS III User s Manual Message Passing It is sometimes necessary for a task or an ISR to communicate information to another task This information transfer is called inter task communication Information can be communicated between tasks in two ways through global data or by sending messages As seen in Resource Management when using global variables each task or ISR must ensure that it has exclusive access to variables If an ISR is involved the only way to ensure exclusive access to common variables is to disable interrupts If two tasks share data each can gain exclusive access to variables either by disabling interrupts locking the scheduler using a semaphore or preferably using a mutual exclusion semaphore Note that a task can only communicate information to an ISR by using global variables A task is not aware when a global variable is changed by an ISR unless the ISR signals the task or the task polls the contents of a variable periodically Messages can either be sent to an intermediate object called a message queue or directly toa task since in wC OS HI each task has its own built in message queue You can use an external message queue if multiple tasks are to wait for messages You would send a mess
20. A semaphore contains a counter As explained above the counter can be implemented as either an 8 16 or 32 bit value depending on how the data type 0S_SEM_CTR is declared in os_type h wC OS III keeps track of how many times the semaphore is signaled with this counter and this field is typically initialized to zero by OSSemCreate 6 A semaphore contains a time stamp which is used to indicate the last time the semaphore was signaled or posted to wC OS II assumes the presence of a free running counter that allows the application to make time measurements When the semaphore is signaled the free running counter is read and the value is placed in this field which is returned when 0SSemPend is called This value allows the application to determine either when the signal was performed or how long it took for the task to get control of the CPU from the signal In the latter case you should call Os_TS_GET to determine the current timestamp and compute the difference Even for users who understand the internals of the os_sem data type the application code should never access any of the fields in this data structure directly Instead you should always use the APIs provided with uC OS III Semaphores must be created before they can be used by an application The listing below shows how to create a semaphore OS_SEM MySem 1 void MyCode void OS_ERR err OSSemCreate amp MySem 2 My Semaphore 3 OS_SEM_CTR
21. Contains all software components and projects provided by Micrim Software This sub directory contains all software components and projects EvalBoards This sub directory contains all projects related to evaluation boards lt manufacturer gt The name of the manufacturer of the evaluation board The lt and gt are not part of the actual name lt board name gt The name of the evaluation board A board from Micrim will typically be called uC Eval xxxx where xxxx is the name of the CPU or MCU used on the evaluation board The lt and gt are not part of the actual name lt compiler gt Copyright 2015 Micrium Inc 36 uC OS III User s Manual The name of the compiler or compiler manufacturer used to build code for the evaluation board The lt and gt are not part of the actual name BSP This directory is always called BSP The source files of the BSP Typically all of the file names start with BSP It is therefore normal to find bsp c and bsp h in this directory BSP code should contain such functions as LED control functions initialization of timers interface to Ethernet controllers and more Copyright 2015 Micrium Inc 37 uC OS III User s Manual uC OS III CPU Independent Source Code The files in these directories are uC OS II processor independent files provided in source form Micrium Software uCOS III Cfg Template os_app_hooks c o
22. My in front of a directory name it means a directory you will need to create for your tests of the port As you will see you can start with the template files provided with wC CPU and uC OS III with little or no modifications Copyright 2015 Micrium Inc uC OS III User s Manual Micrium Software EvalBoards MyBoardManufacturer MyBoardName MyToolsName MyBSP bsp c bsp h bsp_os c bsp_os_a asm optional bsp_os h cpu_bsp c cpu_bsp h MyTest 1 app c 2 includes h 3 app_cfg h 4 cpu_cfg h 5 lt lib_cfg h lt os_app_hooks c lt os_app_hooks h lt os_cfg h 6 lt os_cfg_app h lt os_type h lt Micrium Software uC CPU cpu_core c cpu_core h cpu_def h MyCPUName MyToolsName Copied Copied Copied Copied Copied Copied Copied lt See the section yC OS III port lt See the section ywC OS III port lt See the section ywC OS III port from Micrium Software uC CPU Cfg Template from Micrium Software uC LIB Cfg Template from Micrium Software uCOS III Cfg Template from Micrium Software uCOS III Cfg Template from Micrium Software uCOS III Cfg Template from Micrium Software uCOS III Cfg Template from Micrium Software uCOS III Source cpu h cpu_a asm Micrium Software uC LIB ib_ascii c ib_ascii h ib_def h ib_math c ib_math h ib_mem ib_mem ib_str ib_str Micrium Software uC OS III Cfg os_app_hooks c os_app_hooks h os_cfg h os_cfg_app h
23. OS_ERR amp err 9 2 3 4 5 Copyright 2015 Micrium Inc Check err OSStart amp err Listing Creating a memory partition 1 An application needs to allocate storage for a memory partition control block i e OS_MEM structure This can be a static allocation as shown here or malloc can be used in the code However the application code must not deallocate the memory control block The application also needs to allocate storage for the memory that will be split into memory blocks This can also be a static allocation or malloc can be used The same reasoning applies Do not deallocate this storage since other tasks may rely on the existence of this storage Memory partition must be created before allocating and deallocating blocks from the partition One of the best places to create memory partitions is in main prior to starting the multitasking process Of course an application can call a function from main to do this instead of actually placing the code directly in main You pass the address of the memory partition control block to OSMemCreate You should never reference any of the internal members of the os_mem data structure Instead you should always use wC OS III s API You can assign a name to the memory partition There is no limit to the length of the ASCII string as uC OS III saves a pointer to the ASCII string in the partition control block and not the actual characte
24. Task L finishes working with the resource and releases the mutex uC OS HI notices that Task L was raised in priority and thus lowers Task L to its original priority After doing so uC OS III gives the mutex to Task H which was waiting for the mutex to be released 9 Task H now has the mutex and can access the shared resource 10 Task H is finished accessing the shared resource and frees up the mutex 11 There are no higher priority tasks to execute therefore Task H continues execution 12 Task H completes and decides to wait for an event to occur At this point wC OS III resumes Task M which was made ready to run while Task H or Task L were executing Task M was made ready to run because an interrupt not shown in figure 13 5 occurred which Task M was waiting for 13 Task M executes Note that there is no priority inversion only resource sharing Of course the faster Task L accesses the shared resource and frees up the mutex the better uC OS III implements full priority inheritance and therefore if a higher priority requests the resource the priority of the owner task will be raised to the priority of the new requestor A mutex is a kernel object defined by the 0S_MUTEX data type which is derived from the structure os_mutex see os h An application may have an unlimited number of mutexes limited only by the RAM available Copyright 2015 Micrium Inc 233 uC OS III User s Manual Only tasks are allowed to use m
25. Ticks ticks Time Callback Called Figure Retriggering a One Shot Timer Periodic no initial delay As indicated in the figure below timers can be configured for periodic mode When the countdown expires the callback function is called the timer is automatically reloaded and the process is repeated If specifying a delay of zero i e dly when the timer is created and when started the timer immediately uses the period as the reload value You can call OSTmrStart at any point in the countdown to restart the process Copyright 2015 Micrium Inc 196 uC OS III User s Manual OSTmrCreate OSTmrStart Ticks period ticks Time l Callback Callback Callback Called Called Called Figure Periodic Timers dly 0 period gt 0 Periodic with initial delay As shown in the figure below timers can be configured for periodic mode with an initial delay that is different than its period The first countdown count comes from the dly argument passed in the 0STmrcreate call and the reload value is the period You can call OSTmrStart to restart the process including the initial delay OSTmrCreate OSTmrStart Auto reload Ticks Callback Callback Callback Callback Callback Called Called Called Called Called Figure Periodic Timers dly gt 0 period gt 0 Copyright 2015 Micrium Inc 197 uC OS III User s Manual Timer Management Internals Timer States
26. a semaphore a message queue or a mutual exclusion Copyright 2015 Micrium Inc 140 uC OS III User s Manual semaphore if tasks are waiting on the kernel object those tasks will be made ready to run and the scheduler will be called to determine if any of the tasks have a higher priority than the task that deleted the kernel object Those tasks will be notified that the kernel object was deleted A task changes the priority of itself or another task The scheduler is called when a task changes the priority of another task or itself and the new priority of that task is higher than the task that changed the priority A task suspends itself by calling OSTaskSuspend The scheduler is called since the task that called oSTaskSuspend is no longer able to execute The suspended task must be resumed by another task A task resumes another task that was suspended by OSTaskSuspend The scheduler is called if the resumed task has a higher priority than the task that calls OSTaskResume At the end of all nested ISRs The scheduler is called at the end of all nested ISRs to determine whether a more important task is made ready to run by one of the ISRs The scheduling is actually performed by OSIntExit instead of OSSched The scheduler is unlocked by calling OSSchedUnlock The scheduler is unlocked after being locked You can lock the scheduler by calling OSSchedLock Note that locking the scheduler can be nested and the schedul
27. common mathematical operations like min max abs bit_set bit_clr etc with DEF_MIN DEF_MAX DEF_ABS DEF_BIT_SET DEF_BIT_CLR respectively lib_math c and 1ib_math h contain source code to replace some standard library functions such as rand srand etc with uC LIB equivalent functions Math_Rand Math_SetSeed respectively lib_mem c and 1ib_mem h contain source code to replace some standard library functions such as memc1r memset memcpy memcmp etc with uC LIB equivalent functions Mem_Clr Mem_Set Mem_Copy Mem_Cmp respectively lib_str c and lib_str h contain source code to replace some standard library functions such as strlen strcpy strcmp memcmp etc with uC LIB equivalent functions Str_Lenr Str_Copy Str_Cmp respectively Cfg Template This directory contains a configuration template file lib_cfg h that should be copied to the application directory to configure the uC LIB module based on application requirements lib_cfg h determines whether to enable assembly language optimization assuming there is an assembly language file for the processor i e 1ib_mem_a asm and a few other defines Ports Architecture Compiler This directory contains optimized assembly language files specific to the CPU architecture to replace C functions with much faster assembly language implementations The presence of this folder depends on whether such a
28. originally submitted to C User s Journal Had I taken that route the resulting book would have been approximately 80 pages or so in length To make the most of this opportunity I prepared a comprehensive text With the consent of R amp D I spent the next several months writing In late 1992 my first book aptly titled uC OS The Real Time Kernel was released The book had 250 pages and was available in paperback form Although initial sales of the book were somewhat disappointing R amp D advertised uC OS The Real Time Kernel each month in C User s Journal At the same time I was beginning to gain attention as a kernel expert In the spring of 1993 I was invited to speak at the Embedded Systems Conference ESC in Atlanta Georgia where I described operating system fundamentals to a highly receptive audience of more than 70 embedded enthusiasts Within a few years I was an ESC fixture delivering my kernel lectures to hundreds of engineers at each conference While my popularity as a speaker rose interest in my book also picked up steam After its slow start uC OS The Real Time Kernel went on to sell more than 15 000 copies Thanks to the success of my book the number of engineers using wC OS increased substantially throughout the 1990s Developers easily adapted the operating system to new hardware platforms and were designing a myriad of uC OS based applications Although several uC OS users simply tinkered with the op
29. purpose of having a preemptive kernel Locking the scheduler makes the current task the highest priority task Copyright 2015 Micrium Inc 212 uC OS III User s Manual Semaphores in uC OS Ill A semaphore was originally a mechanical signaling mechanism The railroad industry used the device to provide a form of mutual exclusion for railroads tracks shared by more than one train In this form the semaphore signaled trains by closing a set of mechanical arms to block a train from a section of track that was currently in use When the track became available the arm would swing up and the waiting train would then proceed The notion of using a semaphore in software as a means of mutual exclusion was invented by the Dutch computer scientist Edgser Dijkstra in 1959 In computer software a semaphore is a protocol mechanism offered by most multitasking kernels Semaphores originally used to control access to shared resources but now they are used for synchronization as described in Synchronization However it is useful to describe how semaphores can be used to share resources The pitfalls of semaphores will be discussed in a later section A semaphore was originally a lock mechanism and code acquired the key to this lock to continue execution Acquiring the key means that the executing task has permission to enter the section of otherwise locked code Entering a section of locked code causes the task to wait until the key becomes av
30. through semaphores All elements of uC OS were designed to be both highly dependable and easy to use Presumably most kernel developers have similar goals in mind when they write new software I was especially well equipped to meet these goals in part because of my punctilious coding style Throughout my career I focused on consistency and documentation I began using formal coding standards in 1984 and the consistency of the uC OS code is a testimony to this process uC OS was designed according to the stringent standards that I created and promulgated at Dynalco The operating system s source code featured liberal spacing carefully worded comments and consistent naming Offering further evidence of the prudent coding techniques the kernel was also highly portable Although uC OS like its kernel peers featured a small number of processor specific functions these routines were clearly separated from other portions of the operating system Engineers could easily adapt uC OS to new CPU architectures Unfortunately I was the only one to know about the virtues of uC OS Eager to describe my new software to others I wrote an in depth paper explaining the inner workings of uC OS There was plenty to say and my final paper was approximately 70 pages in length I offered my paper to C User s Journal and they rejected it on the grounds that it was too long and that its subject matter wasn t fresh The magazine had already publis
31. to a timer service for example OSTmrStart then wC OS III will be able to recognize that an invalid object was passed and return an error code accordingly Each kernel object can be given a name for easier recognition by debuggers or wC Probe This member is simply a pointer to an ASCII string which is assumed to be NUL terminated The CallbackPtr member is a pointer to a function that is called when the timer expires If a timer is created and passed a NULL pointer a callback would not be called when the timer expires If there is a non NULL CallbackPtr then the application code could have also specified that the callback be called with an argument when the timer expires This is the argument that would be passed in this call NextPtr and PrevPtr are pointers used to link a timer in a doubly linked list These are described later The Remain field contains the amount of time remaining for the timer to expire This value is updated each time the timer task executes described later The value is expressed in multiples of 1 0S_CFG_TMR_TASK_RATE_HZ of a second see os_cfg_app h The Dly field contains the one shot time when the timer is configured i e created as a one shot timer and the initial delay when the timer is created as a periodic timer The value is expressed in multiples of 1 0S_CFG_TMR_TASK_RATE_HZ of a second see os_cfg_app h The Period field is the timer period when the timer is created to opera
32. uC LIB consists of library functions meant to be highly portable and not tied to any specific compiler This facilitates third party certification of Micrium products wC OS III does not use any uC LIB functions however uC OS II and uC CPU assumes the presence of lib_def h for such definitions as DEF_YES DEF_NO DEF_TRUE DEF_FALSE DEF_ON DEF_OFF and more Micrium Software uC LIB lib_ascii c lib_ascii h lib_def h lib_math c lib_math h lib_mem c lib_mem h lib_str c lib_str h Cfg Template lib_cfg h Ports lt architecture gt lt compiler gt lib_mem_a asm Micrium Contains all software components and projects provided by Micrium Software This sub directory contains all software components and projects uC LIB This is the main uC LIB directory lib_ascii c and lib_ascii h contain source code to replace some standard library functions such as tolower toupper isalpha isdigit etc with uwC LIB equivalent functions ASCII_ToLower ASCII_ToUpper ASCII_IsAlpha and ASCII_IsDig respectively Copyright 2015 Micrium Inc 47 uC OS III User s Manual lib_def h defines constants for many common values such as TRUE FALSE YES NO ENABLED DISABLED as well as for integer octet and bit values However all define in this file starts with DEF_ so those constants are actually called DEF_TRUE DEF_FALSE DEF_YES DEF_NO DEF_ENABLED DEF_DISABLED etc This file also contains macros for
33. uC OS III will instead exit through OsIntctxsw because the tick ISR has a higher priority than the idle task STEP 5 You should now Step Into the code for oS_ISR_EXIT and Step Over OSIntExit os_core c OSIntExit should not return to its caller but instead call OSIntCtxSw os_cpu_a asm as shown below At this point OSTCBHighRdyPtr should point at OSTickTaskTCB OSIntCtxSw OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr OS_CTX_RESTORE Return from Interrupt Exception STEP 6 Before going any further in the code you should set a breakpoint in OS_TickTask os_tick c as shown below void OS_TickTask void p_arg Copyright 2015 Micrium Inc 380 uC OS III User s Manual OS_ERR err CPU_TS ts p_arg p_arg while DEF_ON void OSTaskSemPend OS_TICK lt Set BREAKPOINT here OS_OPT OS_OPT_PEND_ BLOCKING CPU_TS amp ts OS_ERR amp err if err OS_ERR_NONE OS_CRITICAL_ENTER OSTickCtr OS_CRITICAL_EXIT ts_delta_dly OS_TickListUpdateDly ts_delta_timeout OS_TickListUpdateTimeout ts_delta ts_delta_dly ts_delta_timeout if OSTickTaskTimeMax lt ts_delta OSTickTaskTimeMax ts_delta STEP 7 You should then go back to os_cpu_a asm and Step Into the code for OS_CTX_RESTORE and then execute the Return from Interrupt Exception instruction This should cause the code to c
34. 1 60 64 The Timer Task vs nace ester vite haa ie Bae BA ie a l aea ees 123 1 6 6 5 The ISR Handler Task 2 2 i e bee et ee ek ee eed eed eee ee ee dee ee 125 1 7 The Ready Eist Tose eiae Sika eke ats ge oie aka Lak be ae ee Cie Sh og 126 be Priority Levels ave ecw sack eee at karaeloko dada wed adel ohan ica ey AVA ties 127 1 7 2 About th Ready List ose serene bed dee oe det eey enti Shee ook bee ek eee Sede ek 131 1 7 3 Adding Tasks to the Ready List 0 0 ee cece eect ene nee 134 1 8 Sched lins ss s 02 4 24 des gear Gok oh Gk bi dee Been Fee be hae EE E db neti eek eld Feet 136 18 1 Preemptive Scheduling 20 4 02 cc enn Gace ate dg Bo Lee Sok ent ee e o e 137 1 8 2 Scheduling Ponts ssi sce taste ia p E E o a bebe EE EREE EE eae eae 140 1 8 3 Round Robin Scheduling 0 0 0 cece ene n ene e eens 142 1 8 4 Scheduling Internals s ee oa a ete COR Ce he Ghee Vanes Mite 144 L 9 Context S witching 2 48 succeded a E E E E E EDE E AE taal ta takes DS 147 WITOSCXSW Seen hoes atine ed Wes aaas Wel as Re ded we ea a a e ee Wo Ea eee eas 150 1 92 OSIMCES wes caer E cael Ge cdot Gate SLOG ee LR PAR ST Saad Bad BBM OR ee ae i 153 1 10 Interrupt Management spie ey tec Si eee ban eed data dar ae eae 155 1 10 1 Handling CPU Interrupts 2 cc cee eect eens 156 1 10 2 Typical uC OS II Interrupt Service Routine 0 0 eee eee 158 1 10 3 FAST Interrupt Service Routine 2 0 0 0 ccc eee DEE ee nee 161 1 10 4 Processors
35. 5 Task Figure Event Flags used for Status and Transient Events 280 uC OS III User s Manual Synchronizing Multiple Tasks Synchronizing the execution of multiple tasks by broadcasting to a semaphore is a commonly used technique It may be important to have multiple tasks start executing at the same time Obviously on a single processor only one task will actually execute at one time However the start of their execution will be synchronized to the same time This is called a multiple task rendez vous However some of the tasks synchronized might not be waiting for the semaphore when the broadcast is performed It is fairly easy to resolve this problem by combining semaphores and event flags as shown in the figure below For this to work properly the task on the left needs to have a lower priority than the tasks waiting on the semaphore Timeout OSSemPend osS_ m 2 OSSemPost _ p ___ OSSemPend Broadcast gt 4 N ks PS OSSemPend OS_FLAG_GRP OSFlagPend AND Consume OSF lagPost lt 4 0SFlagPost lt A OSF lagP ost ________ _ Figure Multiple Task Rendezvous 1 Each task that needs to synchronize at the rendez vous needs to set an event flag bit and specify 0S_OPT_POST_NO_SCHED 2 The task needs to wait for the semaphore to be signaled Copyright 2015 Micrium Inc 281 uC OS III User s Manual 3 The task that will be broadcasting must wait for a11
36. At that point it is known that the current task s stack is corrupted Without an application hook uC OS III simply calls the software based exception Which stops the execution of the application See the uC OS III API Reference for information regarding OSRedzoneHitHook Note that the size of the Redzone is determined by 0S_CFG_TASK_STK_REDZONE_DEPTH By default it is 8 CPU_STK elements deep Hence the effectively usable stack space is reduced by 8 elements Copyright 2015 Micrium Inc 85 uC OS III User s Manual Stack RAM Low Memory amp MyTaskStk 0 Redzone Depth StkLimitPtr SP Current Stack Usage Stack Growth amp MyTaskStk N 1 High Memory lt 4 CPU STK gt Figure Redzone Stack Overflow detection 5 Counting the amount of free stack space Another way to check for stack overflows is to allocate more stack space than is anticipated to be used for the stack then monitor and possibly display actual maximum stack usage at run time This is fairly easy to do First the task stack needs to be cleared i e filled with zeros when the task is created Next a low priority task walks the stack of each task created from the bottom amp yTaskStk towards the top counting the number of zero entries When the task finds a non zero value the process is stopped and the usage of the stack can be computed in number of bytes used or as a percentage Then you can adjust the size of the stacks by recompiling
37. BSP_OS_TickNextSet s pseudo code is listed below OS_TICK BSP_OS_TickNextSet OS_TICK ticks If needed stop the Timer Convert the needed ticks in dynamic timer ticks Verify and adjust the dynamic timer tick so that it does not overflow and still expresses an even number of OS_TICKs Set the Timer to interrupt after the calculated dynamic timer ticks have elapsed Save the number of effective OS ticks that will elapse before next interrupt If stopped restart the Timer Return the the number of effective OS ticks that will elapse before next interrupt Listing BSP_OS_TickNextSet Pseudo code Copyright 2015 Micrium Inc 348 uC OS III User s Manual os_cpu h OS_TASK_SW OS_TASK_SW is a macro that is called by oSSched to perform a task level context switch The macro can translate directly to a call to oSCtxSw trigger a software interrupt or a TRAP If a software interrupt or TRAP is used then you would most likely need to add the address of OsctxSw in the interrupt vector table The choice depends on the CPU architecture OS_TS_GET OS_TS_GET is a macro that obtains the current time stamp It is expected that the time stamp is type CPU_TS which is typically declared as at least a 32 bit value OSCtxSw OSIntCtxSw and OSStartHighRdy os_cpu h declares function prototypes for OSCtxSw OSIntCtxSw OSStartHighRdy and possibly other functions required by the port OS _cpu_c c The func
38. CPU_TS ts while DEF_ON OSFlagPend amp MyEventFlagGrp TEMP_LOW BATT_LOW OS_TICK OS_OPT OS_OPT_PEND_ FLAG SET_ANY amp ts amp err Check err void MyISR void OS_ERR err OSFlagPost amp MyEventFlagGrp BAT_LOW OS_OPT OS_OPT_POST_FLAG SET amp err Check err Listing Using Event Flags 1 You need to define some bits in the event flag group 1 2 3 4 5 6 7 2 You have to declare an object of type 0S_FLAG_GRP This object will be referenced in all subsequent uC OS III calls that apply to this event flag group For the sake of discussions assume that event flags are declared to be 16 bits in os_type h i e of type Copyright 2015 Micrium Inc 277 uC OS III User s Manual 3 4 5 6 7 Copyright 2015 Micrium Inc CPU_INT16U Event flag groups must be created before they can be used The best place to do this is in your startup code as it ensures that no tasks or ISR will be able to use the event flag group until uC OS III is started In other words the best place is to create the event flag group is in main In the example the event flag was given a name and all bits start in their cleared state i e all zeros You can assume here that the application created MyTask which will be pending on the event flag group To pend on an event flag group you call OSFlagPend and pass it
39. III User s Manual 2 3 4 consists of a series of bits 8 16 or 32 bits based on the data type 0S_FLAGS defined in os_type h The event flag group also contains a list of tasks waiting for some or all of the bits to be set or clear 1 or 0 An event flag group must be created before it can be used by tasks and ISRs You need to create event flags prior to starting C OS IIL or by a startup task in the application code Tasks or ISRs can post to event flags In addition only tasks can create delete and stop other task from pending on event flag groups A task can wait i e pend on any number of bits in an event flag group i e a subset of all the bits As with all C OS III pend calls the calling task can specify a timeout value such that if the desired bits are not posted within a specified amount of time in ticks the pending task is resumed and informed about the timeout The task can specify whether it wants to wait for any subset of bits OR to be set or clear or wait for all bits in a subset of bit AND to be set or clear There are a number of operations to perform on event flags as summarized in the table below Function Name Operation OSF lagCreate Create an event flag group OSF lagDel Delete an event flag group OSF lagPend Pend i e wait on an event flag group OSF lagPendAbort Abort waiting on an event flag group OSF lagPendGetF lagsRdy Get flags that caused
40. III User s Manual CPU_STK OSTaskStkInit OS_TASK_PTR p_task void p_arg CPU_STK p_stk_base CPU_STK p_stk_limit CPU_STK_SIZE stk_size OS_OPT opt 1 2 Copyright 2015 Micrium Inc CPU_STK p_stk void opt p_stk amp p stk_base stk_size 1 p stk CPU_STK 0xee e000e0u 2 p stk CPU_STK p_task 3 p stk CPU_STK p_arg 4 p stk CPU_STK 0x 1010101u 5 p stk CPU_STK 0x 2020202u p stk CPU_STK 0x03030303u p stk CPU_STK 0xe4040404u p stk CPU_STK 0x 5050505u p stk CPU_STK 0x 6060606u p stk CPU_STK 0x 7070707uU p stk CPU_STK 0x 8 80808u p stk CPU_STK 0x 9090909U p stk CPU_STK 0x10101010U p stk CPU_STK 0x11111111uU p stk CPU_STK 0x12121212u p stk CPU_STK OS_TaskReturn 6 return p_stk 7 Listing Generic OSTaskStkInit You need to initialize the top of stack For our generic 32 bit CPU the top of stack TOS points at one location beyond the area reserved for the stack This is because we will decrement the TOS pointer before storing a value into the stack If the stack for the processor grew from low memory to high memory most likely you would have setup the TOS to point at the base of the memory or amp p_stk_base Since we are simulating an interrupt and the stacking of registers in the same order as an ISR would place them on the stack we start by putting the SR
41. Inc uC OS III User s Manual BUF BufReq void BUF ptr Wait on semaphore ptr OSMemGet Get a buffer syi return ptr void BufRel BUF ptr OSMemPut void ptr Return the buffer Signal semaphore Listing Buffer management using a semaphore Note that the details of creating the memory partition are removed since this is discussed in Memory Management API Changes The semaphore is used here to extend the memory management capabilities of uC OS III and to provide it with a blocking mechanism However only tasks can make BufReq and BufRel calls Copyright 2015 Micrium Inc 223 uC OS III User s Manual Notes on Semaphores Using a semaphore to access a shared resource does not increase interrupt latency If an ISR or the current task makes a higher priority task ready to run while accessing shared data the higher priority task executes immediately An application may have as many semaphores as required to protect a variety of different resources For example one semaphore may be used to access a shared display another to access a shared printer another for shared data structures and another to protect a pool of buffers etc However it is preferable to use semaphores to protect access to I O devices rather than memory locations Semaphores are often overused The use of a semaphore to access a simple shared variable is overkill in most situations The overhead involve
42. NULL value Copyright 2015 Micrium Inc 312 uC OS III User s Manual while all the other entries have the RdyObjPtr set to NULL Going back to the case where a task waits on five semaphores and two message queues if the first message queue is posted while the task is pending on all those objects the OS_PEND_DATA table will be as shown in the figure below PrevPtr NextPtr TCBPtr PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS fo resp Pender o J o J o mO freer Penos o o o x Oe rce Ponson 0 o o amyar MsgPw Msg size Timestamp T A ie eI C o o reee emar a Co respir Penaoni Figure Message queue 1 posted before timeout expired Copyright 2015 Micrium Inc 313 uC OS III User s Manual Memory Management An application can allocate and free dynamic memory using any ANSI C compiler s malloc and free functions respectively However using malloc and free in an embedded real time system may be dangerous Eventually it might not be possible to obtain a single contiguous memory area due to fragmentation Fragmentation is the development of a large number of separate free areas i e the total free memory is fragmented into small non contiguous pieces Execution time of malloc and free is generally nondeterministic given the algorithms used to locate a contiguous block of free memory large enough to satisfy a malloc request uC OS III provides
43. OS II function calls and are thus implemented as shown in Listing 9 2 It s important to note that since uC OS III cannot disable these interrupts interrupt latency for these interrupts is very short Listing 9 3 shows how to implement non kernel aware ISRs when the processor supports multiple interrupt priorities MyNonKernelAwareISR 1 Save enough registers as needed by the ISR 2 Clear interrupting device 3 Enable higher priority interrupts optional 4 Call user ISR 5 Restore the saved CPU registers 6 Return from interrupt 7 1 2 3 4 5 Copyright 2015 Micrium Inc Listing Non Kernel Aware ISRs for Processors with Multiple Priority Levels As mentioned above an ISR is typically written in assembly language MyNonKernelAwarelISR corresponds to the name of the handler that will handle the interrupting device Here you save sufficient registers as required to handle the ISR The user probably needs to clear the interrupting device to prevent it from generating the same interrupt once the ISR returns At this point you could enable higher priority interrupts assuming that the CPU disables all interrupts when the interrupt is accepted However you don t want to enable kernel aware or lower priority interrupts Now you can take care of the interrupting device in assembly language or call a C function if necessary 163 uC OS III User s Manual 6 Once finishe
44. OS II API Reference for a list of possible error codes Even though uC OS III allows for very long delays for tasks it is actually not recommended to delay tasks for a long time The reason is that there is no indication that the task is actually alive unless it is possible to monitor the amount of time remaining for the delay It is better to have the task wake up approximately every minute or so and have it tell you that it is still ok OSTimeDly is often used to create periodic tasks tasks that execute periodically For example it is possible to have a task that scans a keyboard every 50 milliseconds and another task that reads analog inputs every 10 milliseconds etc OSTimeDlyResume Resume a Delayed Task A task can resume another task that called OSTimeDly or OSTimeDlyHMSM by calling OSTimeDlyResume The listing below shows how to use OSTimeDlyResume The task that delayed itself will not know that it was resumed but will think that the delay expired Because of this use this function with great care Copyright 2015 Micrium Inc 191 uC OS III User s Manual OS_TCB MyTaskTCB void MyTask void p_arg OS ERR err while DEF_ON OSTimeDly 10 OS_OPT_TIME_DLY amp err Check err void MyOtherTask void p_arg OS_ERR err while DEF_ON OSTimeDlyResume amp MyTaskTCB amp err Check err Listing OSTimeDly Resume OSTimeGet
45. OS III was designed to be portable and since uC OS III is similar to uC OS II the user can start from a wC OS II port In fact this is the easiest way to do a uC OS III port If there is already a port for the processor to be used it is not necessary to read this chapter unless of course there is an interest in knowing how uC OS III processor speci c code works uC OS III can run on a processor if it satisfies the following general requirements e The processor has an ANSI C compiler that generates reentrant code In fact the toolchain used must contain an assembler C compiler and linker locator Finding such a toolchain is generally not an issue since there are a number of good toolchains available on the market The processor supports interrupts and can provide an interrupt that occurs at regular intervals typically between 10 and 1000 Hz Most processors especially MCUs provide timer that can be used for this purpose Some processors even have dedicated timers for use by an RTOS e Interrupts can be disabled and enabled All current processors that we ve worked with offer this Ideally the processor allows you to save the current state of the interrupt mask so that it can be restored The processor supports a hardware stack that accommodates a fair amount of data possibly many kilobytes The processor has instructions to save and restore the stack pointer and other CPU registers either on the stack or in
46. OS IT ww ccc cece cece n ene nee 50 1 4 1 Single Task Application 0 0 0 eee cece eben e beeen nee 51 1 4 2 Multiple Tasks Application with Kernel Objects 0 0 0 0 c cece eee ee 58 I S Critical Sections i0 6k ia eee ee oie eek oe eek doen koa eek E 65 1 5 1 Disabling Interrupts 2 22 eee era ee a ee ee Ee bee be pea be eb bee 66 1 5 1 1 Measuring Interrupt Disable Time 0 0 0 cee cece cence 67 1 5 2 Locking the Scheduler o1s 0p0840 0 ch cihae egietas HEE a Ree te Seta eae ede 68 1 5 2 1 Measuring Scheduler Lock Time 0 0 0 c eee ccc eee 69 1 5 3 uC OS III Features with Longer Critical Sections 0 0 0 0 cece cece eee 70 1 6 About Task Management s 2 00 ee cee beeen cee et cede bene debe a O 71 1 6 1 Assigning Task Priorities ove wavawiad ei ee ian alta wea Ge Ree A ee 719 1 6 2 Determining the Size of a Stack 1 0 Lecce cece e eens 81 1 6 3 Detecting Task Stack Overflows 0 ccc cee eee n teen ence 82 1 6 4 Task Management Services iras 0 0 eee ce eee e eee eben teen ence 88 1 6 5 Task Management Internals 0 0 ee ccc cece a E a aea 89 1 6 6 Internal Tasks 2 4 c6s2 Y ote cided ga othe date Ae oe ek aoe oa cae ee 109 1 6 6 1 The Idle Task oeo iio mere Boca we Bethe Bi eh PE AR ee ee 110 1 6 6 2 Th Tick Task iene cere 5 ayes eee bese Aon Ena EE Sg dtd SR EN od eu hee Ged 112 1 6 6 3 The Statistic Task 3 022 0c0s0adeestesieatiede eb ie tie ia aba E a 119
47. OSFlagPost returns an error code based on the outcome of the call If the call was successful err will contain OS_ERR_NONE If not the error code will indicate the reason of the error see Appendix A wC OS HI Configuration Manual for a list of possible error codes for OSFlagPost Using Event Flags When a task or an ISR posts to an event flag group all tasks that have their wait conditions satisfied will be resumed It s up to the application to determine what each bit in an event flag group means and it is possible to use as many event flag groups as needed In an event flag group you can for example define that bit 0 indicates that a temperature sensor is too low bit 1 may indicate a low battery voltage bit 2 could indicate that a switch was pressed etc The code tasks or ISRs that detects these conditions would set the appropriate event flag by calling OSFlagPost and the task s that would respond to those conditions would call OSFlagPend The listing below shows how to use event flags Copyright 2015 Micrium Inc 276 uC OS III User s Manual define TEMP_LOW OS_FLAGS x0001 define BATT_LOW OS_FLAGS x0002 define SW_PRESSED OS_FLAGS 0x0004 OS_FLAG_GRP MyEventFlagGrp void main void OS_ERR err OSInit amp err OSFlagCreate amp MyEventFlagGrp My Event Flag Group OS_FLAGS amp err Check err OSStart amp err void MyTask void p_arg OS ERR err
48. OS_ERR amp err if err OS_ERR TIMEOUT RPM else if delta gt Qu RPM 60 ReferenceFrequency delta Copyright 2015 Micrium Inc 300 uC OS III User s Manual 1 2 3 4 Copyright 2015 Micrium Inc Compute average RPM Detect maximum RPM Check for overspeed Check for underspeed Listing Pseudo code of RPM measurement Instead of declaring a message queue it is important to know the os_TCB of the task that will be receiving messages The RPM task is created and a queue size of 10 entries is specified Of course hard coded values should not be specified in a real application but instead you should use defines Fixed numbers are used here for sake of illustration Instead of posting to a message queue the ISR posts the message directly to the task specifying the address of the 0s_TcB of the task This is known since the 0S_TCB is allocated when creating the task The RPM task starts by waiting for a message from the RPM ISR by calling OSTaskQPend This is an inherent call so it is not necessary to specify the address of the OS_TCB to pend on as the current task is assumed The second argument specifies the timeout Here ten seconds worth of timeout is specified which corresponds to 6 RPM 301 uC OS III User s Manual Clients and Servers Another interesting use of message queues is shown in the figure below Here a task the server is used to monit
49. Ports MyCPUName MyToolsName os_cpu h os_cpu_a asm os_cpu_a inc os_cpu_c c Source os h os_cfg_app c os_core c os_dbg c a ih VE FT Copyright 2015 Micrium Inc 7 lt See the section wC CPU lt See the section ywC CPU lt See the section yC OS III port lt See the section yC OS III port lt See the section yC OS III port lt See the section yC OS III port 369 uC OS III User s Manual os_flag c os_int c os_mem c os_msg c os_mutex c os_pend_multi c os_prio c os_q c os_sem c os_stat c os_task c os_tick c os_time c os_tmr c os_type h os_var c Listing Test Code Directory Structure 1 MyTest is the name of the directory that will contain the project source files 2 app c is the test file that contains main and should look as shown below app c Copyright 2015 Micrium Inc include includes h void main void OS_ERR err OSInit amp err OSStart amp err Listing main Example 3 includes h is a master include file that app c and other files assume The contents of this file should be as shown below Note the use of includes h is deprecated Your application should directly include only the needed headers 370 uC OS III User s Manual includes h include include include include include include include include include include include include include include include 4 app_cfg h must exist but s
50. Preempts Done TaskL 10 8 t Tasik o W M o W Task L gets Semaphore 2 Figure Unbounded priority Inversion 1 Task H and Task M are both waiting for an event to occur and Task L is executing 2 At some point Task L acquires a semaphore which it needs before it can access a shared resource 3 Task L performs operations on the acquired resource 4 The event that Task H was waiting for occurs and the kernel suspends Task L and start executing Task H since Task H has a higher priority 5 Task H performs computations based on the event it just received 6 Task H now wants to access the resource that Task L currently owns i e it attempts to Copyright 2015 Micrium Inc 230 uC OS III User s Manual get the semaphore that Task L owns Because Task L owns the resource Task H is placed in a list of tasks waiting for the semaphore to be available 7 Task L is resumed and continues to access the shared resource 8 Task L is preempted by Task M since the event that Task M was waiting for occurred 9 Task M handles the event 10 When Task M completes the kernel relinquishes the CPU back to Task L 11 Task L continues accessing the resource 12 Task L finally finishes working with the resource and releases the semaphore At this point the kernel knows that a higher priority task is waiting for the semaphore and a context switch takes place to resume Task H 13 Task H has the semaphore
51. Suspended 4 OSTaskResume Timeout or Timeout or OS Pend OS Post or OS Post or wi Timeout S PendAbort or 0S PendAbort or OS Del OS Del OSTaskSuspend OS Post or OS Post or Pend OS Pend OSPendAbort or OS PendAbort or OS Del Timeout OS Del Suspended OSTaskResume OSTaskSuspend Pend Suspended 6 OSTaskResume Figure C OS III s internal task state machine 1 A task is in State 0 when a task is ready to run Every task wants to be ready to run as that is the only way it gets to perform their duties 2 A task can decide to wait for time to expire by calling either oSTimeDly or OSTimeDlyHMSM When the time expires or the delay is cancelled by calling OSTimeDlyResume the task returns to the ready state Copyright 2015 Micrium Inc 93 uC OS III User s Manual 3 4 5 6 7 8 Copyright 2015 Micrium Inc A task can wait for an event to occur by calling one of the pend i e wait functions OSFlagPend OSMutexPend OSQPend OSSemPend OSTaskQPend or OSTaskSemPend and specify to wait forever for the event to occur The pend terminates when the event occurs i e a task or an ISR performs a post the awaited object is deleted or another task decides to abort the pend A task can wait for an event to occur as indicated but speci
52. The consumer waits for messages and when processed signals the semaphore Producer Task Pend on Semaphore Send message to message queue Consumer Task Wait for message from message queue Signal the semaphore Listing Producer and consumer flow control Combining the task message queue and task semaphores see Synchronization it is easy to Copyright 2015 Micrium Inc 290 uC OS III User s Manual implement flow control as shown in the figure below In this case however OSTaskSemSet must be called immediately after creating the task to set the value of the task semaphore to the same value as the maximum number of allowable messages in the task message queue CallOSTaskSemSet 9 to set queue size A g after task creation ee _ rere oe ss e n a 9 2 3 Uv 3 amp a pee ii Figure Flow control with task semaphore and task message queue Copyright 2015 Micrium Inc 291 uC OS III User s Manual Keeping the Data in Scope The messages sent typically point to data structures variables arrays tables etc However it is important to realize that the data must remain static until the receiver of the data completes its processing of the data Once sent the sender must not touch the sent data This seems obvious however it is easy to forget One possibility is to use the fixed size memory partition manager provided with wC OS III see Memory Management API Change
53. This information is quite useful during debugging as it provides a sense of how well an application is running and the resources being used uC OS III also provides information about the configuration of the system Specifically the amount of RAM used by uC OS III including all internal variables and task stacks The uC OS III variables described in this chapter should be displayed and never changed Copyright 2015 Micrium Inc 383 uC OS III User s Manual General Statistics Run Time The following is a list of uC OS III variables that are not associated to any specific task Interrupts OSIntNestingCtr This variable contains the interrupt nesting level 1 means servicing the first level of interrupt nesting 2 means the interrupt was interrupted by another interrupt etc OSIntDisTimeMax This variable contains the maximum interrupt disable time in CPU_TS units Interrupt Queue OSIntQNbrEntries This variable indicates the current number of entries in the interrupt handler queue OSIntQNbrEntriesMax This variable contains the maximum i e peak number of entries in the interrupt handler queue This variable is reset by oSStatReset OSIntQovfctr This variable shows the number of attempts to post a message from an interrupt to the interrupt handler queue and there was not enough room to place the post call In other words how many times an interrupt was not being able to be serviced by its corresponding task Thi
54. Ticks since last interrupt Save The Last OSTickCtr OSIntExit Listing BSP_OS_DynTickHandler Pseudo code BSP_OS_TickGet This particular function is used by wC OS III to get the OS time OSTickCtr as if it were incremented 0S_CFG_TICK_RATE_HZ times per second BSP_OS_TickGet exists only because the OS time counter isn t incremented periodically Indeed while wC OS II is waiting for Tick Step ticks to elapse an interrupt could occur that would resume a previously interrupted task That task in turn could try to delay itself Now even though the OS time counter hasn t been updated since uC OS III is still waiting for Tick Step ticks to elapse time has still elapsed This function is used to measure how much time has elapsed since oSTickCtr was last updated BSP_OS_TickGet s pseudo code is listed below OS_TICK BSP_OS TickGet void return The Last OSTickCtr The Timer Counter Converted to OS Tick units given the fact that the Timer isn t OS_CFG_TICK_RATE_HZ times per second Listing BSP_OS_TickGet Pseudo code Copyright 2015 Micrium Inc 347 uC OS III User s Manual BSP_OS TickNextSet As explained in The Tick Task this function gets called when a task needs to delay its execution when a task waits with a timeout on a kernel object and every time the Tick task is run The argument passed to this function is the number of OS ticks that need to elapse before the Tick task is run again Th
55. allows users to make time measurements When the event flag group is posted to the free running counter is read and the value is placed in this field which is returned when OSFlagPend is called This value allows an application to determine either when the post was performed or how long it took for your code to obtain control of the CPU from the post In the latter case you can call 0S_TS_GET to determine the current timestamp and compute the difference Even if the user understands the internals of the 0S_FLAG_GRP data type application code should never access any of the fields in this data structure directly Instead you should always use the APIs provided with uwC OS IIL Event flag groups must be created before they can be used by an application as shown in the listing below Copyright 2015 Micrium Inc 271 uC OS III User s Manual OS_FLAG_GRP MyEventFlagGrp 1 void MyCode void 1 2 3 4 5 OS_ERR err OSFlagCreate amp MyEventFlagGrp 2 My Event Flag Group 3 OS_FLAGS 4 amp err 5 Check err Listing Creating a Event Flag Group The application must declare a variable of type 0S_FLAG_GRP This variable will be referenced by other event flag services You create an event flag group by calling OSFlagCreate and pass the address to the event flag group allocated in 1 You can assign an ASCII name to the event flag group which can be used b
56. another task uC OS III switches back to task T1 because Task T2 can no longer continue It needs mutex M1 to access resource R1 Task T1 now tries to access mutex M2 but unfortunately mutex M2 is owned by task T2 At this point the two tasks are deadlocked neither one can continue because each owns a resource that the other one wants Techniques used to avoid deadlocks are for tasks to e Acquire all resources before proceeding e Always acquire resources in the same order e Use timeouts on pend calls uC OS III allows the calling task to specify a timeout when acquiring a mutex This feature allows a deadlock to be broken but the same deadlock may then recur later or many times later If the mutex is not available within a certain period of time the task requesting the resource resumes execution yC OS III returns an error code indicating that a timeout occurred A return error code prevents the task from thinking it has properly obtained the resource The pseudo code avoids deadlocks by first acquiring all resources as shown in Listing 13 17 Copyright 2015 Micrium Inc 245 uC OS III User s Manual void T1 void p_arg while DEF_ON Wait for event to occur Acquire M1 Acquire M2 Access R1 Access R2 void T2 void p_arg while DEF_ON Wait for event to occur Acquire M1 Acquire M2 Access R1 Access R2 Listing Deadlock avoidance acquire all first and in the same order
57. array must be NUL terminated You specify the initial value of the semaphore You should initialize the semaphore to 1 when the semaphore is used to access a single shared resource as in this example OSSemCreate returns an error code based on the outcome of the call If all the arguments are valid err will contain OS_ERR_NONE Refer to the description of OSSemCreate in Appendix A wC OS II API Reference for a list of other error codes and their meaning Copyright 2015 Micrium Inc 216 uC OS III User s Manual void Task1 void p_arg OS ERR err CPU_TS ts while DEF_ON OSSemPend amp MySem 1 a 2 OS_OPT_PEND_BLOCKING 3 ats 4 amp err 5 switch err case OS_ERR_NONE Access Shared Resource 6 OSSemPost amp MySem 7 OS_OPT_POST_1 8 amp err 9 Check err break case OS_ERR_PEND_ ABORT The pend was aborted by another task vf break case OS_ERR_OBJ_DEL The semaphore was deleted Sif break default Other errors E Listing Using a semaphore to access a shared resource 1 The task pends or waits on the semaphore by calling OSSemPend The application must specify the desired semaphore to wait upon and the semaphore must have been previously created 2 The next argument is a timeout specified in number of clock ticks The actual timeout depends on the tick rate If the tick rate see os_cfg_app h is set to 1000 a timeout of 10 tic
58. as the ISR Epilogue 160 uC OS III User s Manual FAST Interrupt Service Routine The above sequence assumes that the ISR signals or sends a message to a task However in many cases the ISR may not need to notify a task and can simply perform all of its work within the ISR assuming it can be done quickly In this case the ISR will appear as shown in Listing 9 2 MyShortISR 1 Save enough registers as needed by the ISR 2 Clear interrupting device 3 DO NOT re enable interrupts 4 Call user ISR 5 Restore the saved CPU registers 6 Return from interrupt 7 Listing Fast ISRs with C OS III 1 As mentioned above an ISR is typically written in assembly language MyShortISR 2 3 4 5 6 7 Copyright 2015 Micrium Inc corresponds to the name of the handler that will handle the interrupting device Here you save sufficient registers as required to handle the ISR The user probably needs to clear the interrupting device to prevent it from generating the same interrupt once the ISR returns Do not re enable interrupts at this point since another interrupt could make uC OS III calls forcing a context switch to a higher priority task This means that the above ISR would complete but at a much later time and possible cause other complications Now you can take care of the interrupting device in assembly language or call a C function if necessary Once finished simply restore
59. available from wC OS II Refer to wC OS III API Reference for a full description of their use Function Name Operation OSTaskQPend Wait for a message OSTaskQPendAbort Abort the wait for a message OSTaskQPost Send a message to a task OSTaskQFlush Empty the message queue Table Task message queue API summary The figure below shows an example of using a message queue when determining the speed of a rotating wheel Copyright 2015 Micrium Inc 294 uC OS III User s Manual 1 2 3 4 Previous Counts 5 Message Queue OSQPost gt OSQPend 6 X 7 Current Timeout Sensor Counts 2 RPM 32 bit Reference Input Capture Average RPM Frequency 8 Maximum RPM 3 Underspeed Overspeed Figure Measuring RPM The goal is to measure the RPM of a rotating wheel A sensor is used to detect the passage of a hole in the wheel In fact to receive additional resolution the wheel could contain multiple holes that are equally spaced A 32 bit input capture register is used to capture the value of a free running counter when the hole is detected An interrupt is generated when the hole is detected The ISR reads the current count of the input capture register and subtracts the value of the previous capture to determine the time it took for one rotation assuming only a single hole Delta Counts Current Counts Previous Counts Previous Counts Current Counts 5 6 T
60. calls should be short in the Deferred Post Method because it only involves copying the post call and its arguments into the interrupt queue The difference is that in the Deferred Post Method interrupts are disabled for a very short amount of time and thus the first three metrics should be fast However task latency is higher as uC OS III locks the scheduler to access critical sections Direct Post Method The Direct Post Method is used by uC OS II and is replicated in wC OS UI This method is enabled by default the Deferred Post method is currently DEPRECATED and will be removed in a future uC OS III release The figure below shows a task diagram of what takes place in a Direct Post New High Priority uC OS lll of Disables Interrupts r a in Critical Sections Figure Direct Post Method 1 A device generates an interrupt Copyright 2015 Micrium Inc 171 uC OS III User s Manual 2 The Interrupt Service Routine ISR responsible to handle the device executes assuming interrupts are enabled The device interrupt is generally the event a task is waiting for The task waiting for this interrupt to occur either has a higher priority than the interrupted task or lower or equal in priority 3 Ifthe ISR made a lower or equal priority task ready to run then upon completion of the ISR uC OS III returns to the interrupted task exactly at the point the interrupt occurred 4 Ifthe ISR made a h
61. can perform on message queues summarized in the figure below However an ISR can only call osgPost A message queue must be created before sending messages through it OSQCreate OSQDel osaFiush Message Queue OSQPendAbort jaa x Timeout ees Figure Operations on message queue Message queues are drawn as a first in first out pipe FIFO However with C OS III it is possible to post messages in last in first out order LIFO The LIFO mechanism is useful when a task or an ISR must send an urgent message to a task In this case the message bypasses all other messages already in the message queue The size of the message queue is configurable at run time The small hourglass close to the receiving task in the figure above indicates that the task has an option to specify a timeout This timeout indicates that the task is willing to wait for a message to be sent to the message queue within a certain amount of time If the message is not sent within that time C OS III resumes the task and returns an error code indicating that the task was made ready to run because of a timeout and not because the message was received It is possible to specify an infinite timeout and indicate that the task is willing to wait forever for the message to arrive The message queue also contains a list of tasks waiting for messages to be sent to the message queue Multiple tasks can wait on a message queue as shown in the figure below Wh
62. created at the same priority as the idle task The idle task runs whenever there are no other tasks that are ready to run If RAM space is tight the idle task can be removed This allows the user to save some data space since there is no need to have a stack for the idle task However even if there is not an actual task running at priority OS_CFG_PRIO_MAX 1 the user cannot create a task at that priority level The level is still used to determine when to idle the CPU The important portions of the code for the idle task are shown below refer to os_core c for the complete code These portions are still executed even if the idle task is disabled in os_cfg h void OS_IdleTask void p_arg while DEF_ON 1 CPU_CRITICAL_ENTER OSIdleTaskCtr 2 OSStatTaskCtr CPU_CRITICAL_EXIT OSIdleTaskHook 3 Listing Idle Task 1 The idle task is a true infinite loop that never calls functions to wait for an event This is because on most processors when there is nothing to do the processor still executes instructions When uC OS II determines that there is no other higher priority task to run uC OS III parks the CPU in the idle task However instead of having an empty infinite loop doing nothing uC OS III uses this idle time to do something useful 2 Two counters are incremented whenever the idle task runs OSIdleTaskCtr is typically defined as a 32 bit unsigned integer
63. entry in the ready list Entries is set to zero 0 if there are no tasks ready to run at a given priority level TailPtr and HeadPtr are used to create a doubly linked list of all the tasks that are ready at a specific priority HeadPtr points to the head of the list and TailPtr points to its tail The index into the array is the priority level associated with a task For example if a task is created at priority level 5 then it will be inserted in the table at OSRdyList 5 if that task is ready to run The table below shows the functions that uC OS III uses to manipulate entries in the ready list These functions are found in os_core c and are internal to uC OS III so the application code must never call them Function Description OS_RdyListInit Initialize the ready list to empty see the figure below OS_RdyListInsert Insert a TCB into the ready list OS_RdyListInsertHead Insert a TCB at the head of the list OS_RdyListInsertTail Insert a TCB at the tail of the list OS_RdyListMoveHeadToTail Move a TCB from the head to the tail of the list OS_RdyListRemove Remove a TCB from the ready list Table Ready List access functions Copyright 2015 Micrium Inc 131 uC OS III User s Manual 2 3 Copyright 2015 Micrium Inc OS_RDY_LIST OSRdyList OS_CFG_PRIO MAX OSRdyList 0 entries 0 Pr gt 0 HeadPtr 0 TailPtr 1 Entries 4 0 HeadPtr 0 TailPtr 2 Entries o 0 HeadPtr 0
64. file os_core c You should see the following code void OSStart OS_ERR p_err ifdef OS_SAFETY_CRITICAL if p_err OS_ERR OS_SAFETY_CRITICAL_EXCEPTION return endif if OSRunning OS_STATE_OS_STOPPED OSPrioHighRdy OS PrioGetHighest 1 OsPrioCur OSPrioHighRdy OSTCBHighRdyPtr OSRdyList OSPrioHighRdy HeadPtr 2 OSTCBCurPtr OSTCBHighRdyPtr OSRunning OS_STATE_OS_RUNNING OsStartHighRdy 3 p err OS_ERR_FATAL_RETURN else p err OS_ERR_OS RUNNING STEP 4 Step into the code and stop just before executing OSStartHighRdy You should confirm that OSPrioCur is the same value as OS_CFG_TICK_TASK_PRIO see os_cfg_app h and that OSTCBHighRdyPtr point at OSTickTaskTCB In other words the highest priority task should be the tick task because we should only have two task created after OSInit and the tick task always has a higher priority than the idle task Copyright 2015 Micrium Inc 373 uC OS III User s Manual STEP 5 Now Step Into osstartHighRdy file os_cpu_a asm You should see the assembly language shown below OSStartHighRdy OSTaskSwHook SP OSTCBHighRdyPtr gt StkPtr OS_CTX_RESTORE Return from Interrupt Exception You can Step Over OSTaskSwHook and the code to load the stack pointer However you should set a breakpoint at the Return from Interrupt Exception instruction Once you executed the O0S_CTX_RESTORE macro you
65. got switched out The field is enabled at compile time when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CyclesStart This field is used to measure how long a task had control of the CPU cyclesStart is updated when uC OS III performs a context switch CyclesStart contains the value of the current time stamp it calls 0S_TS_GET when a task is switched in The field is enabled at compile time when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CyclesTotal This field accumulates the value of cyclesDelta so it contains the total execution time of a task during a set period of time CyclesTotal is used by 0S_StatTask to determine CPU usage on a per task basis This is typically a 32 bit value because of the accumulation of cycles over time On the other hand using a 64 bit value ensures that we can accumulate CPU cycles for almost 600 years even if the CPU is running at 1 GHz Of course it s assumed that the compiler supports 64 bit data types The field is enabled at compile time when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CyclesTotal is used by 0S_StatTask to determine CPU usage on a per task basis SemPendTime This field contains the amount of time taken for the semaphore to be signaled When OSTaskSemPost is called the current time stamp is read and stored in the 0S_TCB see TS When OSTaskSemPend returns the current time stamp is read again and the difference between the t
66. hook function OSTimeTickHook The hook Copyright 2015 Micrium Inc 176 uC OS III User s Manual function allows the implementer of the uC OS III port to perform additional processing when a tick interrupt occurs In turn the tick hook can call a user defined tick hook if its corresponding pointer OS_AppTimeTickHookPtr is non NULL The reason the hook is called first is to give the application immediate access to this periodic time source This can be useful to read sensors at a regular interval not as subject to jitter update Pulse Width Modulation PWM registers and more 2 If wC OS IL is configured for the Deferred Post Method wC OS III reads the current timestamp and defers the call to signal the tick task by placing an appropriate entry in the interrupt queue The tick task will thus be signaled by the Interrupt Queue Handler Task 3 If uC OS II is configured for the Direct Post Method uC OS III signals the tick task so that it can process the time delays and timeouts 4 uC OS III runs the round robin scheduling algorithm to determine whether the time slot for the current task has expired 5 The tick task is also used as the time base for the timers see Resource Management A common misconception is that a system tick is always needed with uC OS IIL In fact many low power applications may not implement the system tick because of the power required to maintain the tick list In other words it is not reasonabl
67. in 1998 This new text was accompanied by the source code that it described and I would again have thousands of developers testing the kernel and providing valuable feedback Among the thousands of readers of my books using the software there were many kernel rookies For them the book provided thorough and accessible coverage of operating system fundamentals Many university professors recognized the book s appeal to new kernel users and started designing entire courses around uC OS II Soon college graduates whose kernel training focused on the operating system made their way into the workforce where they continued to use uC OS II While students gravitated to uC OS II because of my book and readily available source code a substantial number of engineers using wC OS I commercially selected the software for its reliability Definitive proof of the operating system s reliability was provided in July 2000 when DO 178B Level A certification was conferred on an avionics product incorporating uC OS II This certification recognized by the Federal Avionics Administration FAA is awarded to software deemed safe enough to be used in aircraft To this day there are few operating systems that have successfully completed the rigorous testing that certified software must undergo DO 178B certification is only one of uC OS II s credentials Additional certifications include Food and Drug Administration FDA pre market notification 510 k pr
68. in the figure below wC OS III checks to ensure that if the match is computed such that it represents a value that has already gone by then the delay will be zero Tick Task Time Figure OSTimeDly Periodic Copyright 2015 Micrium Inc 188 uC OS III User s Manual OS_ERR err while DEF_ON OSTimeDly 4 1 OS_OPT_TIME PERIODIC 2 amp err Check err 3 Listing OSTimeDly Periodic 1 The first argument specifies the period for the task to execute specifically every four ticks Of course if the task is a low priority task uwC OS III only schedules and runs the task based on its priority relative to what else needs to be executed 2 Specifying 0S_OPT_TIME_PERIODIC indicates that the task is to be ready to run when the tick counter reaches the desired period from the previous call 3 You should always check the error code returned by uC OS IIL Relative and Periodic modes might not look different but they are In Relative mode it is possible to miss one of the ticks when the system is heavily loaded missing a tick or more on occasion In Periodic mode the task may still execute later but it will always be synchronized to the desired number of ticks In fact Periodic mode is the preferred mode to use to implement a time of day clock Finally you can use the absolute mode to perform a specific action at a fixed time after power up For example turn off a light 10 se
69. involved emptied The task then re enables interrupts locks the scheduler and performs the post call as if the post was performed at the task level all along This effectively manipulates critical sections at the task level When the interrupt queue handler task empties the interrupt queue it makes itself not ready to run and then calls the scheduler to determine which task must run next If the original interrupted task is still the highest priority task wC OS II will resume that task If however a more important task was made ready to run because of the post uC OS III will context switch to that task for each as shown below The execution times of the uwC OS HI ISR prologue ISR epilogue OSIntExit and Copyright 2015 Micrium Inc Interrupt Latency Maximum interrupt disable time Interrupt Response Interrupt latency Vectoring to the interrupt handler ISR prologue Interrupt Recovery Handling of the interrupting device Posting a signal or a message to the Interrupt Queue OSIntExit OSIntCtxSw to Interrupt Queue Handler Task Task Latency Interrupt response Interrupt recovery Re issue the post to the object or task Context switch to task Time scheduler is locked 170 uC OS III User s Manual OSIntCtxSw can be measured independently and should be constant It should also be easy to measure the execution time of a post call by using 0S_TS_GET In fact the post
70. it first starts As far as the task is concerned it looks like any other C function that can be called by the code However your code must not call MyTask The call is actually performed through wC OS HI The fourth argument of OSTaskCreate is the actual argument that the task receives when it first begins In other words the p_arg of MyTask In the example a NULL pointer is passed and thus p_arg for AppTaskStart will be a NULL pointer The argument passed to the task can actually be any pointer For example the user may pass a pointer to a data structure containing parameters for the task The next argument to OSTaskCreate is the priority of the task The priority establishes the relative importance of this task with respect to the other tasks in the application A low priority number indicates a high priority or more important task You can set the priority of the task to any value between 1 and 0S_CFG_PRIO_MAX 2 inclusively Avoid using priority 0 and priority 0S_CFG_PRIO_MAX 1 because these are reserved for uC OS III 0S_CFG_PRIO_MAX is a compile time configuration constant which is declared in os_cfg h The sixth argument to OSTaskCreate is the base address of the stack assigned to this task The base address is always the lowest memory location of the stack The next argument specifies the location of a watermark in the task s stack that can be used to determine the allowable stack growth of t
71. it is easy to start from a uC OS II port Converting a uC OS II port to uC OS II takes approximately an hour The process is described in Migrating from uC OS II to uC OS IHI A port involves three aspects CPU OS and board specific code The board specific code is often called a Board Support Package BSP and from uC OS III s point of view requires very little In this section we ll present the steps needed to do a port from scratch Actually you ll be starting from templates files that already contain placeholders for the code you ll need to insert The following is the layout for this section e Conventions e uC CPU Port Files Copyright 2015 Micrium Inc 329 uC OS III User s Manual e uC OS III Port Files BSP Files e Testing a Port Copyright 2015 Micrium Inc 330 uC OS III User s Manual Conventions uC CPU and uC OS III are provided in source form and include template files C and assembly language which contain instructions about what code needs to be inserted and where Specifically you will need to search the source files for four dollar signs i e which are used as placeholders and replace those with the necessary code It is assumed that assembly language code use a file extension of asm Other assembler might require that the extension be s or src If that s the case with your tools simply name the assembly language files using the proper extension It is assumed that commen
72. memory e The processor has access to sufficient RAM for wC OS III s variables and data structures as well as internal task stacks Copyright 2015 Micrium Inc 326 uC OS III User s Manual The compiler should support 32 bit data types For some fast 32 bit processors the compiler should also support 64 bit data types typically long long The figure below shows the uC OS III architecture and its relationship with other software components and hardware When using uC OS III in an application the user is responsible for providing application software and the uC OS III configuration sections Copyright 2015 Micrium Inc 327 uC OS III User s Manual Configuration Files cpu_cfg h 1lib_cfg h os_cfg h os_cfg_ app h pC OS III CPU Independent os_cfg_app c os_type h os_core c os_dbg c os_flag c os_int c os_mem c os_msg c os_mutex c os_pend multi c os _prio c os_q c os_sem c os_stat c os_task c os_tick c os_time c os_tmr c Os_var c os h pC OS III CPU Specific oak cpu_bsp c cpu_def h cpu_a asm cpu_c c os_cpu h os_cpu_a asm os_cpu_a inc pC CPU CPU Specific Application Code app c app h app_cfg h pC LIB Libraries lib_ascii c lib_ascii c lib_def h lib_math c lib_math h lib_mem_a asm lib_mem c lib_mem h lib_str c lib_str h BSP Board Support Package bsp c bsp h bsp_int c bsp_int h os_cpu c c 1 The port developer is responsible for providing the
73. or measure the time difference between two events The free running counter is generally incremented at a fairly high rate for example 1 MHz or more Copyright 2015 Micrium Inc 333 uC OS III User s Manual CPU_CFG_TS 64 EN This define specifies whether 64 bit time stamps are available for this CPU A 64 bit timestamp is typically the value of a free running 64 bit counter possibly made up by counting overflows of a 32 bit counter that is used to make accurate time measurements The application code can obtain the current value of this free running timer at any point in time and use such value to determine when an event occurred or measure the time difference between two events The free running counter is generally incremented at a fairly high rate for example 100 MHz or more CPU_CFG_TS TMR SIZE This define specifies the size in number of bytes of a timestamp A 32 bit timestamp is 4 bytes long while a 64 bit timestamp is 8 bytes long CPU_CFG_INT_DIS MEAS EN This define specifies whether extra code will be inserted to measure interrupt disable time when the code uses CPU_CRITICAL_ENTER and CPU_CRITICAL_EXIT This extra code obviously adds additional interrupt latency because of the measurement artifacts CPU_CFG_INT_DIS MEAS OVRHD_NBR This define is used to account for the interrupt disable time measurement artifacts The value should typically be 1 CPU_CFG_LEAD_ZEROS_ASM_PRESENT This define specifies whet
74. overflows occur often and can lead to some curious behaviors In fact whenever someone mentions that his or her application behaves strangely insufficient stack size is the first thing that comes to mind Copyright 2015 Micrium Inc 81 uC OS III User s Manual Detecting Task Stack Overflows 1 Using an MMU or MPU Stack overflows are easily detected if the processor has a Memory Management Unit MMU or a Memory Protection Unit MPU Basically MMUs and MPUs are special hardware devices integrated alongside the CPU that can be configured to detect when a task attempts to access invalid memory locations whether code data or stack However setting up an MMU or MPU is well beyond the scope of this book 2 Using a CPU with stack overflow detection Some processors however do have simple stack pointer overflow detection registers When the CPU s stack pointer goes below or above depending on stack growth the value set in this register an exception is generated and the exception handler ensures that the offending code does not do further damage possibly issue a warning about the faulty code or even terminate it The StkLimitPtr field in the oS_TcB see Task Control Blocks is provided for this purpose as shown in the figure below Note that the position of the stack limit is typically set at a valid location in the task s stack with sufficient room left on the stack to handle the exception itself assuming the CPU does not h
75. released Memory Partitons NamePtr This is a pointer to an ASCII string that is used to provide a name to the memory partition The ASCII string can have any length as long as it is NUL terminated B1kSize This variable contains the block size in bytes for the memory partition NbrMax This variable contains the maximum number of memory blocks belonging to the memory partition NbrFree This variable contains the number of memory blocks that are available from memory partition The number of memory blocks in use is given by Copyright 2015 Micrium Inc 396 uC OS III User s Manual NbrMax NbrFree Message Queues NamePtr This is a pointer to an ASCII string used to provide a name to the message queue The ASCII string can have any length as long as it is NUL terminated PendList NbrEntries Each message queue contains a wait list of tasks waiting for messages to be sent to the queue The variable represents the number of entries in the wait list MsgQ NbrEntries This variable represents the number of messages currently in the message queue MsgQ NbrEntriesMax This variable represents the maximum number of messages ever placed in the message queue MsgQ NbrEntriesSize This variable represents the maximum number of messages that can be placed in the message queue Event Flags NamePtr This is a pointer to an ASCII string used to provide a name to the event flag group The ASCII string can have an
76. rules No Yes Yes Yes Yes Yes Yes Extensive Yes Yes Yes Yes Yes Yes Yes 70 N A Yes except 7 rules Yes Yes Yes Yes Table 1 1 uC OS uC OS II and uC OS III Features Comparison Chart Copyright 2015 Micrium Inc 27 uC OS III User s Manual uC Probe uC Probe is a Microsoft Windows based application that enables the user to visualize variables in a target at run time Specifically you can display or change the value of any variable in a system while the target is running These variables can be displayed using such graphical elements as gauges meters bar graphs virtual LEDs numeric indicators and many more Sliders switches and buttons can be used to change variables This is accomplished without the user having to write a single line of code uC Probe interfaces to any target 8 16 32 64 bit or even DSPs through one of the many interfaces supported J Tag RS 232C USB Ethernet etc uC Probe displays or changes any variable as long as they are global in the application including uC OS HT s internal variables uC Probe works with any compiler assembler linker able to generate an ELF DWAREF or IEEE695 file This is the exact same file that the user will download to the evaluation board or a final target From this file wC Probe is able to extract symbolic information about variables and determine where variables are stored in RAM or ROM uC Probe also a
77. semaphore the semaphore object contains a pend list as described in Pend Lists 225 uC OS III User s Manual 5 6 A semaphore contains a counter As explained above the counter can be implemented as either an 8 16 or 32 bit value depending on how the data type 0S_SEM_CTR is declared in os_type h uC OS III does not make a distinction between binary and counting semaphores The distinction is made when the semaphore is created If creating a semaphore with an initial value of 1 it is a binary semaphore When creating a semaphore with a value gt 1 it is a counting semaphore In the next chapter you will discover that a semaphore is more often used as a signaling mechanism and therefore the semaphore counter is initialized to zero A semaphore contains a timestamp used to indicate the last time the semaphore was posted uC OS III assumes the presence of a free running counter that allows the application to make time measurements When the semaphore is posted the free running counter is read and the value is placed in this field which is returned when oSSemPend is called The value of this field is more useful when a semaphore is used as a signaling mechanism see Synchronization as opposed to a resource sharing mechanism Even if the user understands the internals of the 0S_SEM data type the application code should never access any of the fields in this data structure directly Instead you should always use t
78. shown as a darker tick mark Beate TI meser Pt Pll ld dd ibd dd 3 7 yC OS Ill Task 1 Priority X Task 2 Priority X Task 3 Priority X Figure Round Robin Scheduling 1 Task 3 is executing During that time a tick interrupt occurs but the time quanta have not expired yet for Task 3 2 On the 4th tick interrupt the time quanta for Task 3 expire 3 pC OS II resumes Task 1 since it was the next task in the list of tasks at priority X Copyright 2015 Micrium Inc 142 uC OS III User s Manual 4 5 6 7 8 that was ready to run Task 1 executes until its time quanta expires i e after four ticks Here Task 3 executes but decides to give up its time quanta by calling the uC OS III function OSSchedRoundRobinYield which causes the next task in the list of tasks ready at priority X to execute An interesting thing occurred when pC OS HI scheduled Task 1 It reset the time quanta for that task to four ticks so that the next time quanta will expire four ticks from this point Task 1 executes for its full time quanta uC OS III allows the user to change the default time quanta at run time through the OSSchedRoundRobinCfg function see Appendix A wC OS II API Reference This function also allows round robin scheduling to be enabled disabled and the ability to change the default time quanta uC OS III also enables the user to specify the tim
79. switch as implemented by OSCtxSw 2 Memory Address High Memory Address 1 osSctxSw begins by saving the status register and program counter of the current task onto the current task s stack The saving order of register depends on how the CPU Copyright 2015 Micrium Inc OSTCBCurPtr 1 OSTCBHighRdyPtr gt CPU Figure Operations performed by OSCtxSw uC OS III User s Manual 2 3 4 Copyright 2015 Micrium Inc expects the registers on the stack frame when an interrupt occurs In this case it is assumed that the SR is stacked first The remaining registers are then saved onto the stack OSCtxSw saves the contents of the CPU s stack pointer into the os_TcB of the task being context switched out In other words OSTCBCurPtr gt StkPtr R14 osctxSw then loads the CPU stack pointer with the saved top of stack from the new task s oS_TCB In other words R14 OSTCBHighRdyPtr gt StkPtr Finally osctxSw retrieves the CPU register contents from the new stack The program counter and status registers are generally retrieved at the same time by executing a return from interrupt instruction 152 uC OS III User s Manual OSIntCtxSw OSIntCtxSw See os_cpu_a asm is called when the ISR level scheduler OSIntExit determines that a new high priority task is ready to execute The figure below shows the state of several uC OS III variables and data structure
80. task OS_TmrTask and the interrupt handler queue management task 0S_IntQTask Those are all discussed in About Task Management Most of wC OS III s functions return an error code via a pointer to an OS_ERR variable err in this case If OSInit was successful err will be set to OS_ERR_NONE If OSInit encounters a problem during initialization it will return immediately upon detecting the problem and set err accordingly If this occurs look up the error code value in os h Specifically all error codes start with OS_ERR_ It is important to note that OSInit must be called before any other uC OS III function You create a task by calling OSTaskCreate OSTaskCreate requires 13 arguments The first argument is the address of the os_TcB that is declared for this task About Task Management provides additional information about tasks OSTaskCreate allows a name to be assigned to each of the tasks wC OS III stores a pointer to the task name inside the os_TcB of the task There is no limit on the number of ASCII characters used for the name The third argument is the address of the task code A typical uC OS III task is implemented as an infinite loop as shown 53 uC OS III User s Manual 6 7 8 9 10 Copyright 2015 Micrium Inc void MyTask void p_arg Do something with p_arg while 1 Task body Listing app c 3rd Part The task receives an argument when
81. task to become ready OSFlagPost Post flag s to an event flag group Table Event Flags API summary Event Flags Internals The application programmer can create an unlimited number of event flag groups limited only by available RAM Event flag services in uC OS III start with OSFlag and the services available to the application programmer are described in the topics below e OSFlagCreate Copyright 2015 Micrium Inc 269 uC OS III User s Manual e OSFlagDel e OSFlagPend e OSFlagPendAbort e OSFlagPendGetFlagsRdy e OSFlagPost Event flag services are enabled at compile time by setting the configuration constant OS_CFG_FLAG_EN to DEF_ENABLED in os_cfg h An event flag group is a kernel object as defined by the 0S_FLAG_GRP data type which is derived from the structure os_flag_grp see os h as shown in the listing below The services provided by uC OS III to manage event flags are implemented in the file os_flag c typedef struct os_flag_grp OS_FLAG_GRP 1 struct os_flag_grp OS_OBJ_TYPE Type 2 CPU_CHAR NamePtr 3 OS_PEND_LIST PendList 4 OS_FLAGS Flags 5 CPU_TS TS 6 J Listing OS_FLAG_GRP data type 1 In uC OS III all structures are given a data type In fact all data types start with os _ and are uppercase When an event flag group is declared you simply use OS_FLAG_GRP as the data type of the variable used to declare the event flag group 2 The structure start
82. thanks to my long time friend colleague and partner Christian Legare who has provided his advice and support throughout this project and on a day to day basis at Micrium Thank you also to the dozens of people who provided feedback about the uC OS III code as well as reviewers Finally I listen to music when I write software and artist Gino Vannelli s awesome music has provided a creative environment for me for over three decades I would be remiss if I did not acknowledge his contribution here as well Copyright 2015 Micrium Inc 12 uC OS III User s Manual Introduction Real time systems are systems whereby the correctness of the computed values and their timeliness are at the forefront There are two types of real time systems hard and soft real time What differentiates hard and soft real time systems is their tolerance to missing deadlines and the consequences associated with those misses Correctly computed values after a deadline has passed are often useless For hard real time systems missing deadlines is not an option In fact in many cases missing a deadline often results in catastrophe which may involve human lives For soft real time systems however missing deadlines is generally not as critical Real time applications cover a wide range but many real time systems are embedded An embedded system is a computer built into a system and not acknowledged by the user as being a computer Embedded systems are
83. the address of the desired event flag group The second argument specifies which bits the task will be waiting to be set assuming the task is triggered by set bits instead of cleared bits You also need to specify how long to wait for these bits to be set A timeout value of zero 0 indicates that the task will wait forever A non zero value indicates the number of ticks the task will wait until it is resumed if the desired bits are not set Specifying 0S_OPT_FLAG_SET_ANY indicates that the task will wake up if either of the two bits specified is set A timestamp is read and saved when the event flag group is posted to This timestamp can be used to determine the response time to the event OSFlagPend performs a number of checks on the arguments passed i e did you pass NULL pointers invalid options etc and returns an error code based on the outcome of the call assuming 0S_CFG_ARG_CHK_EN is set to DEF_ENABLED in os_cfg h If the call was successful err will be set to OS_ERR_NONE An ISR it can also be a task is setup to detect when the battery voltage of the product goes low assuming the product is battery operated The ISR signals the task letting the task perform whatever corrective action is needed The desired event flag group is specified in the post call as well as which flag the ISR is setting The third option specifies that the error condition will be flagged as a set bit 278 uC OS II
84. the appropriate task s This extra step is performed to reduce the amount of interrupt disable time that would otherwise be necessary to remove tasks from wait lists insert them in the ready list and perform other time consuming operations Lock Unlock Scheduler Disable Enable Interrupts ISR Handler Task Priority 0 Holding Queue OSFlagPost OSFlagPost OSQPost i OSQPost OSSemPost OSSemPost OSTaskQPost OSTaskQPost OSTaskSemPost i OSTaskSemPost NOT allowed to access ppC OS Ill s Allowed to access pC OS IIl s Ready List Pend Lists etc Ready List Pend Lists etc Figure ISR Handler Task OS_IntQTask is created by wC OS III and always runs at priority 0 i e the highest priority If OS_CFG_ISR_POST_DEFERRED_EN is Set to DEF_ENABLED no other task will be allowed to use priority 0 Copyright 2015 Micrium Inc 125 uC OS III User s Manual The Ready List Tasks that are ready to execute are placed in the Ready List The ready list consists of two parts a bitmap containing the priority levels that are ready and a table containing pointers to all the tasks ready In this section e Priority Levels e About the Ready List e Adding Tasks to the Ready List Copyright 2015 Micrium Inc 126 uC OS III User s Manual Priority Levels The figures below show the bitmap of priorities that are ready The width of the table depends on the data type CPU_D
85. the stack frame for the task The template file contains the following code void OSTaskCreateHook OS_TCB p_tcb if OS_CFG_APP_HOOKS_EN gt u if OS_AppTaskCreateHookPtr OS_APP_HOOK_TCB 0S_AppTaskCreateHookPtr p_tcb else void p_tcb Listing Typical OSTaskCreateHook OSTaskDelHook This function is called by OSTaskDe1 after the task to delete has been removed either from the ready list or a wait list The template file contains the following code Copyright 2015 Micrium Inc 351 uC OS III User s Manual void OSTaskDelHook OS_TCB p_tcb if OS_CFG_APP_HOOKS_EN gt u if OS_AppTaskDelHookPtr OS_APP_HOOK_TCB 0S_AppTaskDelHookPtr p_tcb else void p_tcb endif Listing Typical OSTaskDelHook OSTaskReturnHook This function is called by 0S_TaskReturn if the user accidentally returns from the task code The template file contains the following code void OSTaskReturnHook OS_TCB p_tcb if OS_CFG_APP_HOOKS_EN gt u if OS_AppTaskReturnHookPtr OS_APP_HOOK_TCB 0S_AppTaskReturnHookPtr p_tcb else void p_tcb Listing Typical OSTaskReturnHook OSTaskStklinit OSTaskStkInit is called by OSTaskCreate and is one of the most difficult port functions to create because it establishes the stack frame of every task created The template file contains the following code Copyright 2015 Micrium Inc 352 uC OS
86. the task level 91 uC OS III User s Manual As the state diagram indicates an interrupt can interrupt another interrupt This is called interrupt nesting and most processors allow this However interrupt nesting easily leads to stack overflow if not managed properly Internally uC OS III keeps track of task states using the state machine shown in the figure below The task state is actually maintained in a variable that is part of a data structure associated with each task the task s TCB The task state diagram was referenced throughout the design of uC OS II when implementing most of wC OS III s services The number in parentheses is the state number of the task and thus a task can be in any one of eight 8 states see os h OS _TASK_STATE_ Note that the diagram does not keep track of a dormant task as a dormant task is not known to uC OS III Also interrupts and interrupt nesting is tracked differently as will be explained further in the text This state diagram should be quite useful to understand how to use several functions and their impact on the state of tasks In fact P d highly recommend that the reader bookmark the page of the diagram Copyright 2015 Micrium Inc uC OS III User s Manual OSTaskSuspend Dela Delay y Suspended 1 5 OSTaskResume OSTimeDly Dly Expires or Dly Expires or OSTimeD1lyHMSM OSTimeDlyResume OSTaskDlyResume OSTaskSuspend
87. things get the figure below is an example of a task pending on two semaphores Copyright 2015 Micrium Inc 309 uC OS III User s Manual OS_SEM 4 Type OS_PEND_OBJ SS ae a Ctr OS_PEND_LIST OS_PEND_ DATA Nye 0 0 Fi 0 5 Os_SEM aoa T i OS_PEND_OBJ sS e nai ee a anme a 0 er i 9 PendDataTbiPtr PendDataTbiEntries 2 2 OS_TCB Figure Task pending on two semaphores 1 A pointer to the base address of the OS_PEND_DATA table is placed in the oS_TcB of the task placed in the pend list of the two semaphores 2 The number of entries in the 0S_PEND_DATA table is also placed in the os_TcB Again this Copyright 2015 Micrium Inc 310 uC OS III User s Manual 3 4 5 6 7 8 9 task is waiting on two semaphores and therefore there are two entries in the table The first semaphore is linked to the first entry in the OS_PEND_DATA array Entry 0 of the 0S_PEND_DATA table is linked to the semaphore object specified by that entry s PendObjPtr This pointer was specified by the caller of oSPendMulti Since there is only one task in the pend list of the semaphore the PrevPtr and NextPtr are pointing to NULL The second semaphore points to the second entry in the 0S_PEND_DATA table The second entry in the 0S_PEND_DATA array points to the second semaphore This pointer was specified by the caller of oSPendMulti The second semaphore only
88. timers may need to be taken care of prior to calling OSTimeTick instead of after as shown below void TickISR void OSTimeTick Clear tick interrupt source ai Reload the timer for the next interrupt t Listing Handle timer source after OSTimeTick or uC OS III may need to place literally hundreds of tasks if an application has that many tasks in the tick list The tick list is implemented such that it takes as little CPU time as possible to determine if time has expired for those tasks placed in the tick list and possibly makes those tasks ready to run In fact the tick management has been completely redesigned as of V3 04 00 and the tick list is actually split into two separate delta lists as shown in the figure below Copyright 2015 Micrium Inc 113 uC OS III User s Manual 1 OSTickListDly NbrUpdated 2 OSTickListTimeout NbrUpdated TCB_Ptr 0 6 OSTickCtr Figure Empty Tick Lists 1 This list contains all the tasks that are waiting for time to expire and thus contains all the os_TcBs for the tasks that have called OSTimeDly or OSTimeD1yHMSM 2 This list contains all the tasks that are pending on an object with a timeout i e they called 0S Pend and specified a non zero timeout value 3 The NbrEntries field in each list contains the current number of entries in the list and is thus updated each time an 0S_TCB is either inserted or removed
89. uC OS III CPU Specific portion A uC OS III port consists of writing or changing the contents of four kernel specific files Copyright 2015 Micrium Inc cpu_core c cpu_core h Software Firmware Hardware Interrupt Controller Figure C OS III architecture uC OS III User s Manual os_cpu h oS_cpu_a asm os_cpu_a inc and os _cpu_c c 2 A port also involves writing or changing the contents of two CPU specific files cpu h and cpu_a asm cpu_core c is generally generic and should not require modifications 3 A Board Support Package BSP is generally necessary to interface wC OS III to a timer which is used for the clock tick and an interrupt controller 4 Some semiconductor manufacturers provide source and header files to access on chip peripherals These are contained in CPU MCU specific files You generally don t need to modify any of these and thus you can use them as is Porting wC OS II is quite straightforward once the subtleties of the target processor and the C compiler assembler are understood Depending on the processor a port consists of writing or changing between 100 and 400 lines of code which takes a few hours to a few days to accomplish The easiest thing to do however is to modify an existing port from a processor that is similar to the one intended for use A uC OS III port looks very much like a wC OS II port Since uC OS II was ported to well over 45 different CPU architectures
90. uC OS III is software that is added to an application it requires extra ROM code space and RAM data space Low end single chip microcontrollers are generally not able to run a real time kernel such as uC OS III since they have access to very little RAM uC OS III requires between 1 Kbyte and Copyright 2015 Micrium Inc uC OS III User s Manual 4 Kbytes of RAM plus each task requires its own stack space It is possible for wC OS III to work on processors having as little as 4 Kbytes of RAM Finally uC OS II allows for better use of the CPU by providing approximately 70 indispensable services After designing a system using a real time kernel such as wC OS IIL you will not return to designing a foreground background system Copyright 2015 Micrium Inc uC OS III User s Manual RTOS Real Time Operating System A Real Time Operating System generally contains a real time kernel and other higher level services such as file management protocol stacks a Graphical User Interface GUI and other components Most additional services revolve around I O devices Micrium offers a complete suite of RTOS components including uC FS an Embedded File System wC TCP IP a TCP IP stack uC GUI a Graphical User Interface two USB stacks uC USB Device and uC USB Host and more Most of these components are designed to work standalone users can pick and choose only the components required for the application Contact Micrium www micri
91. void main void 1 OS ERR err OSInit amp err 2 if err OS_ERR_NONE Something wasn t configured properly wC OS III not properly initialized Serr will tell you the cause see os h f 3 Create ONE task we 1l call it AppTaskStart for sake of discussion S OSStart amp err 4 void AppTaskStart void p_arg OS ERR err 5 Initialize the tick interrupt oi if OS_CFG_STAT_TASK_EN DEF_ENABLED OSStatTaskCPUUsageInit amp err 6 OsStatReset amp err 7 endif 8 Create other tasks ry while DEF_ON AppTaskStart body yf 1 2 3 Copyright 2015 Micrium Inc Listing Proper startup for computing CPU utilization The C compiler should start up the CPU and bring it to main as is typical in most C applications main calls OSInit to initialize wC OS III It is assumed that the statistics task was enabled by setting 0S_CFG_STAT_TASK_EN to DEF_ENABLED in os_cfg h You should always examine tC OS III s returned error code to make sure the call was done properly Refer to os h for a list of possible errors OS_ERR_ As the comment indicates you should create a single task called AppTaskStart in the example its name is left to the creator s discretion When creating this task give it a fairly high priority do not use priority 0 since it s reserved for wC OS HI Normally uC OS III allows the user to create as many tasks a
92. was absurd to me The software provider thought otherwise and I forked over the maintenance fee Incredibly the vendor took six months to actually remove the bug All told I completed my ignition system incorporating the second operating system a year after receiving the software Clearly I needed a better solution Twice disappointed I began to develop my own kernel In my naive opinion all a kernel really did was to save and restore CPU registers writing one should not be especially challenging The project kept me busy at night and on weekends and proved to be much more difficult than anticipated Approximately a year after I starting the project my first operating system was complete With a new kernel in hand there was finally a handy means of developing multitasking applications The operating system consisted of little more than a single C file and allowed up to 64 tasks to be created in a single application Each task was required to be have a unique priority The highest priority task that was ready to run when the operating system s scheduler was invoked was given control of the CPU uC OS was preemptive so scheduling could occur at practically any time Efficient task scheduling was actually one of many services offered by uC OS The operating system also facilitated inter task communication via message queues and mailboxes and task Copyright 2015 Micrium Inc uC OS III User s Manual synchronization
93. which is used to queue up deferred posts The value of this variable is zero if OS_CFG_ISR_POST_DEFERRED_EN is DEF_DISABLED inos_cfg h ROM Variable Data Type Value OSDbg_ISRPostDeferredEn CPU_INT 8U OS_CFG_ISR_POST_DEFERRED_EN When 1 this variable indicates that an ISR will defer posts to task level code This value is set in os_cfg h ROM Variable Data Type Value OSDbg_MemEn CPU_INT 8U OS_CFG_MEM_EN When 1 this variable indicates that wC OS III s memory management services are available to the application This value is set in os_cfg h Copyright 2015 Micrium Inc 401 uC OS III User s Manual ROM Variable Data Type Value OSDbg_MemSize CPU_INT16U sizeof OS_MEM This variable indicates the RAM footprint in bytes of a memory partition control block OS_MEM ROM Variable Data Type Value OSDbg_MsgEn CPU_INT 8U OS_MSG_EN When 1 this variable indicates that the application either enabled message queues or task message queues or both This value is set in os_cfg h by ORing the value of 0S_CFG_Q_EN and OS_CFG_TASK_Q EN ROM Variable Data Type Value OSDbg_ MsgSize CPU_INT16U sizeof OS_MSG This variable indicates the RAM footprint in bytes of an os_MsG data structure ROM Variable Data Type Value OSDbg_ MsgPoolSize CPU_INT16U sizeof OS_MSG_POOL This variable indicates the RAM footprint in bytes of an OS_MSG_POOL data structure ROM Variable Data Type Value OSDbg MsgQSize CPU_INT16U sizeof OS_MSG _Q
94. with Multiple Interrupt Priorities 0 0 0 eee eee eee eee 162 1 10 5 All Interrupts Vector toa Common Location 0 0 cece cece 165 1 10 6 Every Interrupt Vectors to a Unique Location 0 0 0 c cece cece eee nee 167 1 10 7 Direct and Deferred Post Methods 0 0 eee cc ee eens 168 1 10 8 Direct vs Deferred Post Method 0 eee ccc cee teen n nee 174 1 109 Whe Clock Tick siii ais eevee aus deahined wae a ay dsb ed de Ged be doe yah Pade seg aSa 176 1 11 Pend Tist x aetna e ohare es bDet ws oh ode Me oe ee deen es dee te adivew E aa eee ed 179 1 12 Time Management 2 2 nese ers bee ce bee es Sea ee bee Cee a Eaa eee 185 1 13 Timer Management ii toc ceh dag Bad Sesto Soe ieee d Meek hed baw dee a ei ea aala ea 194 1 13 1 Timer Management Internals 0 0 e ene nee 198 1 14 Resource Management 0 eee ccc Ee EE e E a eben ene nee 207 1 14 1 Disable Enable Interrupts 0 0 0 ee ccc tenet eens 210 FIA Lock Unl0ck s t004 452 24 4 beget laine oO eae Pe ee a eae ee 212 1 14 3 Semaphores in uC OS IIT 2 cece cece ene n ence 213 1 14 31 Binary Semaphores secl sisted i se ce eee bad aele tate ake e apg geile 215 1 14 3 2 Counting Semaphores 0 0 eee eect cent E nes 222 1 14 33 Not s on Semaphores 3 3 2 oieeca keh eae eke aad we WE He ee Aaa 224 1 14 34 Semaphore Internals 2 3 c sgccnat as aed ae ak ob de ee eh od eee eee 225 1 14 35 Priority Inversions sorore t
95. zero 0 means that the task will wait forever for the task semaphore 2 The second argument specifies how to pend There are two options OS_OPT_PEND_BLOCKING and 0S_OPT_PEND_NON_BLOCKING The blocking option means that if the task semaphore has not been signaled or posted to the task will wait until the semaphore is signaled the pend is aborted by another task or until the timeout expires Copyright 2015 Micrium Inc 263 uC OS III User s Manual 3 4 When the semaphore is signaled uwC OS III reads a timestamp and places it in the receiving task s OS_TCB When OSTaskSemPend returns the value of the timestamp is placed in the local variable ts This feature captures when the signal actually happened You can call 0S_TS_GET to read the current timestamp and compute the difference This establishes how long it took for the task to receive the signal from the posting task or ISR OSTaskSemPend returns an error code based on the outcome of the call If the call was successful err will contain OS_ERR_NONE If not the error code will indicate the reason of the error see uC OS III API Reference for a list of possible error code for OSTaskSemPend Posting i e Signaling a Task Semaphore An ISR or a task signals a task by calling OSTaskSemPost as shown in the listing below OS_TCB MyTaskTCB void MyISR void p_arg 1 2 Copyright 2015 Micrium Inc OS_ERR err OSTa
96. 2015 Micrium Inc When should you use When access to shared resource is very quick reading from or writing to few variables and access is faster than uC OS III s interrupt disable time It is highly recommended to not use this method as it impacts interrupt latency When access time to the shared resource is longer than uC OS III s interrupt disable time but shorter than uC OS III s scheduler lock time Locking the scheduler has the same effect as making the task that locks the scheduler the highest priority task It is recommended not to use this method since it defeats the purpose of using uC OS III However it is a better method than disabling interrupts as it does not impact interrupt latency When all tasks that need to access a shared resource do not have deadlines This is because semaphores may cause unbounded priority inversions described later However semaphore services are slightly faster in execution time than mutual exclusion semaphores This is the preferred method for accessing shared resources especially if the tasks that need to access a shared resource have deadlines yC OS III s mutual exclusion semaphores have a built in priority inheritance mechanism which avoids unbounded priority inversions However mutual exclusion semaphore services are slightly slower in execution time than semaphores since the priority of the owner may need to be changed which requires CPU processing Table
97. 2C port Copyright 2015 Micrium Inc 221 uC OS III User s Manual Counting Semaphores A counting semaphore is used when elements of a resource can be used by more than one task at the same time For example a counting semaphore is used in the management of a buffer pool as shown in the figure below Let s assume that the buffer pool initially contains 10 buffers A task obtains a buffer from the buffer manager by calling BufReq When the buffer is no longer needed the task returns the buffer to the buffer manager by calling BufRel The pseudo code for these functions is shown in the listing that follows the figure below The buffer manager satisfies the first 10 buffer requests because the semaphore is initialized to 10 When all buffers are used a task requesting a buffer is suspended until a buffer becomes available You use uC OS III s 0SMemGet and OSMemPut see Memory Management API Changes to obtain a buffer from the buffer pool When a task is finished with the buffer it acquired the task calls BufRel to return the buffer to the buffer manager and the buffer is inserted into the linked list before the semaphore is signaled By encapsulating the interface to the buffer manager in BufReq and BufRe1 the caller does not need to be concerned with actual implementation details 3 of of BufFreeListPtr p NextPtr NextPtr NextPtr 0 Figure Using a counting semaphore Copyright 2015 Micrium
98. 3 4 5 6 Copyright 2015 Micrium Inc Instead of allocating static storage for the memory partition control block you can assign a pointer that receives the 0S_MEM allocated using malloc The application allocates storage for the memory control block We then allocate storage for the memory partition A pointer is passed to the allocated memory control block to OSMemCreate The base address of the storage used for the partition is passed to OSMemCreate Finally the number of blocks and the size of each block is passed so that wC OS HI can create the linked list of 12 blocks of 100 bytes each Again hard coded numbers are used but these would typically be replaced by defines 319 uC OS III User s Manual Getting a Memory Block from a Partition Application code can request a memory block from a partition by calling OSMemGet as shown in the listing below The code assumes that the partition was already created OS_MEM MyPartition 1 CPU_INT 8U MyDataBlkPtr void MyTask void p_arg OS_ERR err while DEF_ON MyDataBlkPtr CPU_INT 8U OSMemGet OS_MEM amp MyPartition OS_ERR amp err if err OS_ERR_NONE You have a memory block from the partition i Listing Obtaining a memory block from a partition 2 3 1 The memory partition control block must be accessible by all tasks or ISRs that will be using the partition 2 Simply call osMemGet to o
99. 5 1 2 3 4 5 Copyright 2015 Micrium Inc OSTCBCurPtr gt StkPtr SP Clear tick interrupt 6 OSTimeTick 7 OSIntExit 8 OS_CTX_RESTORE 9 Return from Interrupt Exception 10 Listing BSP_OS_TickISRQ Pseudo Code BSP_OS_TickISR is generally invoked automatically by the interrupt controller when the tick interrupt occurs Assuming again our generic 32 bit CPU it s assumed here that the SR and PC of the interrupted task are pushed automatically onto the stack of the interrupted task Again OS_CTX_SAVE saves the CPU context onto the current task s stack For our generic 32 bit CPU 0S_CTX_SAVE would push Re through R13 onto the stack in that order Interrupts should be disabled here On some processors interrupts are automatically disabled when the processor accepts the interrupt Some processors support multiple interrupt levels In fact some interrupts are allowed to make kernel calls while others are not Typically interrupts that do not make kernel calls called Non Kernel Aware Interrupts would generally be high priority interrupts and kernel aware interrupts would all be grouped in priority below these For example if a processor has 16 different interrupt levels and level is the lowest priority interrupt then all kernel aware interrupts would be assigned from 0 to some number N let s say 12 and N 1 to 15 would be assigned to be non kernel aware interrupts BSP_OS_
100. 5 peer LOOT ees Priorities OSPrioTh OS_PRIO_TBL_SIZE 1 to OS_CFG_PRIO_MAX 1 15 0 Figure CPU_DATA declared as a CPU_INT16U Highest Priority Task Vt A _ _________ gt 042 3 45 6 7 RQ 41M 14142 13 1415 1617 1R 192M 24 222324 25 26 272A 2930 31 TOIRE COT eee sig laine COT TT esata ek oe COT TT sca Priorities OS_CFG PRIO MAX 32 OSPrioTb OS_PRIO_TBL_SIZE 1 to OS CFG PRIO_MAX 1 31 0 Figure CPU_DATA declared as a CPU_INT32U os_prio c contains the code to set clear and search the bitmap table These functions are internal to uC OS III and are placed in os_prio c to allow them to be optimized in assembly language by replacing os_prio c with an assembly language equivalent os_prio asm if necessary Copyright 2015 Micrium Inc 128 uC OS III User s Manual Function Description OS_PrioGetHighest Find the highest priority level OS_PrioInsert Set bit corresponding to priority level in the bitmap table OS_PrioRemove Clear bit corresponding to priority level in the bitmap table Table Priority Level access functions To determine the highest priority level that contains ready to run tasks the bitmap table is scanned until the first bit set in the lowest bit position is found using O0S_PrioGetHighest The code for this function is shown in the listing below OS_PRIO OS _PrioGetHighest void CPU_DATA p_tbl OS_PRIO prio prio OS_PRIO p_tbl amp 0SPrioTb1 wh
101. 94 1 16 38 Cli nts and Servers 32 2 24 cs5tsan halts s cashed E POE E E AEE ME EOE e dete Batis 302 1 16 9 Message Queues Internals 1 1 cece eect nent n nee 303 1 17 Pending on Multiple Objects eimen i a E E cece cence ence nee 306 1 18 Memory Management 2 05 3 cage See eneee eee aie bane ea sh ea teed dare eee E 314 1 18 1 Creating a Memory Partition 0 ee cece cece nen n nee 316 1 18 2 Getting a Memory Block from a Partition 0 0 cece eect ee nee 320 1 18 3 Returning a Memory Block toa Partition 0 0 eee ee eee eee 321 1 18 4 Using Memory Partitions 2 0 cece eect n ene nee 322 1 19 Porting uC OS UT ereot i prde pii bee ea SE SR DPS Cee ee oa D i 326 LA92T CONnVentiONS 4 sts snes to wit AM Arig dash Saw he nade eka baa ted kewl erated eye 331 1 192 0CCPU misias kr epini nep er eu we aeN AEM eas Pu eae eile neal ha Hake a at ee 332 1 19 3 UE OS MEP Ort lt eere a a Gee ee EE Le ete deg dead eee 341 1 19 4 Board Support Package 0 cece eee eee eee cnet e eee een eee 366 119S Pesting a Port ait cioten ohare dha ee beta ee Siow ee Seta as Perera eee R 368 1 20 Run Time Statistics oie cedeo Epia ccc ccc cece bene nen eben ene nes 383 1 20 1 General Statistics Run Time 2 0 cece eee ene n nee 384 1 20 2 Per Task Statistics Run Time 0 0 ccc cece cece ene n ene nee 390 1 20 3 Kernel Object Run Time 0 0 eee eee ee rererere 395 T20 4 08 dD8 6 Statue neri dies peas souls Gated each ded boda
102. ABLED in os_cfg h oSStatTaskCtrMax This variable contains the maximum number of times the idle task loop runs in 0 1 second This value is used to measure the CPU usage of the application This variable is declared only if 0S_CFG_STAT_TASK_EN is set to DEF_ENABLED in os_cfg h OSStatTaskTimeMax This variable contains the maximum execution time of the statistic task in CPU_TS units Copyright 2015 Micrium Inc 387 uC OS III User s Manual It is declared only if OS_CFG_STAT_TASK_EN is set to DEF_ENABLED in os_cfg h The total time also includes the time of any ISR that occurred while the statistic task was running Tick Task OSTickCtr This variable is incremented every time the tick task executes OSTickTaskTimeMax This variable contains the maximum execution time of the tick task in CPU_TS units The total time also includes the time of any ISR that occurred while the tick task was running OSTickListDly NbrEntries This variable indicates the number of tasks currently in the list of task that are waiting for time to expire This number is updated whenever tasks are inserted or removed from that list This field is only available when 0S_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h OSTickListDly NbrUpdated This variable indicates the number of 0S_TCcBs in the list of tasks waiting for time to expire that were last updated by 0S_TickTask In other words if 0S_TickTask only updated the TickRemain of one 0S_TCB the
103. ATA see cpu h which can either be 8 16 or 32 bits The width depends on the processor used uC OS III allows up to 0S_CFG_PRIO_MAX different priority levels see os_cfg h In yC OS IMI a low priority number corresponds to a high priority level Priority level zero 0 is thus the highest priority level Priority 0S_CFG_PRIO_MAX 1 is the lowest priority level uC OS III uniquely assigns the lowest priority to the idle task and thus no other tasks are allowed at this priority level If there are tasks that are ready to run at a given a priority level then its corresponding bit is set i e 1 in the bitmap table Notice in the figures below that priority levels are numbered from left to right and the priority level increases moves toward lower priority with an increase in table index The order was chosen to be able to use a special instruction called Count Leading Zeros CLZ which is found on many modern processors This instruction greatly accelerates the process of determining the highest priority level Highest Priority Task 8 bits 0123458472 OSPrioTb 0 Priorities 0 to 7 osPricTot2 TL Priorities 16 to 23 Priorities OS_CFG_PRIO_MAX 8 OSPrioTbh OS_PRIO_TBL_SIZE 1 to OS_CFG_PRIO_MAX 1 7 0 Lowest Priority Task Figure CPU_DATA declared as a CPU_INT08U Copyright 2015 Micrium Inc 127 uC OS III User s Manual A 16 bits e gt 0123 456 7 8A MARAA OSPrioTb 0 Priorities 0 to 1
104. CAL_ENTER saves the current state of the CPU interrupt disable flag s in the local variable allocated by CPU_SR_ALLOC and disables all maskable interrupts 3 The critical section of code is then accessed without fear of being changed by either an Copyright 2015 Micrium Inc 210 uC OS III User s Manual ISR or another task because interrupts are disabled In other words this operation is now atomic 4 CPU_CRITICAL_EXIT restores the previously saved interrupt disable status of the CPU from the local variable CPU_CRITICAL_ENTER and CPU_CRITICAL_EXIT are always used in pairs Interrupts should be disabled for as short a time as possible as disabling interrupts impacts the response of the system to interrupts This is known as interrupt latency Disabling and enabling is used only when changing or copying a few variables Note that this is the only way that a task can share variables or data structures with an ISR uC CPU provides a way to actually measure interrupt latency When using uC OS III interrupts may be disabled for as much time as uC OS III does without affecting interrupt latency Obviously it is important to know how long pC OS II disables interrupts which depends on the CPU used Although this method works you should avoid disabling interrupts as it affects the responsiveness of the system to real time events Copyright 2015 Micrium Inc uC OS III User s Manual Lock Unlock If the task does no
105. CK_PTR p_callback Fnct to call at y void p_callback_arg Arg to callback i OS_ERR p err Once created a timer can be started or restarted and stopped as often as is necessary Timers can be created to operate in one of three modes One shot Periodic no initial delay and Periodic with initial delay One Shot Timers As its name implies a one shot timer will countdown from its initial value call the callback function when it reaches zero and stop The figure below shows a timing diagram of this operation The countdown is initiated by calling osTmrstart At the completion of the time delay the callback function is called assuming a callback function was provided when the timer was created Once completed the timer does not do anything unless restarted by calling OSTmrStart at which point the process starts over You terminate the countdown process of a timer before it reaches zero by calling OSTmrStop In this case you can specify that the callback function be called or not Copyright 2015 Micrium Inc 195 uC OS III User s Manual OSTmrCreate OSTmrStart A dly Ticks ticks Time Callback Called Figure One Shot Timers dly gt 0 period 0 As shown in the figure below a one shot timer can be retriggered by calling OSTmrStart before the timer reaches zero This feature can be used to implement watchdogs and similar safeguards OSTmrStart OSTmrCreate oa A dly
106. Context Switching The unit of measure for the measured time is in CPU_TS timestamp units It is necessary to find out the resolution of the timer used to measure these timestamps For example if the timer used for the timestamp is incremented at 1 MHz then the resolution of CPU_TS is 1 microsecond Measuring the interrupt disable time obviously adds measurement artifacts and thus increases the amount of time the interrupts are disabled However as far as the measurement is concerned measurement overhead is accounted for and the measured value represents the actual interrupt disable time as if the measurement was not present Interrupt disable time is obviously greatly affected by the speed at which the processor accesses instructions and thus the memory access speed In this case the hardware designer might have introduced wait states to memory accesses which affects overall performance of the system This may show up as unusually long interrupt disable times Copyright 2015 Micrium Inc uC OS III User s Manual Locking the Scheduler When setting OS_CFG_ISR_POST_DEFERRED_EN to DEF_ENABLED wC OS III locks the scheduler before entering a critical section and unlocks the scheduler when leaving the critical section OS_CRITICAL_ENTER simply increments OSSchedLockNestingCtr to lock the scheduler This is the variable the scheduler uses to determine whether or not the scheduler is locked It is locked when the value is non z
107. DEL OS_STATUS_PEND_ TIMEOUT TaskState This field indicates the current state of a task and contains one of the eight 8 task states that a task can be in These states are declared in os h OS_TASK_STATE_RDY OS_TASK_STATE_DLY OS_TASK_STATE_PEND OS_TASK_STATE_PEND_ TIMEOUT OS_TASK_STATE_SUSPENDED OS_TASK_STATE_DLY_SUSPENDED Copyright 2015 Micrium Inc 100 uC OS III User s Manual OS_TASK_STATE_PEND_SUSPENDED OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED Prio This field contains the current priority of a task Prio is a value between 0 and OS_CFG_PRIO_MAX 1 In fact the idle task is the only task at priority OS_CFG_PRIO_MAX 1 BasePrio This field contains the base priority of a task BasePrio is a value between 0 and OS_CFG_PRIO_MAX 1 This field is used to correctly propagate mutex owner priorities to prevent priority inversion MutexGrpHeadPtr This field is a pointer to a list of mutexes that this task owns StkSize This field contains the size in number of CPU_STK elements of the stack associated with the task Recall that a task stack is declared as follows CPU_STK MyTaskStk StkSize is the number of elements in the above array Opt This field saves the options passed to OSTaskCreate when the task is created as shown below Note that task options are additive OS_OPT_TASK_NONE OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR OS_OPT_TASK_SAVE_FP PendDataTblEntries Copyright 2015 Micrium Inc 101
108. EEE EEEE EEEE E EEEE E E E E E E E E E E E E E E E k k k k k k k k k k k kk k k k kkk ef include lt app_cfg h gt 1 include lt bsp h gt include lt os h gt ies EEEE EEEE EEEE EE EEEE EEEE EEEE ree errr ce EEEE EEEE EEEE EEEE E E E E E E E EE E E E E E E E k k K k k k k k k kk k k k kkk i LOCAL GLOBAL VARIABLES FKK KK K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K A static OS_TCB AppTaskStartTCB 2 static CPU_STK AppTaskStartStk APP_TASK_START_STK_SIZE 3 ie PTI tt tere eC EEEE EEEE EEE EEEE EEEE EEEE EEEE EEEE EEEE EEE EE EEEE E EEEE E E E EEE E E E E E E E E E E E k k k k k k k k k k kkk z FUNCTION PROTOTYPES EE EEEE EEEE EEEE EEEE EEEE EEE EEEE EEEE EEE EEE EEEE EE EEEE E EEEE E E E EE E E E E E E E E E E K E k k k k k k k k k kk kk A static void AppTaskStart void p_arg 4 Listing app c 1st Part 1 As with any C programs you need to include the necessary headers to build the application app_cfg h is a header file that configures the application For our example app_cfg h contains define constants to establish task priorities stack sizes and other application specifics bsp h is the header file for the Board Support Package BSP which defines macros defines and function prototypes such as BSP_Init BSP_LED_On OS_TS_GET and more The actual BSP might c
109. Figure Hiding a semaphore from a task The function CommSendCmd is called with three arguments the ASCII string containing the command a pointer to the response string from the device and finally a timeout in case the device does not respond within a certain amount of time The pseudo code for this function is shown in the listing below Copyright 2015 Micrium Inc 220 uC OS III User s Manual APP_ERR CommSendCmd CPU_CHAR cmd CPU_CHAR response OS_TICK timeout Acquire serial port s semaphore Send cmd to device Wait for response with timeout if timed out Release serial port s semaphore return error code else Release serial port s semaphore return no error Listing Encapsulating the use of a semaphore Each task that needs to send a command to the device must call this function The semaphore is assumed to be initialized to 1 i e available by the communication driver initialization routine The first task that calls CommSendcmd acquires the semaphore proceeds to send the command and waits for a response If another task attempts to send a command while the port is busy this second task is suspended until the semaphore is released The second task appears simply to have made a call to a normal function that will not return until the function performs its duty When the semaphore is released by the first task the second task acquires the semaphore and is allowed to use the RS 23
110. Get Value of the Tick Counter uC OS III increments a tick counter every time a tick interrupt occurs This counter allows the application to make coarse time measurements and have some notion of time after power up OSTimeGet allows the user to take a snapshot of the tick counter You can use this value to delay a task for a specific number of ticks and repeat this periodically without losing track of time OSTimeSet allows the user to change the current value of the tick counter Although uC OS III allows for this it is recommended to use this function with great care especially if you use match time delays Copyright 2015 Micrium Inc uC OS III User s Manual OSTimeSet and OSTimeGet uC OS III increments a tick counter every time a tick interrupt occurs This counter allows the application to make coarse time measurements and have some notion of time after power up OSTimeGet allows the user to take a snapshot of the tick counter You can use this value to delay a task for a specific number of ticks and repeat this periodically without losing track of time OSTimeSet allows the user to change the current value of the tick counter Although uC OS III allows for this it is recommended to use this function with great care especially if you use match time delays OSTimeTick Signal a Clock Tick The tick Interrupt Service Routine ISR must call this function every time a tick interrupt
111. I User s Manual Again the function sets err based on the outcome of the call Event flags are generally used for two purposes status and transient events Typically you would use different event flag groups to handle each of these as shown in the figure below Tasks or ISRs can report status information such as a temperature that has exceeded a certain value that RPM is zero on an engine or motor or there is fuel in the tank and more This status information cannot be consumed by the tasks waiting for these events because the status is managed by other tasks or ISRs Event flags associated with status information are monitored by other task by using non blocking wait calls Tasks will report transient events such as a switch was pressed an object was detected by a motion sensor an explosion occurred etc The task that responds to these events will typically block waiting for any of those events to occur and consume the event Copyright 2015 Micrium Inc 279 uC OS III User s Manual Copyright 2015 Micrium Inc Explosion Explosion Abort Status OS_FLAG GRP RPM 0 gt RPM gt 0 gt AirTemp gt 120 AlrPres gt 30 _ FuelLevel gt 30 Transient Events OS_FLAG_GRP OSFlagPendi Display NON_BLOCKING Task OSFlagPend NON_BLOCKING OSFlagPend BLOCKING CONSUM Timeout OSFlagPend BLOCKING CONSUM Timeout Data Logging Task O Abort
112. I and the application code must never call them The code is found in os_core c Copyright 2015 Micrium Inc 183 uC OS III User s Manual Function Description OS_PendListChangePrio Change the priority of a task in a pend list OS_PendListInit Initialize a pend list OS_PendListInsertHead Insert an OS_PEND_DATA at the head of the pend list OS_PendListInsertPrio Insert an OS_PEND_DATA in priority order in the pend list OS_PendListRemove Remove multiple OS_PEND_DATA from the pend list OS_PendListRemove1 Remove single OS_PEND_DATA from the pend list Table Pend List access functions Copyright 2015 Micrium Inc 184 uC OS III User s Manual Time Management uC OS III provides time related services to the application programmer In the section Interrupt Management it was established that uC OS III generally requires as do most kernels that the user provide a periodic interrupt to keep track of time delays and timeouts This periodic time source is called a clock tick and should occur between 10 and 1000 times per second or Hertz see 0S_CFG_TICK_RATE_HZ in os_cfg_app h The actual frequency of the clock tick depends on the desired tick resolution of the application However the higher the frequency of the ticker the higher the overhead uC OS III provides a number of services to manage time as summarized in the table below and the code is found in os_time c Function Name Operation OSTimeDly Delay execution o
113. II will run the most important ready to run task highest priority With uwC OS HI a low priority number indicates a high priority In other words a task at priority 1 is more important than a task at priority 10 uC OS III supports a compile time user configurable number of different priorities see OS_PRIO_MAX in os_cfg h Thus uC OS III allows the user to determine the number of different priority levels the application is allowed to use Also uC OS III supports an unlimited number of tasks at the same priority For example uC OS III can be configured to have 64 different priority levels and one can assign dozens of tasks at each priority level See Assigning Task Priorities 77 uC OS III User s Manual 3 4 Copyright 2015 Micrium Inc A task has its own set of CPU registers As far as a task is concerned the task thinks it actually has the CPU all to itself Because uC OS III is a preemptive kernel each task must have its own stack area The stack always resides in RAM and is used to keep track of local variables function calls and possibly ISR Interrupt Service Routine nesting Stack space can be allocated either statically at compile time or dynamically at run time A static stack declaration is shown below This declaration is made outside of a function static CPU_STK MyTaskStk or CPU_STK MyTaskStk Note that indicates that the size of the stack and thus the array d
114. III global variables These variables are for uwC OS III to manage and should not be accessed by application code os h contains the main uC OS III header file which declares constants macros uC OS III global variables for use by uC OS III only function prototypes and more os_type h contains declarations of wC OS III data types that can be changed by the port designer to make better use of the CPU architecture In this case the file would typically be copied to the port directory and then modified See Appendix B uC OS III Configuration Manual TLS lt tool gt The directory containing the compiler interface functions that allow library functions to be thread safe If this feature is not required then you can omit the files in this directory Copyright 2015 Micrium Inc os_tls c provides the compiler specific thread safe interface functions 41 uC OS III User s Manual uC OS lll CPU Specific Source Code The uC OS III port developer provides these files See also Porting uC OS III Micrium Software uCOS III Ports lt architecture gt lt compiler gt os_cpu h os_cpu_a asm os_cpu_c c Micrium Contains all software components and projects provided by Micrium Software This sub directory contains all software components and projects uCOS III The main uC OS III directory Ports The location of port files for the CPU architecture s to be used lt architecture gt This is the name
115. III to manage semaphores are implemented in the file os_sem c Semaphore services are enabled at compile time by setting the configuration constant OS_CFG_SEM EN to 1 inos_cfg h typedef struct os_sem OS_SEM 1 1 2 3 4 Copyright 2015 Micrium Inc struct os_sem OS_OBJ_TYPE Type 2 CPU_CHAR NamePtr 3 OS_PEND_LIST PendList 4 OS_SEM_CTR Ctr 5 CPU_TS TS 6 I3 Listing OS_SEM data type In uC OS III all structures are given a data type All data types start with os_ and are uppercase When a semaphore is declared you simply use 0S_SEM as the data type of the variable used to declare the semaphore The structure starts with a Type field which allows it to be recognized by uwC OS III as a semaphore Other kernel objects will also have a Type as the first member of the structure If a function is passed a kernel object uC OS III will confirm that it is being passed the proper data type assuming OS_CFG_OBJ_TYPE_CHK_EN is set to 1 in os_cfg h For example if you pass a message queue 0S_Q to a semaphore service for example osSemPend uC OS II will recognize that an invalid object was passed and return an error code accordingly Each kernel object can be given a name for easier recognition by debuggers or uC Probe This member is simply a pointer to an ASCII string which is assumed to be NUL terminated Since it is possible for multiple tasks to wait or pend on a
116. IntQTask if you selected the Deferred Post Method of posting described in Chapter 8 The pseudo code for the round robin scheduler is shown in Listing 7 3 Copyright 2015 Micrium Inc 144 uC OS III User s Manual void OS_SchedRoundRobin void 1 2 3 4 5 6 Copyright 2015 Micrium Inc if OSSchedRoundRobinEn TRUE 1 return if Time quanta counter gt 2 Decrement time quanta counter if Time quanta counter gt return if Number of OS_TCB at current priority level lt 2 3 return if OSSchedLockNestingCtr gt 4 return Move OS_TCB from head of list to tail of list 5 Reload time quanta for current task 6 Listing OS_SchedRoundRobin pseudocode OS_SchedRoundRobin starts by making sure that round robin scheduling is enabled Recall that to enable round robin scheduling your code must call OSSchedRoundRobinCfg The time quanta counter which resides inside the os_TcB of the running task is decremented If the value is still non zero then OS_SchedRoundRobin returns Once the time quanta counter reaches zero OS_SchedRoundRobin checks to see that there are other ready to run tasks at the current priority If there are none the function returns Round robin scheduling only applies when there are multiple tasks at the same priority and the task doesn t completes its work within its time quanta OS_SchedRoundRob
117. K K K K K K K K K K K K K K K K K K K K K K K K K K K K K Uf include lt app_cfg h gt include lt bsp h gt include lt os h gt 2k KKK KK KK OR OR KOK OK KO OK RK OK KOK KK kK a KK aK OK Kk ok a kk 2k 2 KK kK kk 2 2 KK ok ok 2k KK kk 2k 2 KK a kk 2k 2 a aK aK aK Kk 4 LOCAL GLOBAL VARIABLES 2k KK KK KK OR OK OK OK OK KOR KR RK KOK Kk OK KK ORK kK kk 2 a KK kK kk 2 2 a KK ok ok 2 a KK kk 2k 2 KK aK kk 2k 2 aK aK aK aK ok Uf static OS_TCB AppTaskStartTCB 1 static OS_TCB AppTask1_TCB static OS_TCB AppTask2_TCB static OS_MUTEX AppMutex 2 static OS_Q AppQ 3 static CPU_STK AppTaskStartStk APP_TASK_START_STK_SIZE 4 static CPU_STK AppTask1_Stk 128 static CPU_STK AppTask2_Stk 128 es FR KK K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K FUNCTION PROTOTYPES KK KK K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K S static void AppTaskStart void p_arg 5 static void AppTask1 void p_arg static void AppTask2 void p_arg Listing app c 1st Part 1 Here we allocate storage for the OS_TCBs of each task 2 A mutual exclusion semaphore a k a a mutex is a kernel object a data structure that is used to protect a shared resource fro
118. KPOINT here OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr OS_CTX_RESTORE Return from Interrupt Exception BSP_OS_TickISR lt Set BREAKPOINT here OS_ISR_ENTER Clear tick interrupt OSTimeTick OS_ISR_EXIT STEP 1 Reset the CPU and run the code until you hit the first breakpoint If you properly initialized the tick timer then you should be looking at the BSP_OS_TickISR code If not you need to determine why you are not getting the tick interrupt If the tick interrupt is properly setup then you should verify that is pointing at OSIdleTaskTCB since your application should have been looping around the idle task until the tick interrupt occurred Copyright 2015 Micrium Inc 379 uC OS III User s Manual STEP 2 You should step into the BSP_OS_TickISR code and verify that OS_ISR_ENTER increments OSIntNestingCtr you should be able to look at that variable with the debugger and notice that it should have a value of 1 Also you should verify that the current SP is saved in OSTCBCurPtr gt StkPtr it should be the same as OSIdleTaskTCB StkPtr STEP 3 You should now step through the code that clears the tick interrupt and verify that it s doing the proper thing STEP 4 You can now Step Over the call to OSTimeTick OSTimeTick basically signals the tick task and thus makes it ready to run Instead of returning from interrupt from BSP_OS_TickISR
119. Listing AppTaskStart As previously mentioned a task looks like any other C function The argument p_arg is passed to AppTaskStart by OSTaskCreate as discussed in the previous listing description BSP_Init is a Board Support Package BSP function that is responsible for initializing the hardware on an evaluation or target board The evaluation board might have General Purpose Input Output GPIO lines that might need to be configured relays sensors and more This functionality is found in a file called bsp c CPU_Init initializes the uC CPU services uwC CPU provides services to measure interrupt latency obtain time stamps and provides emulation of the count leading zeros instruction if the processor used does not have that instruction and more BSP_OS_TickInit sets up the wC OS II tick interrupt For this the function needs to initialize one of the hardware timers to interrupt the CPU at a rate of OSCfg_TickRate_Hz which is defined in os_cfg_app h See OS_CFG_TICK_RATE_HZ BSP_LED_Off is a function that will turn off all LEDs BSP_LED_Off is written such that a zero argument means all the LEDs Most uC OS III tasks will need to be written as an infinite loop 56 uC OS III User s Manual 7 8 Copyright 2015 Micrium Inc This BSP function toggles the state of the specified LED Again a zero indicates that all the LEDs should be toggled on the evaluation board You simply change the zero
120. Manual 1 2 3 4 5 6 7 The oS_SEM data type contains an OS_PEND_OBJ which in turn contains an OS_PEND_LIST The NbrEntries field in the pend list indicates that there are two tasks waiting on the semaphore The HeadPtr field of the pend list points to the 0S_PEND_DATA structure associated with the highest priority task waiting on the semaphore The TailpPtr field of the pend list points to the OS_PEND_DATA structure associated with the lowest priority task waiting on the semaphore Both 0S_PEND_DATA structures in turn point back to the 0S_SEM data structure The pointers think they are pointing to an OS_PEND_0BJ We know that the 0S_PEND_0BJ is a semaphore by examining the Type field of the 0S_PEND_OBJ Type will contain th tfourA SCII characters S E M and A Each 0S_PEND_DATA structure points to its respective 0S_TcB In other words we know which task is pending on the semaphore Each task points back to the 0S_PEND_DATA structure Finally the 0S_PEND_DATA structure forms a doubly linked list so that the wC OS HI can easily add or remove entries in this list Although this may seem complex the reasoning will become apparent in Pending on Multiple Objects For now you should assume that all of the links are necessary The table below shows the functions that uC OS III uses to manipulate entries in a pend list These functions are internal to uC OS II
121. OPT OS_OBJ_QTY CPU_TS OS _SEM_CTR OS_TICK OS_TICK OS_TICK OS_TICK void OS_MSG_SIZE OS _MSG_Q CPU_TS CPU_TS OS_REG OS_FLAGS OS_FLAGS OS_OPT OS_NESTING CTR OS_CPU_USAGE OS_CPU_USAGE OS_CTX_SW_CTR CPU_TS CPU_TS OS_CYCLES OS_CYCLES CPU_TS CPU_TS CPU_STK_SIZE CPU_STK_SIZE CPU_TS CPU OS_TCB OS_TCB CPU_CHAR StkPtr Copyright 2015 Micrium Inc StkPtr ExtPtr StkLimitPtr NextPtr PrevPtr TickNextPtr 3 TickPrevPtr TickListPtr NamePtr StkBasePtr TLS_Tb1 OS_CFG_TLS_TBL_SIZE TaskEntryAddr TaskEntryArg PendDataTb1Ptr PendOn PendStatus TaskState Prio BasePrio MutexGrpHeadPtr StkSize Opt PendDataEntries TS SemCtr TickRemain TickCtrPrev TimeQuanta TimeQuantaCtr MsgPtr MsgSize MsgQ MsgQPendTime MsgQPendTimeMax RegTb1 OS_TASK_REG_TBL_SIZE FlagsPend FlagsRdy FlagsOpt SuspendCtr CPUUsage CPUUsageMax CtxSwCtr CyclesDelta CyclesStart CyclesTotal CyclesTotalPrev SemPendTime SemPendTimeMax StkUsed StkFree IntDisTimeMax SchedLockTimeMax DbgNextPtr DbgPrevPtr DbgNamePtr Listing OS_TCB Data Structure 96 uC OS III User s Manual This field contains a pointer to the current top of stack for the task uC OS III allows each task to have its own stack and each stack can be any size StkPtr should be the only field in the os_TcB data structure accessed from assembly language code for the context switching code
122. OS III are deterministic Scalable The footprint both code and data can be adjusted based on the requirements of the application Adding and removing features i e services is performed at compile time through more than 50 defines see os_cfg h uC OS III also performs a number of run time checks on arguments passed to uC OS III services Specifically wC OS III verifies that the user is not passing NULL pointers not calling task level services from ISRs that arguments are within allowable range and options specified are valid etc These checks can be disabled at compile time to further reduce the code footprint and improve performance The fact that wC OS III is scalable allows it to be used in a wide range of applications and projects Portable uC OS III can be ported to a large number of CPU architectures Most uC OS II ports are easily converted to work on uC OS HI with minimal changes in just a matter of minutes and therefore benefit from more than 45 CPU architectures already supported by uC OS I ROMable uC OS III was designed especially for embedded systems and can be ROMed along with the application code Run time configurable uC OS III allows the user to configure the kernel at run time Specifically all kernel objects such as tasks stacks semaphores event flag groups message queues number of messages mutual exclusion semaphores memory partitions and timers are allocated by the user at run time This prevent
123. OS III to manage shared resources A shared resource is typically a variable static or global a data structure table in RAM or registers in an I O device When protecting a shared resource it is preferred to use mutual exclusion semaphores as will be described in this chapter Other methods are also presented Tasks can easily share data when all tasks exist in a single address space and can reference global variables pointers buffers linked lists ring buffers etc Although sharing data simplifies the exchange of information between tasks it is important to ensure that each task has exclusive access to the data to avoid contention and data corruption For example when implementing a module that performs a simple time of day algorithm in software the module obviously keeps track of hours minutes and seconds The TimeOfDay task may appear as shown in the listing below Imagine if this task was preempted by another task after setting the Minutes to 0 because an interrupt occurred and that the other task was more important than the TimeOfDay task Now imagine what will happen if this higher priority task wants to know the current time from the time of day module Since the Hours were not incremented prior to the interrupt the higher priority task will read the time incorrectly and in this case it will be incorrect by a whole hour The code that updates variables for the TimeOfDay task must treat all of the variabl
124. OSIdleTaskHook void Place the CPU in low power mode Typically most processors exit low power mode when an interrupt occurs Depending on the processor however the Interrupt Service Routine ISR may have to write to special registers to return the CPU to its full or desired speed If the ISR wakes up a high priority task every task is higher in priority than the idle task then the ISR will not immediately return to the interrupted idle task but instead switch to the higher priority task When the higher priority task completes its work and waits for its event to occur uC OS III causes a context switch to return to OSIdleTaskHook just after the instruction that caused the CPU to enter low power mode In turn OSIdleTaskHook returns to OS_IdleTask and causes another iteration through the infinite loop which places the CPU back in the low power state 111 uC OS III User s Manual The Tick Task Periodic Tick Nearly every RTOS requires a periodic time source called a Clock Tick or System Tick to keep track of time delays and timeouts uC OS III s clock tick handling is encapsulated in the file os_tick c OS_TickTask is a task created by uC OS III and its priority is configurable by the user through uC OS III s configuration file os_cfg_app h See OS_CFG_TICK_TASK_PRIO Typically OS_TickTask is set to a relatively high priority but should be slightly lower in priority than your most im
125. Resource sharing 209 uC OS III User s Manual Disable Enable Interrupts The easiest and fastest way to gain exclusive access to a shared resource is by disabling and enabling interrupts as shown in the pseudo code in the listing below Disable Interrupts Access the resource Enable Interrupts Listing Disabling and Enabling Interrupts uC OS III uses this technique as do most if not all kernels to access certain internal variables and data structures ensuring that these variables and data structures are manipulated atomically However disabling and enabling interrupts are actually CPU related functions rather than OS related functions and functions in CPU specific files are provided to accomplish this see the cpu h file of the processor being used The services provided in the CPU module are called uwC CPU Each different target CPU architecture has its own set of uC CPU related files void YourFunction void CPU_SR_ALLOC 1 CPU_CRITICAL_ENTER 2 Access the resource 3 CPU_CRITICAL_EXIT 4 Listing Using CPU macros to disable and enable interrupts 1 The cPU_SR_ALLOC macro is required when the other two macros that disable enable interrupts are used This macro simply allocates storage for a local variable to hold the value of the current interrupt disable status of the CPU If interrupts are already disabled we do not want to enable them upon exiting the critical section 2 CPU_CRITI
126. S II will check the validity of the values of arguments passed to functions The feature is enabled in os_cfg h ROM Variable Data Type Value OSDbg_AppHooksEn CPU_INT 8U OS_CFG_APP_HOOKS_EN When 1 the variable indicates whether application hooks will be available to the application programmer and the pointers listed below are declared This value is set in os_cfg h OS_AppTaskCreateHookPtr OS_AppTaskDelHookPtr OS_AppTaskReturnHookPtr OS_AppIdleTaskHookPtr OS_AppStatTaskHookPtr OS_AppTaskSwHookPtr Copyright 2015 Micrium Inc 399 uC OS III User s Manual OS_AppTimeTickHookPtr ROM Variable Data Type Value OSDbg_EndiannessTest CPU_INT32U x12345678 This variable allows a kernel awareness debugger or uC Probe to determine the endianness of the CPU This is easily done by looking at the lowest address in memory where this variable is saved If the value is 0x78 then the CPU is a little endian machine If it s 0x12 it is a big endian machine ROM Variable Data Type Value OSDbg_CalledFromISRChkEn CPU_INT 8U OS_CFG_CALLED_FROM_ISR_CHK_EN When 1 this variable indicates that wC OS III will perform run time checking to see if a function that is not supposed to be called from an ISR is called from an ISR This value is set in os_cfg h ROM Variable Data Type Value OSDbg_FlagEn CPU_INT 8U OS_CFG_FLAG_EN When 1 this variable indicates that wC OS III s event flag services are available to the applicati
127. SCtxSw lt BREAKPOINT here OS_CTX_SAVE OSTCBCurPtr gt StkPtr SP OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr OS_CTX_RESTORE Return from Interrupt Exception Listing paramCaptionText STEP 14 You can run the target at full speed and the debugger should bring you back at the breakpoint in OS_TickTask If you were to repeatedly run the target at full speed your debugger should now stop at the following places OSCtxSw OS_IdleTask OSCtxSw OS_TickTask OSCtxSw OS_IdleTask OSCtxSw Copyright 2015 Micrium Inc 377 uC OS III User s Manual etc Verifying Interrupt Context Switches In this section we will verify the proper operation of the following functions macros BSP_OS_TickISR bsp_os c bsp_os_a asm os_cpu_c c or os_cpu_a asm OSIntCtxSw os_cpu_a asm OS_ISR_ENTER os_cpu_a inc OS_ISR_EXIT os_cpu_a inc CPU_INT_EN cpu h CPU_IntEn cpu_a asm You can now remove the code we added in OSIdleTaskHook The code should now be as shown below void OSIdleTaskHook void if OS_CFG_APP_HOOKS EN gt u if OS_AppIdleTaskHookPtr OS_APP_HOOK_VOID 0S_AppIdleTaskHookPtr endif You should now setup the tick interrupt in main app c as shown below IA appre Ty include includes h void main void OS_ERR err OSInit amp err 1 Install interrupt vector for OSTickISR ay
128. SIZE found in os_cfg_app h When wC OS III is initialized OS_MSGs are linked in a single linked list as shown in the figure below Notice that the free list is maintained by a data structure of type 0S_MSG_POOL which contains four 4 fields NextPtr which points to the free list NorFree which contains the number of free OS_MSGs in the pool NbrUsed which contains the number of 0S_MSGs allocated to the application and NbrUsedMax which detects the maximum number of messages allocated to the application OS_MSG_POOL OS_MSG OS_MSG OS_MSG NbrUsed NbrUsedMax os_cre_wse poo siz Figure Pool of free OS_MSGs Messages are queued using a data structure of type OS_MSG_Q as shown in the figure below Copyright 2015 Micrium Inc 303 uC OS III User s Manual OS_MSG_Q Pointer to next OS_MSG to insert outPtr Pointer to next OS_MSG to remove NbrEntriesSize NbrEntriesMax Figure OS_MSG_Q structure InPtr This field contains a pointer to where the next 0S_MsG will be inserted in the queue In fact the 0S_MSG will be inserted after the 0S_MSG pointed to OutPtr This field contains a pointer to where the next os_msG will be extracted NbrEntriesSize This field contains the maximum number of os_MSGs that the queue will hold If an application attempts to send a message and the NbrEntries matches this value the queue is considered to be full and the os_msG will not be inserted
129. S_EN gt u if OS_AppTaskSwHookPtr OS_APP_HOOK_VOID 1 0S_AppTaskSwHookPtr endif if OS_CFG_TASK_PROFILE_EN gt u ts OS_TS_GET 2 if OSTCBCurPtr OSTCBHighRdyPtr OSTCBCurPtr gt CyclesDelta ts OSTCBCurPtr gt CyclesStart OSTCBCurPtr gt CyclesTotal OS_CYCLES OSTCBCurPtr gt CyclesDelta OSTCBHighRdyPtr gt CyclesStart ts endif ifdef CPU_CFG_INT_DIS MEAS EN int_dis_time CPU_IntDisMeasMaxCurReset 3 if OSTCBCurPtr gt IntDisTimeMax lt int_dis_time OSTCBCurPtr gt IntDisTimeMax int_dis_time endif if OS_CFG_SCHED_LOCK_TIME_MEAS_EN gt Qu if OSTCBCurPtr gt SchedLockTimeMax lt OSSchedLockTimeMaxCur 4 OSTCBCurPtr gt SchedLockTimeMax OSSchedLockTimeMaxCur OSSchedLockTimeMaxCur CPU_TS endif if OS_CFG_TASK_STK_REDZONE_EN DEF_ENABLED stk_status OSTaskStkRedzoneChk DEF_NULL 5 if stk_status DEF_OK OSRedzoneHitHook OSTCBCurPtr endif Listing Typical OSTaskSwHook 1 If the application code defined a hook function to be called during a context switch then this function is called first You application hook function can assume that OSTCBCurPtr points to the os_TcB of the task being switched out while OSTCBHighRdyPtr points to the os_TcB of the task being switched in 2 OSTaskSwHook then computes the amount of time the current task ran However this includes the execution time of all the ISRs tha
130. S_IntQTask if that task is enabled in os_cfg h through the 0S_CFG_ISR_POST_DEFERRED_EN constant If this is the case OS_IntQTask will perform some initialization of its own and then uC OS III will switch to the next most important task that was created A few important points are worth noting For one thing you can create as many tasks as you want before calling osstart However it is recommended to only create one task as shown in the example because having a single application task allows uC OS HI to determine the relative speed of the CPU This allows wC OS II to determine the percentage of CPU usage at runtime Also if the application needs other kernel objects such as semaphores and message queues then it is recommended that these be created prior to calling osstart Finally notice that interrupts are not enabled This will be discussed next by examining the contents of AppTaskStart which is shown in the listing below Copyright 2015 Micrium Inc 55 uC OS III User s Manual static void AppTaskStart void p_arg 1 1 2 3 4 5 6 Copyright 2015 Micrium Inc OS ERR err p_arg p_arg BSP_Init 2 CPU_Init 3 BSP_OS_TickInit 4 BSP_LED_Off 5 while 1 6 BSP_LED_Toggle 7 OSTimeD1lyHMSM CPU_INT16U 8 CPU_LINT16U CPU_LINT16U CPU_INT32U 100 OS_OPT OS_OPT_TIME_HMSM_STRICT OS_ERR amp err Check for err
131. S_SEM Mutual Exclusion OS_MUTEX Semaphores Synchronization Semaphores OS_SEM Event Flags OS_FLAG_GRP Message Passing Message Queues OS_Q A pend list is similar to the Ready List except that instead of keeping track of tasks that are ready to run the pend list keeps track of tasks waiting for an object to be posted In addition the pend list is sorted by priority the highest priority task waiting on the object is placed at the head of the list and the lowest priority task waiting on the object is placed at the end of the list A pend list is a data structure of type 0S_PEND_LIST which consists of three fields as shown in the figure below TailPtr Figure Pend List NbrEntries Contains the current number of entries in the pend list Each entry in the pend list points to a task that is waiting for the kernel object to be posted TailPtr Is a pointer to the last task in the list i e the lowest priority task HeadPtr Copyright 2015 Micrium Inc 179 uC OS III User s Manual Is a pointer to the first task in the list i e the highest priority task The figure below indicates that each kernel object using a pend list contains the same three fields at the beginning of the kernel object that we called an 0S_PEND_0BJ Notice that the first field is always a Type which allows uC OS III to know if the kernel object is a semaphore a mutual exclusion semaphore an event flag group or a message queue object
132. Semaphores NamePtr This is a pointer to an ASCII string used to provide a name to the semaphore The ASCII string can have any length as long as it is NUL terminated PendList NbrEntries Each semaphore contains a wait list of tasks waiting for the semaphore to be signaled The variable represents the number of entries in the wait list Ctr This variable represents the current count of the semaphore TS This variable contains the timestamp of when the semaphore was last signaled Mutual Exclusion Semaphores NamePtr This is a pointer to an ASCII string used to provide a name to the mutual exclusion semaphore The ASCII string can have any length as long as it is NUL terminated PendList NbrEntries Each mutual exclusion semaphore contains a list of tasks waiting for the semaphore to be released The variable represents the number of entries in the wait list OwnerOriginalPrio Copyright 2015 Micrium Inc 395 uC OS III User s Manual This variable holds the original priority of the task that owns the mutual exclusion semaphore OwnerTCBPtr gt Prio Dereferencing the pointer to the os_TcB of the mutual exclusion semaphore owner allows the application to determine whether a task priority was changed OwnerNestingCtr This variable indicates how many times the owner of the mutual exclusion semaphore requested the semaphore TS This variable contains the timestamp of when the mutual exclusion semaphore was last
133. Status Register also called the Program Status Word of the CPU onto the stack first Also the value stored at this location must be such that once restored into the CPU the SR must enable ALL interrupts Here we assumed that a value of xeeeeeeee would do this However you need to check with the processor you are using to find out how this works on that processor 353 uC OS III User s Manual 3 The address of the task code is then placed onto the next stack location This way when you perform a return from interrupt or exception instruction the PC will automatically be loaded with the address of the task to run 4 You should recall that a task is passed an argument p_arg p_arg is a pointer to some user define storage or function and its use is application specific In the assumptions above we indicated that a function called with a single argument gets this argument passed in Re You will need to check the compiler documentation to determine where p_arg is placed for your processor 5 The remaining registers are placed onto the stack You will notice that we initialized the value of those registers with a hexadecimal number that corresponds to the register number In other words R12 should have the value x12121212 when the task starts R11 should have the value x11111111 when the task starts and so on This makes it easy to determine whether the stack frame was setup properly when you test the port You would si
134. TMR A timer is a kernel object as defined by the 0S_TMR data type see os h as shown in the listing below The services provided by uC OS III to manage timers are implemented in the file os_tmr c Timer services are enabled at compile time by setting the configuration constant OS_CFG_TMR_EN to DEF_ENABLED in os_cfg h typedef struct os_tmr OS_TMR 1 struct os_tmr 3 1 Copyright 2015 Micrium Inc OS_OBJ_TYPE Type 2 CPU_CHAR NamePtr 3 OS_TMR_CALLBACK_PTR CallbackPtr 4 void CallbackPtrArg 5 OS_TMR NextPtr 6 OS_TMR PrevPtr OS_TICK Remain 7 OS_TICK Dly 8 OS_TICK Period 9 OS_OPT Opt 10 OS_STATE State 11 Listing OS_TMR data type In uC OS III all structures are given a data type In fact all data types start with os_ and are all uppercase When a timer is declared you simply use OS_TMR as the data type 199 uC OS III User s Manual 2 3 4 5 6 7 8 9 Copyright 2015 Micrium Inc of the variable used to declare the timer The structure starts with a Type field which allows it to be recognized by uC OS III as a timer Other kernel objects will also have a Type as the first member of the structure If a function is passed a kernel object uC OS III is able to confirm that it is passed the proper data type assuming OS_CFG_OBJ_TYPE_CHK_EN is set to DEF_ENABLED in os_cfg h For example if passing a message queue 0S_Q
135. The figure below shows the state diagram of a timer Tasks can call OSTmrStateGet to find out the state of a timer Also at any time during the countdown process the application code can call OSTmrRemainGet to find out how much time remains before the timer reaches zero 0 The value returned is expressed in timer ticks If timers are decremented at a rate of 10 Hz then a count of 50 corresponds to 5 seconds If the timer is in the stop state the time remaining will correspond to either the initial delay one shot or periodic with initial delay or the period if the timer is configured for periodic without initial delay OSTmrCreate OSTmrDel Unused 0 OSTmrStop OSTmrStart Callback One Shot tly Expired Callback OSTmrDel Completed 3 OSTmrStart OSTmrStart or Periodic Callback Figure Timer State Diagram Copyright 2015 Micrium Inc 198 uC OS III User s Manual 1 The Unused state is a timer that has not been created or has been deleted In other words uC OS III does not know about this timer 2 When creating a timer or calling OSTmrStop the timer is placed in the stopped state 3 A timer is placed in running state when calling OSTmrstart The timer stays in that state unless it s stopped deleted or completes its one shot 4 The Completed state is the state a one shot timer is in when its delay expires OS_
136. The pseudo code to acquire all of the mutexes in the same order is shown in the listing below This is similar to the previous example except that it is not necessary to acquire all the mutexes first only to make sure that the mutexes are acquired in the same order for both tasks void T1 void p_arg while DEF_ON Wait for event to occur Acquire M1 Access R1 Acquire M2 Access R2 void T2 void p_arg while DEF_ON Wait for event to occur Acquire M1 Access R1 Acquire M2 Access R2 Listing Deadlock avoidance acquire in the same order Copyright 2015 Micrium Inc 246 uC OS III User s Manual Synchronization This chapter focuses on how tasks can synchronize their activities with Interrupt Service Routines ISRs or other tasks When an ISR executes it can signal a task telling the task that an event of interest has occurred After signaling the task the ISR exits and depending on the signaled task priority the scheduler is run The signaled task may then service the interrupting device or otherwise react to the event Servicing interrupting devices from task level is preferred whenever possible since it reduces the amount of time that interrupts are disabled and the code is easier to debug There are two basic mechanisms for synchronizations in wC OS HI semaphores and event flags Copyright 2015 Micrium Inc 247 uC OS III User s Manual Semaphores About Semaphores As defined in R
137. This feature is not as useful when semaphores are used to share resources as it is when used as a signaling mechanism OSSemPost checks to see if any tasks are waiting for the semaphore If not oSSemPost simply increments p_sem gt Ctr saves the timestamp in the semaphore and returns If there are tasks waiting for the semaphore to be released OSSemPost extracts the highest priority task waiting for the semaphore This is a fast operation as the pend list is sorted by priority order When calling osSemPost it is possible to specify as an option to not call the scheduler This means that the post is performed but the scheduler is not called even if a higher priority task waits for the semaphore to be released This allows the calling task to perform other post functions if needed and make all posts take effect simultaneously without the possibility of context switching in between each post 229 uC OS III User s Manual Priority Inversions Priority inversion is a problem in real time systems and occurs only when using a priority based preemptive kernel The figure below illustrates a priority inversion scenario Task H high priority has a higher priority than Task M medium priority which in turn has a higher priority than Task L low priority Unbounded t Priority Inversion Task H Co w TaskH Semaphore Task L Preempts Owned Releases Task M Task L by Task L Semaphore 4 6 12 Task M
138. TickISR then needs to increment the interrupt nesting counter This tells uC OS III that the code is servicing an interrupt The nesting counter indicates how many levels of interrupts we are currently servicing in case the application supports nested interrupts If this interrupt interrupts a task then we need to save the stack pointer of that task into the 0S_TcB of that task 344 uC OS III User s Manual 6 7 8 9 10 You need to clear the interrupting device so that it doesn t re issue the same interrupt upon returning from interrupts This can be done here or in the device handler see below At this point BSP_OS_TickISR calls OSTimeTick which is responsible for notifying the tick task that a tick occurred If you model your ISR like BSP_OS_TickISR then you would call your own C function to service the interrupting device OSIntExit is then called at the end of the ISR to notify uC OS III that you are done processing the ISR uwC OS III decrements the nesting counter and if OSIntNestingCtr reaches uC OS III knows it s returning to task level code So if the ISR made a more important task ready to run more important than the interrupted task uwC OS III will context switch to that task instead of returning to the interrupted task If the interrupted task is still the most important task then OSIntExit returns and the ISR will need to restore the saved registers OS_CTX_RESTORE d
139. U_TS amp ts OS_ERR amp err if err OS_ERR_TIMEOUT 6 RPM else if delta gt Qu RPM 60 Reference Frequency delta 7 Compute average RPM 8 Detect maximum RPM Check for overspeed Check for underspeed 297 uC OS III User s Manual 1 2 3 4 5 6 Listing Pseudo code of RPM measurement Variables are declared Notice that it is necessary to allocate storage for the message queue itself You need to call OSInit and create the message queue before it is used The best place to do this is in startup code The RPM ISR clears the sensor interrupt and reads the value of the 32 bit input capture Note that it is possible to read RPM if there is only a 16 bit input capture The problem with a 16 bit input capture is that it is easy for it to overflow especially at low RPMs The RPM ISR also computes delta counts directly in the ISR It is just as easy to post the current counts and let the task compute the delta However the subtraction is a fast operation and does not significantly increase ISR processing time The code then sends the delta counts to the RPM task which is responsible for computing the RPM and perform additional computations Note that the message gets lost if the queue is full when the user attempts to post This happens if data is generated faster than it is processed Unfortunately it is not possible to implement flow control in the e
140. User s Manual ROM Variable Data Type Value OSDbg_TaskRegTblSize CPU_INT16U OS_CFG_TASK_REG_TBL_SIZE This variable indicates how many entries each task register table can accept ROM Variable Data Type Value OSDbg_TaskSemPendAbortEn CPU_INT 8U OS_CFG_TASK_SEM_PEND_ABORT_EN When 1 this variable indicates that the function OSTaskSemPendAbort is available to the application This value is set in os_cfg h ROM Variable Data Type Value OS_CFG_TASK_SUSPEND_EN OSDbg_TaskSuspendEn CPU_INT 8U When 1 this variable indicates that the function OSTaskSuspend is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TCBSize CPU_INT16U sizeof OS_TCB This variable indicates the RAM footprint in bytes of an oS_TcB data structure ROM Variable Data Type Value CPU_INT 8U OS_CFG_TIME_DLY_HMSM_EN OSDbg_TimeD1lyHMSMEn When 1 this variable indicates that the function OSTimeDlyHMSM is available to the application This value is set in os_cfg h ROM Variable Data Type Value OS_CFG_TIME_DLY_RESUME_EN OSDbg _TimeDlyResumeEn CPU_INT 8U When 1 this variable indicates that the function OSTimeDlyResume is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_ TLS _Tb1Size CPU_INT16U OS_CFG_TLS_TBL_SIZE Copyright 2015 Micrium Inc 408 uC OS III User s Manual Indicates the size of the TLS_Tb1 in an 0S_TCB in number of bytes This val
141. _CHK_EN is set to 1 in os_cfg h If the bits the task is waiting for are set or cleared depending on the option OSFlagPend returns and indicate which flags satisfied the condition This is the outcome that the caller expects If the event flag group does not contain the flags that the caller is looking for the calling task might need to wait for the desired flags to be set or cleared If you specify OS_OPT_PEND_NON_BLOCKING as the option the task is not to block OSFlagPend returns immediately to the caller and the returned error code indicates that the bits have not been set or cleared If you specify OS_OPT_PEND_BLOCKING as the option the calling task will be inserted in the list of tasks waiting for the desired event flag bits The task is not inserted in priority order but simply inserted at the beginning of the list This is done because whenever bits are set or cleared it is necessary to examine all tasks in this list to see if their desired bits have been satisfied If you further specify a non zero timeout the task will also be inserted in the tick list A zero value for a timeout indicates that the calling task is willing to wait forever for the 273 uC OS III User s Manual desired bits The scheduler is then called since the current task is no longer able to run it is waiting for the desired bits The scheduler will run the next highest priority task that is ready to run When the event flag group i
142. _SIZE_MAX This define specifies the maximum word size of the processor in number of bytes cpu_def h offers the following choices CPU_WORD_SIZE_ 8 CPU_WORD_SIZE_16 CPU_WORD_SIZE_32 CPU_WORD_SIZE_64 Copyright 2015 Micrium Inc 338 uC OS III User s Manual CPU_CFG_STK_GROWTH This define specifies whether the stack grows from high to low memory or from low to high memory addresses cpu_def h offers the following choices CPU_STK_GROWTH_LO_TO_HI CPU_STK_GROWTH_HI_TO_LO CPU_CFG_CRITICAL_METHOD This define establishes how interrupts will be disabled when processing critical sections Specifically will we simply disable interrupts when entering a critical section irrespective of whether or not interrupts were already disabled Will we save the status of the interrupt disable state before we disable interrupts cpu_def h offers the following choices CPU_CRITICAL_METHOD_INT_DIS_EN CPU_CRITICAL_METHOD_STATUS_STK CPU_CRITICAL_METHOD_STATUS_LOCAL cpu h also declares function prototypes for a number of functions found in either cpu_c c or cpu_a asm cpu_c c This is an optional file containing CPU specific functions to set the interrupt controller timer prescalers and more Most implementations will not contain this file cpu_a asm This file contains assembly language code to implement such functions as disabling and enabling interrupts a more efficient count leading zeros function and more At a minimum this fil
143. a Memory Partition Before using a memory partition it must be created This allows uC OS III to know something about the memory partition so that it can manage their allocation and deallocation Once created a memory partition is as shown in the figure below Calling osMemCreate creates a memory partition 1 gt k Number of Blocks Figure Created Memory Partition 1 When creating a partition the application code supplies the address of a memory partition control block 0S_MEM Typically this memory control block is allocated from static memory however it can also be obtained from the heap by calling malloc The application code should however never deallocate it 2 OSMemCreate organizes the continuous memory provided into a singly linked list and stores the pointer to the beginning of the list in the 0S_MEM structure 3 Each memory block must be large enough to hold a pointer Given the nature of the linked list a block needs to be able to point to the next block The listing below indicates how to create a memory partition with uC OS IIL Copyright 2015 Micrium Inc 316 uC OS III User s Manual OS_MEM MyPartition 1 CPU_INT 8U MyPartitionStorage 12 100 2 void main void 3 OS_ERR err OSInit amp err OSMemCreate OS_MEM amp MyPartition 4 CPU_CHAR My Partition 5 void amp MyPartitionStorage 6 OS_MEM_QTY 12 7 OS_MEM_SIZE 100 8
144. aCtr keeps track of the remaining number of ticks for this to happen and is loaded with TimeQuanta at the beginning of the task s time slice MsgPtr When a message is sent to a task this field contains the message received This field only Copyright 2015 Micrium Inc 102 uC OS III User s Manual exists in a TCB if message queue services OS_CFG_Q_EN is set to DEF_ENABLED in os_cfg h or task message queue services are enabled OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h at compile time MsgSize When a message is sent to a task this field contains the size in number of bytes of the message received This field only exists in a TCB if message queue services OS_CFG_Q_EN is set to DEF_ENABLED in os_cfg h or task message queue services OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h are enabled at compile time MsgQ uC OS III allows tasks or ISRs to send messages directly to tasks Because of this a message queue is actually built into each TCB This field only exists in a TCB if task message queue services are enabled at compile time 0S_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h MsgQ is used by the OSTaskQ services MsgQPendTime This field contains the amount of time it took for a message to arrive When OSTaskQPost is called the current time stamp is read and stored in the message When OSTaskQPend returns the current time stamp is read again and the difference between the two times is
145. accessing shared resources Semaphores are subject to unbounded priority inversions while mutex are not Copyright 2015 Micrium Inc 243 uC OS III User s Manual Deadlocks A deadlock also called a deadly embrace is a situation in which two tasks are each unknowingly waiting for resources held by the other Assume Task T1 has exclusive access to Resource R1 and Task T2 has exclusive access to Resource R2 as shown in the pseudo code of the listing below void T1 void p_arg while DEF_ON 1 2 3 4 Copyright 2015 Micrium Inc Wait for event to occur 1 Acquire M1 2 Access R1 3 Interrupt 4 8 Acquire M2 9 Access R2 void T2 void p_arg while DEF_ON Wait for event to occur 5 Acquire M2 6 Access R2 Acquire M1 7 Access R1 Assume that the event that task T1 is waiting for occurs and T1 is now the highest Listing Deadlock problem priority task that must execute Task T1 executes and acquires Mutex M1 Resource R1 is accessed An interrupt occurs causing the CPU to switch to task T2 since T2 has a higher priority than task T1 244 uC OS III User s Manual 5 6 7 8 9 The ISR is the event that task T2 was waiting for and therefore T2 resumes execution Task T2 acquires mutex M2 and is able to access resource R2 Task T2 tries to acquire mutex M1 but wC OS III knows that mutex M1 is owned by
146. ack to handle ISRs plus whatever stack space is needed by those ISRs Adding all this up is a tedious chore and the resulting number is a minimum requirement Most likely you would not make the stack size that precise in order to account for surprises The number arrived at should probably be multiplied by some safety factor possibly 1 5 to 2 0 This calculation assumes that the exact path of the code is known at all times which is not always possible Specifically when calling a function such as printf or some other library function it might be difficult or nearly impossible to even guess just how much stack space printf will require In this case start with a fairly large stack space and monitor the stack usage at run time to see just how much stack space is actually used after the application runs for a while There are really cool and clever compilers linkers that provide this information in a link map For each function the link map indicates the worst case stack usage This feature clearly enables you to better evaluate stack usage for each task It is still necessary to add the stack space for a full CPU context plus another full CPU context for each nested ISR if the CPU does not have a separate stack to handle ISRs plus whatever stack space is needed by those ISRs Again allow for a safety net and multiply this value by some factor Always monitor stack usage at run time while developing and testing the product as stack
147. age directly to a task if only one task will process the data received When a task waits for a message to arrive it does not consume CPU time Copyright 2015 Micrium Inc 283 uC OS III User s Manual Messages A message consists of a pointer to data a variable containing the size of the data being pointed to and a timestamp indicating when the message was sent The pointer can point to a data area or even a function Obviously the sender and the receiver must agree as to the contents and the meaning of the message In other words the receiver of the message will need to know the meaning of the message received to be able to process it For example an Ethernet controller receives a packet and sends a pointer to this packet to a task that knows how to handle the packet The message contents must always remain in scope since the data is actually sent by reference instead of by value In other words data sent is not copied You might consider using dynamically allocated memory as described in Memory Management API Changes Alternatively you can pass a pointer to a global variable a global data structure a global array or a function etc Copyright 2015 Micrium Inc 284 uC OS III User s Manual Message Queues A message queue is a kernel object allocated by the application In fact you can allocate any number of message queues The only limit is the amount of RAM available There are a number of operations that the user
148. age files Copyright 2015 Micrium Inc 331 uC OS III User s Manual uC CPU About pC CPU uC CPU is a module that provides CPU specific functionality that is independent of uC OS IIL Specifically uC CPU defines compiler and CPU dependent data types the word width of the stack whether the stack grows from high to low memory or from low to high memory functions for disabling and enabling interrupts and more Additional information about this module is provided in the wC CPU User Manual The table below shows the name of uC CPU files and where they should be placed on the computer used to develop a uC OS II based application The file names in bold are files you will need to create or modify for your own port File Directory cpu_bsp c Micrium Software uC CPU BSP Template cpu_bsp c cpu_def h Micrium Software uC CPU cpu_cfg h Micrium Software uC CPU CFG Template cpu_core c Micrium Software uC CPU cpu_core h Micrium Software uC CPU cpu h Micrium Software uC CPU lt processor gt lt compiler gt cpu_c c Micrium Software uC CPU lt processor gt lt compiler gt cpu_a asm Micrium Software uC CPU lt processor gt lt compiler gt Table uC CPU files and directories lt processor gt is the name of the processor that the cpu files apply to lt compiler gt is the name of the toolchain compiler assembler linker locator used Each has its own directory because they may have different features that makes them differe
149. ailable Typically two types of semaphores exist binary semaphores and counting semaphores As its name implies a binary semaphore can only take two values 0 or 1 A counting semaphore allows for values between 0 and 255 65 535 or 4 294 967 295 depending on whether the semaphore mechanism is implemented using 8 16 or 32 bits respectively For C OS II the maximum value of a semaphore is determined by the data type 0S_SEM_CTR see os_type h which can be changed as needed Along with the semaphore s value C OS III also keeps track of tasks waiting for the semaphore s availability Only tasks are allowed to use semaphores when semaphores are used for sharing resources ISRs are not allowed A semaphore is a kernel object defined by the os_sem data type which is defined by the structure os_sem see os h The application can have any number of semaphores limited only by the amount of RAM available There are a number of operations the application is able to perform on semaphores summarized in the table below In this chapter only the three most used functions are discussed OSSemCreate OSSemPend and OSSemPost The other functions are described in Copyright 2015 Micrium Inc 213 uC OS III User s Manual uC OS III API Reference When semaphores are used for sharing resources every semaphore function must be called from a task and never from an ISR The same limitation does not apply when using semaphores for
150. al characters that makes up the string OSMutexCreate returns an error code based on the outcome of the call If all the arguments are valid err will contain 0S_ERR_NONE Note that since a mutex is always a binary semaphore there is no need to initialize a mutex counter A task waits on a mutual exclusion semaphore before accessing a shared resource by calling OSMutexPend as shown in the listing below see wC OS III API Reference for details regarding the arguments OS_MUTEX MyMutex Copyright 2015 Micrium Inc void MyTask void p_arg OS_ERR err CPU_TS ts while DEF_ON OSMutexPend amp MyMutex 1 Pointer to mutex yf 10 if Wait up until this time for the mutex ay OS_OPT_PEND BLOCKING Option s amp ts if Timestamp of when mutex was released a amp err jf Pointer to Error returned i Check err 2 s OSMutexPost amp MyMutex 3 Pointer to mutex Off OS_OPT_POST_NONE amp err ife Pointer to Error returned if Check err yf Listing Pending or waiting on a Mutual Exclusion Semaphore When called OSMutexPend starts by checking the arguments passed to this function to 239 uC OS III User s Manual Copyright 2015 Micrium Inc make sure they have valid values This assumes that OS_CFG_ARG_CHK_EN is set to DEF_ENABLED in os_cfg h If the mutex is available OSMutexPend assumes the calling task is now the owner of the mutex and stores a p
151. alized however that I would pay for the seemingly cheaper operating system with my time During the two months after receiving the kernel I was in constant contact with technical support trying fruitlessly to determine why even the simplest applications would not Copyright 2015 Micrium Inc uC OS III User s Manual run The operating system said to be written in C required me to initialize all of the kerne s internal variables in assembly language a task laden with problems I eventually discovered that I was one of the first customers to purchase this operating system and was essentially an unknowing beta tester Frustrated with the software s many shortcomings I turned to the relatively expensive operating system that I originally rejected It seems that if a project is late money is no object Within two days I was running simple applications that the cheap operating system seemed unable to support My kernel related problems seemed to be over Before long however I would find myself at another impasse My second set of problems began when one of my engineers reported that the new operating system seemed to contain a bug I promptly relayed the engineer s findings to the software vendor assuming that the company would be interested Instead of receiving assurance that the bug would be fixed I was notified that the 90 day warranty expired Unless I purchased a maintenance contract the bug would not be eliminated which
152. allowed to send characters to a printer at the same time The printer would contain interleaved data from each task For instance the printout from Task 1 printing I am Task 1 and Task 2 printing I am Task 2 could result in I Ia amm T Tasask k1 2 In this case you can use a semaphore and initialize it to 1 i e a binary semaphore The rule is simple to access the printer each task must first obtain the resource s semaphore The figure below shows tasks competing for a semaphore to gain exclusive access to the printer Note that a key indicating that each task must obtain this key to use the printer represents the semaphore symbolically Copyright 2015 Micrium Inc uC OS III User s Manual OSSemPend Access Printer a rA PE AccessPrinter OSSemPost Semaphore Figure Using a semaphore to access a printer The above example implies that each task knows about the existence of the semaphore to access the resource It is almost always better to encapsulate the critical section and its protection mechanism Each task would therefore not know that it is acquiring a semaphore when accessing the resource For example an RS 232C port is used by multiple tasks to send commands and receive responses from a device connected at the other end as shown in the figure below COMM Module CommSendCmd Pa RS 232C CommSendCmd A OSSemPend OSSemPost i Semaphore
153. ally However on most processors it is important to know how to save the CPU registers onto the task s stack You should save the full context of the CPU which may also include Floating Point Unit FPU registers if the CPU used is equipped with an FPU Certain CPUs also automatically switch to a special stack just to process interrupts i e an interrupt stack This is generally beneficial as it avoids using up valuable task stack space However for uwC OS III the context of the interrupted task needs to be saved onto that task s stack 158 uC OS III User s Manual 4 5 6 7 8 Copyright 2015 Micrium Inc If the processor does not have a dedicated stack pointer to handle ISRs then it is possible to implement one in software Specifically upon entering the ISR simply save the current task stack switch to a dedicated ISR stack and when done with the ISR switch back to the task stack Of course this means that there is additional code to write however the benefits are enormous since it is not necessary to allocate extra space on the task stacks to accommodate for worst case interrupt stack usage including interrupt nesting Next either call oSIntEnter or simply increment the variable OSIntNestingCtr in assembly language This is generally quite easy to do and is more efficient than calling OSIntEnter As its name implies OSIntNestingCtr keeps track of the interrupt nesting level If this
154. also typically dedicated systems In other words systems that are designed to perform a dedicated function The following list shows just a few examples of embedded systems Aerospace Flight management systems e Jet engine controls Weapons systems Audio MP3 players e Amplifiers and tuners Automotive e Antilock braking systems Climate control Engine controls e Navigation systems GPS Communications Routers e Switches Cell phones Computger peripherals e Printers e Scanners Domestic e Air conditioning units Thermostats e White goods Office automation e FAX machines copiers Process control e Chemical plants Factory automation Food processing Robots Video Broadcasting equipment e HD Televisions And many more Real time systems are typically more complicated to design debug and deploy than Copyright 2015 Micrium Inc 13 uC OS III User s Manual non real time systems Copyright 2015 Micrium Inc 14 uC OS III User s Manual Foreground Background Systems Small systems of low complexity are typically designed as foreground background systems or super loops An application consists of an infinite loop that calls modules i e tasks to perform the desired operations background Interrupt Service Routines ISRs handle asynchronous events foreground Foreground is also called interrupt level background is called task level Critical o
155. alue OSDbg_QFlushEn CPU_INT 8U OS_CFG_Q_FLUSH_EN When 1 this variable indicates that the function OSQFlush is available to the application This value is set in os_cfg h Copyright 2015 Micrium Inc 404 uC OS III User s Manual ROM Variable Data Type Value OSDbg_QPendAbortEn CPU_INT 8U OS_CFG_Q PEND_ABORT_EN When 1 this variable indicates that the function OSQPendAbort is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_QSize CPU_INT16U This variable indicates the RAM footprint in number of bytes of an os_Q data type ROM Variable Data Type Value OSDbg_SchedRoundRobinEn CPU_INT 8U OS_CFG_SCHED_ROUND_ROBIN_EN When 1 this variable indicates that the wC OS III round robin scheduling feature is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_SemEn CPU_INT 8U OS_CFG_SEM_EN When 1 this variable indicates that wC OS III s semaphore management services are available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_SemDelEn CPU_INT 8U OS_CFG_SEM_DEL_EN When 1 this variable indicates that the function OSSemDe1 is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_SemPendAbortEn CPU_INT 8U OS_CFG_SEM_PEND_ABORT_EN When 1 this variable indicates that the function OSSemPendAbort is available to the application This v
156. alue is set in os_cfg h ROM Variable Data Type Value Copyright 2015 Micrium Inc 405 uC OS III User s Manual OSDbg_SemSetEn CPU_INT 8U OS_CFG_SEM_SET_EN When 1 this variable indicates that the function OSSemSet is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_SemSize CPU_INT16U sizeof OS_SEM This variable indicates the RAM footprint in bytes of an os_sem data type ROM Variable Data Type Value OSDbg_RdyList CPU_INT16U sizeof 0S_RDY_LIST This variable indicates the RAM footprint in bytes of the 0S_RDY_LIST data type ROM Variable Data Type Value OSDbg_RdyListSize CPU_INT32U sizeof OSRdyList This variable indicates the RAM footprint in bytes of the ready list ROM Variable Data Type Value OSDbg_StkWidth CPU_INT 8U sizeof CPU_STK This variable indicates the word size of a stack entry in bytes If a stack entry is declared as CPU_INT 8U this value will be 1 if a stack entry is declared as CPU_INT16U the value will be 2 etc ROM Variable Data Type Value OSDbg_StatTaskEn CPU_INT 8U OS_CFG_STAT_TASK_EN When 1 this variable indicates that wC OS III s statistic task is enabled This value is set in os_cfg h ROM Variable Data Type Value OSDbg_ StatTaskStkChkEn CPU_INT 8U OS_CFG_STAT_TASK_STK_CHK_EN Copyright 2015 Micrium Inc 406 uC OS III User s Manual When 1 this variable indicates that uC OS III will perform run time stack check
157. an 60 to 70 percent of the CPU RMS says that the highest rate task has the highest priority In some cases the highest rate task might not be the most important task The application should dictate how to assign priorities However RMS is an interesting starting point Number of Tasks n 21 n 1 1 1 00 2 0 828 3 0 779 4 0 756 5 0 743 Infinite 0 693 Table Allowable CPU usage based on number of tasks Copyright 2015 Micrium Inc 80 uC OS III User s Manual Determining the Size of a Stack The size of the stack required by the task is application specific When sizing the stack however one must account for the nesting of all the functions called by the task the number of local variables to be allocated by all functions called by the task and the stack requirements for all nested interrupt service routines In addition the stack must be able to store all CPU registers and possibly Floating Point Unit FPU registers if the processor has a FPU In addition as a general rule in embedded systems avoid writing recursive code It is possible to manually figure out the stack space needed by adding all the memory required by all function call nesting 1 pointer each function call for the return address plus all the memory required by all the arguments passed in those function calls plus storage for a full CPU context depends on the CPU plus another full CPU context for each nested ISRs if the CPU doesn t have a separate st
158. an alternative to malloc and free by allowing an application to obtain fixed sized memory blocks from a partition made from a contiguous memory area as illustrated in the figure below All memory blocks are the same size and the partition contains an integral number of blocks Allocation and deallocation of these memory blocks is performed in constant time and is deterministic The partition itself is typically allocated statically as an array but can also be allocated by using malloc as long as it is never freed Base Address gt Partition Block Size Memory Block Figure Memory Partition As indicated in the figure below more than one memory partition may exist in an application and each one may have a different number of memory blocks and be a different size An application can obtain memory blocks of different sizes based upon requirements However a specific memory block must always be returned to the partition that it came from This type of Copyright 2015 Micrium Inc 314 uC OS III User s Manual memory management is not subject to fragmentation except that it is possible to run out of memory blocks It is up to the application to decide how many partitions to have and how large each memory block should be within each partition Partition 1 Partition 2 Partition 3 Partition 4 Figure Multiple Memory Partitions Copyright 2015 Micrium Inc 315 uC OS III User s Manual Creating
159. and often save valuable time Since there is no naming convention for these files c and h are assumed The Board Support Package BSP code needed by uC OS III is typically quite simple and generally wC OS III only requires that you initialize a periodic interrupt source which is used for time delays and timeouts This functionality can should be placed in a file called os_bsp c along with its corresponding header file bsp_os h This is the uwC OS III processor independent code This code is written in highly portable ANSIC This is the uwC OS III code that is adapted to a specific CPU architecture and is called a port uC OS III has its roots in wC OS II and benefits from being able to use most of the 45 or so ports available for wC OS II uC OS II ports however will require small changes to work with wC OS II At Micrium we encapsulate CPU functionality These files define functions to disable and enable interrupts CPU_ data types to be independent of the CPU and compiler used and many more functions uC LIB is of a series of source files that provide common functions such as memory copy string and ASCII related functions Some are occasionally used to replace stdlib functions provided by the compiler The files are provided to ensure that they are fully portable from application to application and especially from compiler to compiler uC OS III does not use these files but uC CPU does Some compilers provide extensi
160. and can access the shared resource So what happened here is that the priority of Task H has been reduced to that of Task L since it waited for the resource that Task L owned The trouble begins when Task M preempted Task L further delaying the execution of Task H This is called an unbounded priority inversion It is unbounded because any medium priority can extend the time Task H has to wait for the resource Technically if all medium priority tasks have known worst case periodic behavior and bounded execution times the priority inversion time is computable This process however may be tedious and would need to be revised every time the medium priority tasks change This situation can be corrected by raising the priority of Task L only during the time it takes to access the resource and restore the original priority level when the task is finished The priority of Task L should be raised up to the priority of Task H In fact uC OS III contains a special type of semaphore that does just that and is called a mutual exclusion semaphore Copyright 2015 Micrium Inc 231 uC OS III User s Manual Mutual Exclusion Semaphores uC OS III supports a special type of binary semaphore called a mutual exclusion semaphore also known as a mutex that eliminates unbounded priority inversions The figure below shows how priority inversions are bounded using a Mutex Access To Task H Shared releases Resource the Mutex 10 Task H Lo
161. ask if any of the analog inputs exceed a threshold The message sent contains information about which channel had the error an error code an indication of the severity of the error and other information Error handling in this example is centralized Other tasks or even ISRs can post error messages to the error handling task The error handling task could be responsible for displaying error messages on a monitor a display logging errors to a disk or dispatching other tasks to take corrective action based on the error Copyright 2015 Micrium Inc 322 uC OS III User s Manual 1 2 3 4 5 6 Copyright 2015 Micrium Inc Analog Error IPS eee Handling Monitoring eee SL Message Queue Anal aa na o mle D 1 NG e Ma Tae 2 p f ed G Figure Using a Memory Partition non blocking The analog inputs are read by the task The task determines that one of the inputs is outside a valid range and an error message needs to be sent to the error handler The task then obtains a memory block from a memory partition so that it can place information regarding the detected error The task writes this information to the memory block As mentioned above the task places the analog channel that is at fault an error code an indication of the severity possible solutions and more There is no need to store a timestamp in the message as time stamping is a built in feature of uC OS III so t
162. ask is pending on when the task is pending on either an event flag group a semaphore a mutual exclusion semaphore or a message queue This information is quite useful during debugging and thus this field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h Copyright 2015 Micrium Inc 108 uC OS III User s Manual Internal Tasks During initialization uC OS III creates a minimum of two 2 internal tasks OS_IdleTask and 0S_TickTask and three 3 optional tasks OS_StatTask OS_TmrTask and 0S_IntQTask The optional tasks are created based on the value of compile time defines found in os_cfg h 0S_CFG_STAT_TASK_EN enables OS_StatTask OS_CFG_TMR_EN enables OS_TmrTask 0S _CFG_ISR_POST_DEFERRED_EN enables OS_IntQTask Advanced applications may not require the Tick task or the Idle task To disable a task set its configuration option to DEF_DISABLED in os_cfg h The following configuration parameters affect the Tick and Idle tasks respectively 0S _CFG_TASK_TICK_EN OS _CFG_TASK_IDLE_EN Copyright 2015 Micrium Inc 109 uC OS III User s Manual The Idle Task If enabled 0S_IdleTask is the very first task created by uC OS IIL The priority of the idle task is always set to OS_CFG_PRIO_MAX 1 In fact OS_TdleTask is the only task that is ever allowed to be at this priority and as a safeguard when other tasks are created OSTaskCreate ensures that there are no other tasks
163. ate unbounded priority inversions Accesses to a mutex can be nested and therefore a task can acquire the same mutex up to 250 times Of course the mutex owner needs to release the mutex an equal number of times Nested task suspension uC OS III allows a task to suspend itself or another task Suspending a task means that the task will not be allowed to execute until the task is resumed by another task Suspension can be nested up to 250 levels deep In other words a task can suspend another task up to 250 times Of course the task must be resumed an equal number of times for it to become eligible to run on the CPU Software timers You can define any number of one shot and or periodic timers Timers are countdown counters that perform a user definable action upon counting down to 0 Each timer can have its own action and if a timer is periodic the timer is automatically reloaded and the action is executed every time the countdown reaches zero Pend on multiple objects uC OS III allows an application to wait i e pend on multiple events at the same time Specifically a task can wait on multiple semaphores and or message queues to be posted The waiting task wakes up as soon as one of the events occurs Task Signals uC OS III allows an ISR or task to directly signal a task This avoids having to create an intermediate kernel object such as a semaphore or event flag just to signal a task and results in better performance
164. ave a separate exception stack In most cases the position can be fairly close to amp MyTaskStk Copyright 2015 Micrium Inc uC OS III User s Manual Stack RAM Low Memory amp MyTaskStk 0 StkLimitPtr SP Current Stack Stack Growth Usage amp MyTaskStk N 1 High Memory CPU_STK gt Figure Hardware detection of stack overflows As a reminder the location of the StkLimitPtr is determined by the stk_limit argument passed to OSTaskCreate when the task is created as shown below OS_TCB MtTaskTCB CPU_STK MyTaskStk 1000 OSTaskCreate amp MyTaskTCB MyTaskName MyTask amp MyTaskArg MyPrio amp MyTaskStk Stack base address yf 100 Used to set StkLimitPtr to trigger exception if at stack usage gt 90 af 1000 Total stack size in CPU_STK elements i MyTaskQSize MyTaskTimeQuanta void MY_TASK_OPT amp err Listing stk_limit ie StkLimitPtr as passed to OSTaskCreate Of course the value of StkLimitPtr used by the CPU s stack overflow detection hardware needs to be changed whenever uC OS III performs a context switch This can be tricky because the value of this register may need to be changed so that it first points to NULL then the Copyright 2015 Micrium Inc 83 uC OS III User s Manual CPU s stack pointer is changed and finally the value of the stack checking register is set to the value saved in the TCB s S
165. between a task and an ISR because an ISR cannot wait on a semaphore Figure Bilateral Rendezvous Copyright 2015 Micrium Inc 265 uC OS III User s Manual The code for a bilateral rendez vous is shown in the listing below Of course a bilateral rendez vous can use two separate semaphores but the built in task semaphore makes setting up this type of synchronization quite straightforward OS_TCB MyTask1_TCB OS_TCB MyTask2_TCB void Task1 void p_arg OS_ERR err CPU_TS ts while DEF_ON OSTaskSemPost amp MyTask2_TCB 1 OS_OPT_POST_NONE amp err Check err OSTaskSemPend 2 OS_OPT_PEND_BLOCKING amp ts amp err Check err void Task2 void p_arg OS_ERR err CPU_TS ts while DEF_ON OSTaskSemPost amp MyTask1_TCB 3 OS_OPT_POST_NONE amp err Check err OSTaskSemPend 4 OS_OPT_PEND_BLOCKING amp ts amp err Check err Listing Tasks synchronizing their activities 1 Task 1 is executing and signals Task 2 s semaphore 2 Task 1 pends on its internal semaphore to synchronize with Task 2 Because Task 2 has not executed yet Task 1 is blocked waiting on its semaphore to be signaled Copyright 2015 Micrium Inc 266 uC OS III User s Manual uC OS III context switches to Task 2 3 Task 2 executes and signals Task 1 s semaphore 4 Since it has already been signaled Task 2 is now sync
166. btain a memory block from the desired partition A pointer to the allocated memory block is returned This is similar to malloc except that the memory block comes from a pool that is guaranteed to not fragment Also it s assumed that your application knows the size of each block so it doesn t overflow the block with data 3 It is important to examine the returned error code to ensure that there are free memory blocks and that the application can start putting content in the memory blocks Copyright 2015 Micrium Inc 320 uC OS III User s Manual Returning a Memory Block to a Partition The application code must return an allocated memory block back to the proper partition when finished You do this by calling OSMemPut as shown in the listing below The code assumes that the partition was already created OS_MEM MyPartition 1 1 2 3 4 Copyright 2015 Micrium Inc CPU_INT 8U MyDataBlkPtr void MyTask void p_arg OS_ERR err while DEF_ON OSMemPut OS_MEM amp MyPartition 2 void MyDataBlkPtr 3 OS_ERR amp err if err OS_ERR_NONE 4 You properly returned the memory block to the partition Listing Returning a memory block to a partition The memory partition control block must be accessible by all tasks or ISRs that will be using the partition You simply call OSMemPut to return the memory block back to the memory partition Note tha
167. case When a mutex is declared you simply use 0S_MUTEX as the data type of the variable used to declare the mutex The structure starts with a Type field which allows it to be recognized by uwC OS III as a mutex Other kernel objects will also have a Type as the first member of the structure If a function is passed a kernel object wC OS III will be able to confirm that it is being passed the proper data type assuming OS_CFG_OBJ_TYPE_CHK_EN is set to DEF_ENABLED in os_cfg h For example if passing a message queue 0S_Q to a mutex service for example OSMutexPend wC OS III will recognize that the application passed an invalid object and return an error code accordingly Each kernel object can be given a name to make them easier to recognize by debuggers or uC Probe This member is simply a pointer to an ASCII string which is assumed to be NUL terminated Because it is possible for multiple tasks to wait or pend on a mutex the mutex object contains a pend list as described in Pend Lists To propagate the correct priority to the owning tasks and because a task can own more than one mutex wC OS II has to track which mutex is owned by which tasks 237 uC OS III User s Manual 6 Ifthe mutex is owned by a task it will point to the os_TcB of that task 7 wC OS ILI allows a task to acquire the same mutex multiple times In order for the mutex to be released the owner must release the mutex the same nu
168. conds after the product powers up In this case you would specify 0S_OPT_TIME_MATCH while dly actually corresponds to the desired value of OSTickCtr you want to reach However you should use the 0S_OPT_TIME_MATCH with care because somewhere else in your code you can change the value of OSTickCtr by calling OSTimeSet as described in Time Management To summarize the task will wake up when osTickctr reaches the following value Value of opt Task wakes up when Copyright 2015 Micrium Inc 189 uC OS III User s Manual OS_OPT_TIME_DLY OSTickCtr dly OS_OPT_TIME_PERIODIC OSTCBCurPtr gt TickCtrPrev dly OS_OPT_TIME_MATCH dly OSTimeDIyHMSM Delay a Task for a Specified Time If enabled a task may call this function to suspend execution until some time expires by specifying the length of time in a more user friendly way Specifically you can specify the delay in hours minutes seconds and milliseconds thus the HMsM This function only works in Relative mode The listing below indicates how to use OSTimeD1yHMSM void MyTask void p_arg OS_ERR err while DEF_ON OSTimeDlyHMSM 1 1 OS_OPT_TIME_HMSM_STRICT 2 amp err 3 Check err Listing OSTimeDlyHMSMQ 1 The first four arguments specify the amount of time delay in hours minutes seconds and milliseconds from this point in time In the above example the task should delay for 1 second The reso
169. configuration constant OS_CFG_TMR_TASK_RATE_HZ which is expressed in Hertz Hz So if the timer task described later rate is set to 10 all timers have a resolution of 1 10th of a second ticks in the diagrams to follow In fact this is the typical recommended value for the timer task Timers are to be used with coarse granularity uC OS III provides a number of services to manage timers as summarized in the table below Copyright 2015 Micrium Inc 194 uC OS III User s Manual Function Name Operation OSTmrCreate Create and specify the operating mode of the timer OSTmrDel Delete a timer OSTmrRemainGet Obtain the remaining time left before the timer expires OSTmrStart Start or restart a timer OSTmrStateGet Obtain the current state of a timer OSTmrStop Stop the countdown process of a timer Table Timer API summary A timer needs to be created before it can be used You create a timer by calling OSTmrCreate and specify a number of arguments to this function based on how the timer is to operate Once the timer operation is specified its operating mode cannot be changed unless the timer is deleted and recreated The function prototype for OSTmrCreate is shown below as a quick reference void OSTmrCreate OS_TMR p_tmr Pointer to timer A CPU_CHAR p_name Name of timer ASCII OS_TICK dly Initial delay OS_TICK period Repeat period OS_OPT opt Options lt i OS_TMR_CALLBA
170. consistent coding conventions used it is simple to predict the functions to call for the services required and even predict which arguments are needed For example a pointer to an object is always the first argument and a pointer to an error code is always the last one Preemptive multitasking uC OS III is a preemptive multi tasking kernel and therefore uC OS III always runs the most important ready to run task Round robin scheduling of tasks at equal priority uC OS III allows multiple tasks to run at the same priority level When multiple tasks at the same priority are ready to run and that priority level is the most important level uC OS III runs each task for a user specified time called a time quanta Each task can define its own time quanta and a task can also give up the CPU to another task at the same priority if it does not require the full time quanta Low interrupt disable time uC OS II has a number of internal data structures and variables that it needs to access atomically To ensure this uC OS III is able to protect these critical Copyright 2015 Micrium Inc 20 uC OS III User s Manual regions by locking the scheduler instead of disabling interrupts Interrupts are therefore disabled for very little time This ensures that uC OS II is able to respond to some of the fastest interrupt sources Deterministic Interrupt response with uC OS II is deterministic Also execution times of most services provided by uC
171. d simply restore the saved CPU registers 7 Perform a return from interrupt to resume the interrupted task Copyright 2015 Micrium Inc 164 uC OS III User s Manual All Interrupts Vector to a Common Location Even though an interrupt controller is present in most designs some CPUs still vector to a common interrupt handler and the ISR queries the interrupt controller to determine the source of the interrupt At first glance this might seem silly since most interrupt controllers are able to force the CPU to jump directly to the proper interrupt handler It turns out however that with uC OS IIL it s easy to have the interrupt controller vector to a single ISR handler Listing 9 4 describes the sequence of events to be performed when the interrupt controller forces the CPU to vector to a single location An interrupt occurs 1 The CPU vectors to a common location 2 The ISR code performs the ISR prologue 3 The C handler performs the following 4 while there are still interrupts to process 5 The a 2 3 4 5 Copyright 2015 Micrium Inc Get vector address from interrupt controller Call interrupt handler ISR epilogue is executed 6 Listing Single interrupt vector for all interrupts An interrupt occurs from any device The interrupt controller activates the interrupt pin on the CPU If there are other interrupts that occur after the first one the interrup
172. d in acquiring and releasing the semaphore consumes valuable CPU time You can perform the job more efficiently by disabling and enabling interrupts however there is an indirect cost to disabling interrupts even higher priority tasks that do not share the specific resource are blocked from using the CPU Suppose for instance that two tasks share a 32 bit integer variable The first task increments the variable while the second task clears it When considering how long a processor takes to perform either operation it is easy to see that a semaphore is not required to gain exclusive access to the variable Each task simply needs to disable interrupts before performing its operation on the variable and enable interrupts when the operation is complete A semaphore should be used if the variable is a floating point variable and the microprocessor does not support hardware floating point operations In this case the time involved in processing the floating point variable may affect interrupt latency if interrupts are disabled Semaphores are subject to a serious problem in real time systems called priority inversion which is described in Priority Inversions Copyright 2015 Micrium Inc 224 uC OS III User s Manual Semaphore Internals As previously mentioned a semaphore is a kernel object as defined by the 0S_SEM data type which is derived from the structure os_sem see os h as shown in the listing below The services provided by uC OS
173. d only if OS_CFG_TMR_EN is set to DEF_ENABLED in os_cfg h Message Pool OSMsgPool NbrFree Copyright 2015 Micrium Inc 385 uC OS III User s Manual The variable indicates the number of free 0S_MSGs in the message pool This number should never be zero since that indicate that the application is no longer able to send messages This variable is declared only if OS_CFG_Q_EN is set to DEF_ENABLED Or OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h OSMsgPool NbrUsed This variable indicates the number of 0S_MSGs currently used by the application This variable is declared only if 0S_CFG_Q_EN is set to DEF_ENABLED or OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h OSMsgPool NbrUsedMax This variable indicates the maximum i e peak number of OS_MSGs that was ever used by the application and is reset by oSstatReset This variable is declared only if OS_CFG_Q EN is set to DEF_ENABLED or OS_CFG_TASK_Q_EN is Set to DEF_ENABLED in os_cfg h Ready List OSRdyList i NbrEntries These variable are used to examine how many entries there are in the ready list at each priority Scheduler OSSchedLockTimeMax This variable indicates the maximum amount of time the scheduler was locked irrespective of which task did the locking It represents the global scheduler lock time This value is expressed in CPU_TS units The variable is declared only if OS_CFG_SCHED LOCK_TIME_MEAS EN is set to DEF_ENABLED in os _cfg h OSSchedLockTimeMa
174. d the figure that follows shows an array of 0S_PEND_DATA elements Copyright 2015 Micrium Inc 306 uC OS III User s Manual OS_OBJ_QTY OSPendMulti OS_PEND_DATA p_pend_data_tbl 1 OS_OBJ_QTY tbl_size 2 OS_TICK timeout 3 OS_OPT opt 4 OS_ERR p err 5 1 Copyright 2015 Micrium Inc Listing OSPendMulti prototype 0 NextPtr TCBPtr PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS 1 TCBPtr PendObjptr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS 2 NextPtr TCBPtr PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS I N 41 __ProvPtr NextPtr _TCBPtr_ PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize RdyTS OS_PEND_DATA ri Figure Array of OS_PEND_DATA OSPendMulti is passed an array of OS_PEND_DATA elements The caller must instantiate an array of OS_PEND_DATA The size of the array depends on the total number of kernel objects that the task wants to pend on For example if the task wants to pend on three semaphores and two message queues then the array contains five OS_PEND_DATA elements as shown below OS_PEND_DATA my_pend_multi_tb1 5 The calling task needs to initialize the Pendobjptr of each element of the array to point to each of the objects to be pended on For example OS_SEM MySem1 OS_SEM MySem2 OS_SEM MySem3 OS_Q MyQ1 OS_Q MyQ2 void MyTask void OS_ERR err OS_PEND_DATA my_pend_multi_tb1 5 while DEF_ON my_pend_multi_tb1 Pen
175. d worry about the next 0S_TcB in the list three ticks later OSTickListDly NbrEntries 2 NbrUpdated TCB_Ptr TickListPtr TickListPtr 0 TickPrevPtr TickNoxtPtr P TickPrevPtr TickNextPtr 0 Second Task Inserted First Task Inserted 7 ticks to expiration OS_TCB OS_TC B 10 ticks to expiration ____________ gt Figure Inserting a second task in the delayed tasks tick list When the tick task executes see OS_TickTask in os_tick c it starts by incrementing OSTickCtr and if the delayed tasks list is not empty decrements only the TickRemain of the OS_TCB at the head of the list When TickRemain reaches zero the OS_TCB is removed from the list and placed in the ready list Then the TickRemain field of the next 0S_TCB is examined and if the TickRemain field for that task is also zero that task is also placed in the ready list uC OS II continues like this until the TickRemain of an OS_TCB has a non zero value or it reaches the end of the list Copyright 2015 Micrium Inc 116 uC OS III User s Manual The NbrUpdated field of the tick list contains the number of 0S_TCBs removed from the list whenever a tick occurs Of course if TickRemain is non zero NbrUpdated would also be zero because on that specific tick no task would be made ready to run The list of tasks that are waiting for timeouts works exactly the same as the delayed task list The reason there are two lists is to r
176. dObjPtr OS_PEND_OBJ amp MgS em1 my_pend_multi_tbl 1 PendObjPtr OS_PEND_OBJ amp MySem2 307 uC OS III User s Manual 2 3 4 5 6 my_pend_multi_tb1 2 PendObjPtr my_pend_multi_tb1 3 PendObjPtr OS_PEND_OBJ amp MyQ1 my_pend_multi_tb1l 4 PendObjPtr OS_PEND_OBJ amp MyQ2 OSPendMulti OS_PEND DATA amp my pend_multi_tb1 OS_OBJ_QTY 5 OS_PEND_0BJ amp MySem3 i OS_TICK o OS_OPT OS_OPT_PEND_BLOCKING OS_ERR amp err Check err This argument specifies the size of the OS_PEND_DATA table In the above example this is 5 You specify whether or not to timeout in case none of the objects are posted within a certain amount of time A non zero value indicates the number of ticks to timeout Specifying zero indicates the task will wait forever for any of the objects to be posted The opt argument specifies whether to wait for objects to be posted you would set opt to OS_OPT_PEND_BLOCKING or not block if none of the objects have already been posted you would set opt to OS_OPT_PEND_NON_BLOCKING As with most uC OS II function calls you specify the address of a variable that will receive an error code based on the outcome of the function call See Appendix A uC OS III API Reference for a list of possible error codes As always it is highly recommended to examine the error return code Note that all objects are cast to OS_PEND_OBJ data types W
177. e OS_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg h FlagsRdy This field contains the event flags that were posted and that the task was waiting on In other words it allows a task to know which event flags made the task ready to run This field only exists in a TCB if event flags services are enabled at compile time OS_CFG_FLAG_EN is Set to DEF_ENABLED in os_cfg h FlagsOpt When a task pends on event flags this field contains the type of pend pend on any event flag bit specified in FlagsPend or all event flag bits specified in FlagsPend This field only exists in a TCB if event flags services are enabled at compile time 0S_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg h There can be up to eight main values as shown below plus add on options Possible values are OS_OPT_PEND_FLAG_CLR_ALL OS_OPT_PEND_FLAG_CLR_ANY OS_OPT_PEND_FLAG_CLR_AND OS_OPT_PEND_FLAG_CLR_OR OS_OPT_PEND_FLAG_SET_ALL OS_OPT_PEND_FLAG_SET_ANY OS_OPT_PEND_FLAG_SET_AND OS_OPT_PEND_FLAG_SET_OR Copyright 2015 Micrium Inc 104 uC OS III User s Manual You can also add OS_OPT_PEND_FLAG CONSUME and either OS_OPT_PEND_BLOCKING or OS_OPT_PEND_NON_BLOCKING to the above options SuspendCtr This field is used by OSTaskSuspend and OSTaskResume to keep track of how many times a task is suspended Task suspension can be nested When SuspendCctr is 0 all suspensions are removed This field only exists in a TCB if task suspension is enabled at compile
178. e the critical section may be protected through the use of a preemption lock Within uC OS III the critical section access method depends on which ISR post method is used by interrupts see Interrupt Management If 0S_CFG_ISR_POST_DEFERRED_EN is Set to DEF_DISABLED see os_cfg h then pC OS III will disable interrupts when accessing internal critical sections If O0S_CFG_ISR_POST_DEFERRED_EN is set to DEF_ENABLED then uC OS HMI will lock the scheduler when accessing most of its internal critical sections Interrupt Management discusses how to select the method to use uC OS III defines one macro for entering a critical section and two macros for leaving OS_CRITICAL_ENTER OS_CRITICAL_EXIT and OS_CRITICAL_EXIT_NO_SCHED These macros are internal to wC OS III and must not be invoked by the application code However if you need to access critical sections in your application code consult Resource Management Copyright 2015 Micrium Inc uC OS III User s Manual Disabling Interrupts When setting OS_CFG_ISR_POST_DEFERRED_EN to DEF_DISABLED uC OS III will disable interrupts before entering a critical section and re enable them when leaving the critical section OS_CRITICAL_ENTER invokes the uC CPU macro CPU_CRITICAL_ENTER that in turn calls CPU_SR_Save CPU_SR_Save is a function typically written in assembly language that saves the current interrupt disable status and then disables interrupts The saved interrupt d
179. e CPU s natural word size Also the priority resolution algorithm can easily be written in assembly language to benefit from special instructions such as bit set and clear as well as count leading zeros CLZ or find first one FF1 instructions Deadlock prevention All of the uC OS III pend services include timeouts which help avoid deadlocks Tick handling at task level The clock tick manager in wC OS III is accomplished by a task that receives a trigger from an ISR Handling delays and timeouts by a task greatly reduces interrupt latency Also wC OS III uses a hashed delta list mechanism which further reduces the amount of overhead in processing delays and timeouts of tasks User definable hooks uC OS III allows the port and application programmer to define hook functions which are called by wC OS III A hook is simply a defined function that allows the user to extend the functionality of uwC OS III One such hook is called during a context switch another when a task is created yet another when a task is deleted etc Timestamps For time measurements uwC OS III requires that a 16 bit or 32 bit free running counter be made available This counter can be read at run time to make time measurements of Copyright 2015 Micrium Inc 23 uC OS III User s Manual certain events For example when an ISR posts a message to a task the timestamp counter is automatically read and saved as part of the message posted Wh
180. e current task is suspended until it again becomes the highest priority task that is ready to run The operations described above are summarized using the pseudo code shown in the listing below OS_SEM MySem 1 void main void OS_ERR err OSInit amp err OSSemCreate amp MySem 2 My Semaphore 3 iy 4 amp err 5 Check err Create task s OsStart amp err void err Listing Using a semaphore to access a shared resource Copyright 2015 Micrium Inc 215 uC OS III User s Manual 1 2 3 4 5 The application must declare a semaphore as a variable of type 0S_SEM This variable will be referenced by other semaphore services You create a semaphore by calling OSSemCreate and pass the address to the semaphore allocated in 1 The semaphore must be created before it can be used by other tasks Here the semaphore is initialized in startup code i e main however it could also be initialized by a task but it must be initialized before it is used You can assign an ASCII name to the semaphore which can be used by debuggers or uC Probe to easily identify the semaphore Storage for the ASCII characters is typically in ROM which is typically more plentiful than RAM If it is necessary to change the name of the semaphore at runtime you can store the characters in an array in RAM and simply pass the address of the array to OSSemCreate Of course the
181. e market approval PMA for medical devices and IEC 61508 for industrial controls Compliance with such standards is critical within industry segments however the certifications also have value for engineers in other industries as they evidence reliability documentation and time to market advantages beneficial to any design As the decade came to a close I still worked full time at Dynalco and experienced difficulty keeping up with the demand for the operating system I felt obligated to respond to each uC OS II user that contacted me and the flow of messages into my inbox was unrelenting Since I could no longer treat the operating system as a side project I made the decision to found my own software company In September 1999 Micrium officially came into being Copyright 2015 Micrium Inc 10 uC OS III User s Manual Micrium comes from the word Micro for microprocessors or microcontrollers and ium which means the Universe of and thus Micrium means the Universe of Microprocessors as seen through the eyes of software In the months before incorporating Micrium I began working on a second edition of the uC OS II book which made its debut in November 1999 and was accompanied by a new version of the kernel Two major features to the operating system were added event flags and mutual exclusion semaphores These new features fully described in the book were heartily welcomed by uC OS II users The book itself was
182. e module e g Sem and then the operation performed by the function For example OSSemPost indicates that the function belongs to the OS C OS IID that it is part of the Semaphore services and specifically that the function performs a Post i e signal operation This allows all related functions to be grouped together in the reference manual and makes those services intuitive to use You should notice that signaling or sending a message to a task is called posting and waiting for a signal or a message is called pending In other words an ISR or a task signals or sends a message to another task by using 0S Post where is the type of service Sem TaskSem Flag Mutex Q and TaskQ Similarly a task can wait for a signal or a message by calling OS Pend Copyright 2015 Micrium Inc uC OS III User s Manual Directories and Files uC OS III is fairly easy to use once it is understood exactly which source files are needed to make up a uC OS III based application This chapter will discuss the modules available for uC OS III and how everything fits together The figure below shows the wC OS III architecture and its relationship with hardware Of course in addition to the timer and interrupt controller hardware would most likely contain such other devices as Universal Asynchronous Receiver Transmitters UARTs Analog to Digital Converters ADCs Ethernet controller s and more This chapter assumes development on a Wi
183. e number of priority levels is kept low the search is quite fast In fact there are several optimizations to streamline the search For example if using a 32 bit processor and you are satisfied with limiting the number of different priority levels to 64 the above code can be optimized as shown in the listing below In fact some processors have built in Count Leading Zeros instructions and thus the code can even be written with just a few lines of assembly language instead of C Remember that with uwC OS II 64 priority levels does not mean that the user is limited to 64 tasks since with wC OS II any number of tasks are possible at a given priority level except and OS_CFG_PRIO_MAX 1 OS_PRIO OS _PrioGetHighest void OS_PRIO prio if OSPrioTb1 OS_PRIO_BITMAP prio OS_CntLeadZeros OSPrioTb1 else prio OS_CntLeadZeros OSPrioTbl 1 32 return prio Listing Finding the highest priority level within 64 levels Copyright 2015 Micrium Inc 130 uC OS III User s Manual About the Ready List Tasks that are ready to run are placed in the Ready List As shown in the figure below the ready list is an array OSRdyList containing OS_CFG_PRIO_MAX entries with each entry defined by the data type 0S_RDY_LIST see os h An OS_RDY_LIST entry consists of three fields Entries TailPtr and HeadPtr Entries contains the number of ready to run tasks at the priority level corresponding to the
184. e quanta on a per task basis One task could have a time quanta of 1 tick another 12 another 3 and yet another 7 etc The time quanta of a task is specified when the task is created The time quanta of a task may also be changed at run time through the function OSTaskTimeQuantaSet Copyright 2015 Micrium Inc 143 uC OS III User s Manual Scheduling Internals Scheduling is performed by two functions OSSched and OSIntExit OSSched is called by task level code while OSIntExit is called by ISRs Both functions are found in os_core c The figure below illustrates the two sets of data structures that the scheduler uses the priority ready bitmap and the ready list as described in The Ready List OSPrioTbi OSRdyList OSRdyList 0 HO OU L OU 0 OU O OSRdyList OS_CFG_PRIO_MAX 2 seis Tike OSRdyList OS_CFG_PRIO_MAX 1 LI OS_TCBs Figure Priority ready bitmap and Ready list OS_SchedRoundRobin When the time quanta for a task expires and there are multiple tasks at the same priority uC OS III will select and run the next task that is ready to run at the current priority OS_SchedRoundRobin is the code used to perform this operation OS_SchedRoundRobin is either called by OSTimeTick or OS_IntQTask OS_SchedRoundRobin is found in os_core c OS_SchedRoundRobin is called by OSTimeTick if you selected the Direct Method of posting see Interrupt Management 0S_SchedRoundRobin is called by 0S_
185. e should implement CPU_SR_Save and CPU_SR_Restore Copyright 2015 Micrium Inc 339 uC OS III User s Manual CPU_SR_Save CPU_SR_Save reads the current value of the CPU status register where the current interrupt disable flag resides and returns this value to the caller However before returning CPU_SR_Save must disable all interrupts CPU_SR_Save is actually called by the macro CPU_CRITICAL_ENTER CPU_SR_Restore CPU_SR_Restore restores the CPU s status register to a previously saved value CPU_SR_Restore is called from the macro CPU_CRITICAL_EXIT Copyright 2015 Micrium Inc 340 uC OS III User s Manual uC OS IIl Port Porting uC OS III The table following the figure below below shows the name of uC OS III files and where they are typically found For the purpose of demonstrating how to do a port we will assume the generic 32 bit processor as described in Context Switching and shown in the figure below lt 4 32bit gt RO po R1 R2 R3 R4 R5 R6 R7 h R8 a R9 R10 SR Link Register LR Task Stack Pointer TSP ISR Stack Pointer ISP Program Counter PC Status Register SR Figure Generic 32 bit CPU Our generic CPU contains 16 integer registers RO to R15 a separate ISR stack pointer and a separate status register SR Every register is 32 bits wide and each of the 16 integer registers can hold either data or an address The return addres
186. e task in CPU_TS units This variable is declared only when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h Copyright 2015 Micrium Inc 391 uC OS III User s Manual PendOn This variable indicates what a task is pending on if the task is in a pend state Possible values are e 0 Nothing 1 Pending on an event flag group e 2 Pending on the task s message queue e 3 Pending on multiple objects e 4 Pending on a mutual exclusion semaphore e 5 Pending on a message queue e 6 Pending on a semaphore e 7 Pending on a task s semaphore Prio This corresponds to the priority of the task This might change at run time depending on whether or not the task owns a mutual exclusion semaphore or the user changes the priority of the task by calling OSTaskChangePrio SchedLockTimeMax This variable keeps track of the maximum time a task locks the scheduler in CPU_TS units This variable allows the application to see how each task affects task latency The variable is declared only when 0S_CFG_SCHED_LOCK_TIME_MEAS_EN is set to DEF_ENABLED in os_cfg h SemPendTime This variable indicates the amount of time it took for a task or ISR to signal the task in Copyright 2015 Micrium Inc 392 uC OS III User s Manual CPU_TS units This variable is declared only when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h SemPendTimeMax This variable indicates the maximum amount of time it took for a task or an ISR to si
187. e task could also be suspended by another task As one might expect the suspension must be removed by another task or the same task that suspended it in the first place and the event needs to either occur or timeout while waiting for the event 94 uC OS III User s Manual Task Control Blocks A task control block TCB is a data structure used by kernels to maintain information about a task Each task requires its own TCB and for uC OS III the user assigns the TCB in user memory space RAM The address of the task s TCB is provided to uC OS II when calling task related services i e OSTask functions The task control block data structure is declared in os h as shown in the listing below Note that the fields are actually commented in os h and some of the fields are conditionally compiled based on whether or not certain features are desired Both are not shown here for clarity Also it is important to note that even when the user understands what the different fields of the 0S_TCB do the application code must never directly access these especially change them In other words oS_TcB fields must only be accessed by uC OS III and not the code Copyright 2015 Micrium Inc 95 uC OS III User s Manual struct os_tcb CPU_STK void CPU_STK OS_TCB OS_TCB OS_TCB OS_TCB OS_TICK_LIST OS_CHAR CPU_STK OS_TLS OS_TASK_PTR void OS_PEND_DATA OS_STATE OS_STATUS OS_STATE OS_PRIO OS_PRIO OS_MUTEX CPU_STK_SIZE OS_
188. e timestamp timer is incremented at a rate of 1 MHz then this function would return 1000000 CPU_TS_TmrFreqSet CPU_TS_TmrFreqSet is a function that needs to be called by the application code to notify uC CPU about the increment frequency of the timer used for timestamps In other words if the timestamp timer is incremented at a rate of 1 MHz then your application code would need to call CPU_TS_TmrFregSet and pass 1000000 CPU_TS_Get32 CPU_TS_Get32 is a function that returns a 32 bit timestamp The macro 0S_TS_GET see os_cpu h generally maps to this function Copyright 2015 Micrium Inc 335 uC OS III User s Manual cpu_core h This header file is required by cpu_core c to define function prototypes The table below shows the name of uC CPU template files you should use as a starting point should you decide to start a wC CPU port from scratch It s highly recommended that you copy these files to folders that matches the layout shown in this table You would then edit these files to build up your own uC CPU port files Again refer to the uC CPU User s Manual uC CPU Manual pdf found in Micrium Software uC CPU Doc File Directory cpu h Micrium Software uC CPU Template cpu_c c Micrium Software uC CPU Template cpu_a asm Micrium Software uC CPU Template Table uC CPU template files cpu h Many CPUs have different word lengths and cpu h declares a series of type definitions that ensure portability Speci
189. e to continuously power down and power up the product just to maintain the system tick Since uC OS III is a preemptive kernel an event other than a tick interrupt can wake up a system placed in low power mode by either a keystroke from a keypad or other means Not having a system tick means that the user is not allowed to use time delays and timeouts on system calls This is a decision required to be made by the designer of the low power product Copyright 2015 Micrium Inc 177 uC OS III User s Manual Dynamic Tick A uC OS III based system using the Dynamic Tick feature needs a programmable timer that can cause and interrupt after a given delay measured in OS ticks Unlike the periodic tick source this timer is programmed to interrupt the CPU after a variable amount of time but needs to be an integral multiple of the tick period This variable amount of time is called the Tick Step The Tick Step is determined every time a task needs to delay its execution or to pend on a kernel object with a timeout The Tick Step is defined as the smallest amount of time the kernel needs to sleep before running the Tick task which is used to wake up the task with the smallest delay or pend timeout For example if a task needs to sleep for one second the Tick task can be run in one second It does not need to run at a fixed interval until one second has elapsed However this assumes that the timer used for the Dynamic tick doesn t overflow during the wait p
190. eased If you specify OS_OPT_PEND_NON_BLOCKING as the option the application does not want the task to block OSSemPend returns immediately to the caller and the returned error code indicates that the semaphore is unavailable You use this option if the task does not want to wait for the resource to be available and would prefer to do something else and check back later If you specify the 0S_OPT_PEND_BLOCKING option the calling task will be inserted in the list of tasks waiting for the semaphore to become available The task is inserted in the list by priority order and therefore the highest priority task waiting on the semaphore is 227 uC OS III User s Manual 2 3 Copyright 2015 Micrium Inc at the beginning of the list If you specify a non zero timeout the task will also be inserted in the tick list A zero value for a timeout indicates that the user is willing to wait forever for the semaphore to be released Most of the time you would specify an infinite timeout when using the semaphore in resource sharing Adding a timeout may temporarily break a deadlock however there are better ways of preventing deadlock at the application level e g never hold more than one semaphore at the same time resource ordering etc Assuming blocking the scheduler is called since the current task is no longer able to run it is waiting for the semaphore to be released The scheduler will then run the next highest priority tas
191. eatly depends on how many timers expire and how long each of the callback functions takes to execute Since the callbacks are provided by the application code they have a large influence on the execution time of the timer task The timer callback functions must never wait on events because this would delay the timer task for excessive amounts of time if not forever e Callbacks should execute as quickly as possible Timer List uC OS III applications may require many timers The timer manager implements a simple linear list where each timer is linked in a doubly linked list as shown in the figure below OSTmrListEntries 1 OSTmrListPtr o L o OSTmrTickCtr 3 Figure Empty Timer List 1 OSTmrListEntries contains the current number of entries in the list This variable is updated whenever timers are added or removed from the list 2 OSTmrListPtr contains a pointer to a doubly linked list of timers that the timer manager will need to update 3 OSTmrTickCtr is incremented by 0S_TmrTask every time the tick ISR signals the task This counter basically keeps track of the number of times the timer task has been signaled Copyright 2015 Micrium Inc 203 uC OS III User s Manual Timers are inserted in the timer list by calling OSTmrStart and a timer must be created before it can be used Newly created timers are always inserted at the beginning of the list as shown in the figure following the code list
192. eb bdo deh fda a na e 399 120 5 0scigapp c Statie 24 Meter y ghee gis tae Peet ee Se ete ate bedi 410 uC OS III User s Manual uC OS III User Manual uC OS III is a highly portable ROMable scalable preemptive real time deterministic multitasking kernel for microprocessors microcontrollers and DSPs Copyright 2015 Micrium Inc uC OS III User s Manual Preface What is pC OS III uC OS III pronounced Micro C O S Three is a scalable ROMable preemptive real time kernel that manages an unlimited number of tasks uC OS III is a third generation kernel and offers all of the services expected from a modern real time kernel such as resource management synchronization inter task communications and more However uC OS II offers many unique features not found in other real time kernels such as the ability to complete performance measurements at run time to directly signal or send messages to tasks achieve pending on multiple kernel objects and more Why a new uC OS version The uC OS series first introduced in 1992 has undergone a number of changes over the years based on feedback from thousands of people using and deploying its evolving versions uC OS III is the sum of this feedback and experience Rarely used uC OS II features were eliminated and newer more efficient features and services were added Probably the most common request was to add round robin scheduling which was not possible for wC OS II but i
193. educe the amount of time in a critical section Dynamic Tick uC OS III offers a mode where the Tick task is not run periodically but behaves as it does In other words as far as your application is concerned it will not know the difference The benefit of this mode come apparent when you are concerned about power consumption such as with battery operated devices Dynamic Tick mode has the advantage of not waking up the Tick task unless it has to Without Dynamic Tick if a task needs to sleep for one second as done by calling OSTimeDlyHMSM and OS_CFG_TICK_RATE_HZ is set to 1000 the Tick task would run 999 times for nothing before finally waking up the delayed task on it s 1000th run This can impose a large overhead in terms of power usage The standard method used for the Tick task is to wake up OS_CFG_TICK_RATE_HZ times per second by the Tick ISR Then the tick task increments OSTickCtr by one and updates the timeout and delay tick lists reading all tasks that have an expired delay or timeout It would be far more efficient to actually run the Tick task once the 1 second delay has elapsed In order to support this new mode we had to make some changes to the way the Tick task and ISR interact with each other In the Dynamic ticking mode the Tick task is awakened when the smallest needed delay of any tasks of either tick lists has elapsed This minimum delay called the Tick Step is calculated every time a task needs to be delayed ever
194. ement as semaphores were also discussed in that chapter However the material presented here will be applicable to semaphores used for synchronization and thus will differ somewhat A counting semaphore allows values between 0 and 255 65 535 or 4 294 967 295 depending on whether the semaphore mechanism is implemented using 8 16 or 32 bits respectively For uC OS III the maximum value of a semaphore is determined by the data type 0S_SEM_CTR see os_type h which can be changed as needed Along with the semaphore s value uwC OS HI keeps track of tasks waiting for the semaphore s availability Copyright 2015 Micrium Inc 255 uC OS III User s Manual The application programmer can create an unlimited number of semaphores limited only by available RAM Semaphore services in wC OS III start with the osSem prefix and services available to the application programmer are described in uC OS III API Reference Semaphore services are enabled at compile time by setting the configuration constant OS_CFG_SEM_EN to DEF_ENABLED in os_cfg h Semaphores must be created before they can be used by the application The second listing below shows how to create a semaphore As previously mentioned a semaphore is a kernel object as defined by the 0S_SEM data type which is derived from the structure os_sem see os h as shown in the listing below The services provided by uC OS III to manage semaphores are implemented in the file os_se
195. emented as follows OS_CTX_SAVE MACRO PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH ENDM RO R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 Listing OS_CTX_SAVE assuming generic 32 bit CPU OS_CTX_RESTORE This macro is used to reverse the process done by 0S_CTX_SAVE In other words 0S_CTX_RESTORE loads the CPU registers from the stack in the reverse order Copyright 2015 Micrium Inc 362 uC OS III User s Manual OS_CTX_RESTORE Restore all the CPU registers from the new task s stack in the reverse order that they were in OSTaskStkInit Listing OS_CTX_SAVE macro Pseudo Code Assuming our generic 32 bit CPU 0S_CTX_RESTORE would be implemented as follows OS_CTX_RESTORE MACRO POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP R7 POP R6 POP R5 POP R4 POP R3 POP R2 POP R1 POP RO ENDM Listing OS_CTX_RESTORE assuming generic 32 bit CPU OS_ISR_ENTER This macro allows you to simplify your assembly language ISRs 0S_ISR_ENTER is basically the first line of code you would add to the ISR The pseudo code for 0S_ISR_ENTER is shown below OS_ISR_ENTER OS_CTX_SAVE OSIntNestingCtr if OSIntNestingCtr 1 OSTCBCurPtr gt StkPtr SP Listing OS_ISR_ENTER macro Pseudo Code Assuming our generic 32 bit CPU 0S_ISR_ENTER would be implemented as follows You should note that the C like code would actually be implemented in assembly language Copy
196. en a message is sent to the message queue the highest priority task waiting on the message queue Copyright 2015 Micrium Inc 285 uC OS III User s Manual receives the message Optionally the sender can broadcast a message to all tasks waiting on the message queue In this case if any of the tasks receiving the message from the broadcast has a higher priority than the task sending the message or interrupted task if the message is sent by an ISR C OS III will run the highest priority task that is waiting Notice that not all tasks must specify a timeout some tasks may want to wait forever OSQCreate OSQDel osariush Message Queue OSQPendAbort OSQPost OSQPend A OSQPost x osaPend Timeout OSQPend O 0 Figure Multiple tasks waiting on a message queue Copyright 2015 Micrium Inc 286 uC OS III User s Manual Task Message Queue It is fairly rare to find applications where multiple tasks wait on a single message queue Because of this a message queue is built into each task and the user can send messages directly to a task without going through an external message queue object This feature not only simplifies the code but is also more efficient than using a separate message queue object The message queue that is built into each task is shown in the figure below OSTaskQFlush Fa OSTaskQPendAbor OSTaskQPost a i OSTaskQPend OSTaskQPost N x x N Message Tim
197. en the recipient receives the message the timestamp is provided to the recipient and by reading the current timestamp the time it took for the message to be received can be determined Built in support for Kernel Awareness debuggers This feature allows kernel awareness debuggers to examine and display uC OS III variables and data structures in a user friendly way The kernel awareness support in uC OS III can be used by uC Probe to display this information at run time Object names Each uC OS III kernel object can have a name associated with it This makes it easy to recognize what the object is assigned to You can thus assign an ASCII name to a task a semaphore a mutex an event flag group a message queue a memory partition and a timer The object name can have any length but must be NUL terminated Copyright 2015 Micrium Inc uC OS III User s Manual uC OS uC S II and uC S III Features Comparison The table below shows the evolution of uC OS over the years comparing the features available in each version Copyright 2015 Micrium Inc 25 uC OS III User s Manual Feature uC OS pC OS II gt yC OS III Year introduced 1992 1998 2009 Book Yes Yes Yes Source code available Yes Yes Yes Preemptive Multitasking Yes Yes Yes Maximum number of 64 255 Unlimited tasks Number of tasks at 1 1 Unlimited each priority level Round Robin No No Yes Scheduling Semaphores Yes Yes Yes Mutual Exclusion No Yes Yes Nes
198. end OSTaskSemPost OSTaskSemPendAbort OSTaskQPend OSTaskQPost OSTaskQPendAbort OSTaskQFlush Table Task Management Services A complete description of all uwC OS III task related services is provided in uC OS III API Reference Copyright 2015 Micrium Inc 88 uC OS III User s Manual Task Management Internals Task States From a uC OS III user point of view a task can be in any one of five states as shown in the figure below Internally uC OS III does not need to keep track of the dormant state and the other states are tracked slightly differently The actual uC OS III states will be discussed after a discussion on task states from the user s point of view The figure below also shows which uC OS III functions are used to move from one state to another The diagram is actually simplified as state transitions are a bit more complicated than this Copyright 2015 Micrium Inc 89 uC OS III User s Manual casas o behn OSFlagPendAbort Opdit 0 sesadmans OSTaskDel ee 0 OSTaskQPend coer 0 caer e OSQPendAbort eames s OSQPost OSSemDel OSSemPendAbort OSSemPost OSTaskQPendAbort OSTaskQPost OSTaskSemPendAbort OSTaskSemPost OSTaskResume OSTimeDlyResume OSTimeTick OSTaskCreate OSTaskDel OSIntExit Interrupted 5 OSTaskDel Figure Five basic states of a task 1 The Dormant state corre
199. eof OSCfg_TickTaskStk This variable indicates the RAM footprint in bytes of the wC OS III tick task stack ROM Variable Data Type Value oscfg DataSizeRAM CPU_INT32U Total of all configuration RAM This variable indicates the RAM footprint in bytes of all of the configuration variables declared in os_cfg_app c Copyright 2015 Micrium Inc 411
200. eout Seg R Figure Task message queue Task message queue services in C OS III start with the OSTaskQ prefix and services available to the application programmer are described in uC OS III API Reference Setting OS_CFG_TASK_Q_EN to DEF_ENABLED in os_cfg h enables task message queue services The code for task message queue management is found in os_task c You use this feature if the code knows which task to send the message s to For example if receiving an interrupt from an Ethernet controller you can send the address of the received packet to the task that will be responsible for processing the received packet Copyright 2015 Micrium Inc 287 uC OS III User s Manual Bilateral Rendez vous Two tasks can synchronize their activities by using two message queues as shown in the figure below This is called a bilateral rendez vous and works the same as with semaphores except that both tasks may send messages to each other A bilateral rendez vous cannot be performed between a task and an ISR since an ISR cannot wait on a message queue Message Queue ATM OSQPost OSQPend Timeout osapenay Message Queue ocoposti xX N x Timeout Figure Bilateral Rendez vous In a bilateral rendez vous each message queue holds a maximum of one message Both message queues are initially created empty When the task on the left reaches the rendez vous point it sends a message to the top message queue and waits for a messa
201. ep abreast of the latest developments in the high tech world the focus is on solving engineers problems and providing a solid and complete infrastructure rather than on how to prematurely exploit emerging trends This philosophy has yielded considerable success Micrium now in its 14th year is a highly respected embedded software provider Industry surveys consistently show the operating systems to be among the most popular in the embedded space My goal has always been and Copyright 2015 Micrium Inc 11 uC OS III User s Manual continues to be to provide effective solutions for the same types of problems that I confronted at Dynalco and that millions of embedded systems developers continue to face today Acknowledgements First and foremost I d like to thank my loving and caring wife Manon for her unconditional support encouragement understanding and patience This project was again a huge undertaking and I could not have done it without her I would also like to thank many fine people at Micrium who have tested the code and reviewed the documentation In alphabetic order e Brian Nagel e Eric Shufro e Hong Soong e Freddy Torres A special thanks to Frank Voorburg from Feaser and to Ian Hall and Robert Mongrain from Renesas for feedback and corrections to the text to Michael Barr for sharing his real life RTOS experiences and to Carolyn Mathas for the incredible job of editing this huge project A very special
202. epends on the task stack requirements Stack space may be allocated dynamically by using the C compiler s heap management function i e malloc as shown below However care must be taken with fragmentation If creating and deleting tasks the process of allocating memory might not be able to provide a stack for the task s because the heap will eventually become fragmented For this reason allocating stack space dynamically in an embedded system is typically allowed but once allocated stacks should not be deallocated Said another way it s fine to create a task s stack from the heap as long as you don t free the stack space back to the heap 78 uC OS III User s Manual Assigning Task Priorities Sometimes task priorities are both obvious and intuitive For example if the most important aspect of the embedded system is to perform some type of control and it is known that the control algorithm must be responsive then it is best to assign the control task s a high priority while display and operator interface tasks are assigned low priority However most of the time assigning task priorities is not so cut and dry because of the complex nature of real time systems In most systems not all tasks are considered critical and non critical tasks should obviously be given low priorities An interesting technique called rate monotonic scheduling RMS assigns task priorities based on how often tasks execute Simply put tasks with t
203. er must be unlocked a number of times equal to the number of locks A task gives up its time quanta by calling osschedRoundRobinYield This assumes that the task is running alongside with other tasks at the same priority and the currently running task decides that it can give up its time quanta and let another task run The user calls osSched The application code can call oSSched to run the scheduler This only makes sense if calling 0S Post functions and specifying O0S_OPT_POST_NO_SCHED so that multiple posts can be accomplished without running the scheduler on every post However in the above situation the last post can be a post without the 0S_OPT_POST_NO_SCHED option Copyright 2015 Micrium Inc 141 uC OS III User s Manual Round Robin Scheduling When two or more tasks have the same priority wC OS III allows one task to run for a predetermined amount of time called a Time Quanta before selecting another task This process is called Round Robin Scheduling or Time Slicing If a task does not need to use its full time quanta it can voluntarily give up the CPU so that the next task can execute This is called Yielding uC OS III allows the user to enable or disable round robin scheduling at run time The figure below shows a timing diagram with tasks running at the same priority There are three tasks that are ready to run at priority X For sake of illustration the time quanta occurs every 4th clock tick This is
204. erating system in their spare time many engineers used the software commercially in complex and demanding projects Comments and suggestions from uC OS users helped me to continue to refine and evolve the operating system For several years only minor changes were made to uC OS However when R amp D asked me to write a second edition I decided that a substantial update of both the operating system and the book was warranted The updated operating system became uC OS II A quick glance at the uwC OS II files revealed that this operating system was different from uC OS Whereas all of the processor independent code incorporated by uC OS was contained in a single C file wC OS II spanned multiple files each corresponding to one of the operating system s services uC OS II also offered many features that its predecessor lacked including stack checking capabilities hook functions and a safe means to dynamically allocate memory Copyright 2015 Micrium Inc uC OS III User s Manual To fully describe all of the new operating system s features I nearly doubled the size of the book Just as the latest version of the software received a new name the new edition became MicroC OS II The Real Time Kernel Micro was used in place of u because titles incorporating Greek letters posed problems for many book retailers Unlike my first text the new book would be a hardcover MicroC OS II The Real Time Kernel was released
205. eriod For example you could not set a 16 bit timer to delay for one second if this timer is clocked at 1 MHz because the timer would overflow after 65 536 ms In this case you might want to set the tick step to 50 ms and thus load the timer with a count of 50 000 For a delay of 1 second you would then get 20 Dynamic tick interrupts The ISR executed by the Dynamic tick interrupt calls the function OSTimeDynTick instead of OSTimeTick The Dynamic tick ISR passes the amount OS Ticks that have elapsed since the last Dynamic tick interrupt to the OSTimeDynTick function By opposition the OSTimeTick function always assumes that the amount of OS Ticks that have elapsed is one The OSTimeDynTick function accomplishes the same work as OSTimeTick but uses a variable OS Tick increment The Tick Task page describes the execution of the Tick task in Periodic and Dynamic modes of operation Note that to use the Dynamic Tick feature the uC OS III port developer has to implement the Dynamic Tick API described in wC OS III Port and OS_CFG_DYN_TICK_EN needs to be set to DEF_ENABLED in os_cfg h Copyright 2015 Micrium Inc 178 uC OS III User s Manual Pend Lists A task is placed in a Pend List also called a Wait List when it is waiting on a semaphore to be signaled a mutual exclusion semaphore to be released an event flag group to be posted or a message queue to be posted See For Kernel Object Resource Management Semaphores O
206. ero OS_CRITICAL_EXIT decrements OSSchedLockNestingCtr and when the value reaches zero invokes the scheduler OS_CRITICAL_EXIT_NO_SCHED also decrements OSSchedLockNestingCtr but does not invoke the scheduler when the value reaches zero The code for the macros is shown in the listing below define OS_CRITICAL_ENTER CPU_CRITICAL_ENTER OSSchedLockNestingCtr CPU_CRITICAL_EXIT AE gt lh define OS CRITICAL_EXIT CPU_CRITICAL_ENTER OSSchedLockNestingCtr if OSSchedLockNestingCtr OS_NESTING_CTR CPU_CRITICAL_EXIT OSSched else CPU_CRITICAL_EXIT FR Nn Se NN ga oh define OS_CRITICAL_EXIT_NO_SCHED CPU_CRITICAL_ENTER OSSchedLockNestingCtr CPU_CRITICAL_EXIT AT E Listing Critical section code Locking the Scheduler Copyright 2015 Micrium Inc uC OS III User s Manual Measuring Scheduler Lock Time uC OS III provides facilities to measure the amount of time the scheduler is locked This is done by setting the configuration constant 0S_CFG_SCHED_LOCK_TIME_MEAS_EN to DEF_ENABLED in os_cfg h The measurement is started each time the scheduler is locked and ends when the scheduler is unlocked The measurement keeps track of two values a global scheduler lock time and a per task scheduler lock time It is therefore possible to know how long each task locks the scheduler allowing the user to better optimize code The per task scheduler l
207. errupt latency would be relatively small If multiple tasks are not created at the same priority use the interrupt disable method If multiple tasks are waiting on different events going through all of the tasks waiting for events requires a fair amount of processing time which means longer critical sections If only a few tasks approximately one to five are waiting on an event flag group the critical section would be short enough to use the interrupt disable method Pending on multiple objects is probably the most complex feature provided by uC OS III requiring interrupts to be disabled for fairly long periods of time should the interrupt disable method be selected If pending on multiple objects it is highly recommended that the user select the scheduler lock method If the application does not use this feature the interrupt disable method is an alternative uC OS III disables interrupts while processing a post to multiple tasks in a broadcast When not using the broadcast option you can use the interrupt disable method Table Disabling interrupts or locking the Scheduler Copyright 2015 Micrium Inc 70 uC OS III User s Manual About Task Management The design process of a real time application generally involves splitting the work to be completed into tasks each responsible for a portion of the problem uC OS III makes it easy for an application programmer to adopt this paradigm A task also called a thread
208. es Especially important for uwC OS III is the definition of the CPU_STK data type which sets the width of a stack entry Specifically is the width of data pushed to and popped from the stack 8 bits 16 bits 32 bits or 64 bits CPU_SR defines the data type for the processor s status register SR that generally holds the interrupt disable status The CPU_TS is a time stamp used to determine when an operation occurred or to measure the execution time of code cpu h also declares macros to disable and enable interrupts CPU_CRITICAL_ENTER and CPU_CRITICAL_EXIT respectively The documentation in the template file explains how to declare these macros cpu h is also where you need to define configuration constants Copyright 2015 Micrium Inc 337 uC OS III User s Manual CPU_CFG_ENDIAN_TYPE This define specifies whether your CPU is a little endian machine or a big endian machine cpu_def h offers the following choices CPU_ENDIAN_TYPE_BIG CPU_ENDIAN_TYPE_LITTLE CPU_CFG_ADDR SIZE This define specifies the size of an address for the processor in number of bytes cpu_def h offers the following choices CPU_WORD_SIZE_ 8 CPU_WORD_SIZE_16 CPU_WORD_SIZE_32 CPU_WORD_SIZE_64 CPU_CFG_DATA SIZE This define specifies the natural data width of the processor in number of bytes cpu_def h offers the following choices CPU_WORD_SIZE_ 8 CPU_WORD_SIZE_16 CPU_WORD_SIZE_32 CPU_WORD_SIZE_64 CPU_DATA
209. es indivisibly or atomically whenever there is possible preemption Time of day variables are considered shared resources and any code that accesses those variables must have exclusive access through what is called a critical section wC OS III provides services to protect shared resources and enables the easy creation of critical sections Copyright 2015 Micrium Inc 207 uC OS III User s Manual CPU_INT 8U Hours CPU_INT 8U Minutes CPU_INT 8U Seconds void TimeOfDay void p_arg OS_ERR err void amp p_arg while DEF_ON OSTimeD1yHMSM 1 OS_OPT_TIME_HMSM_STRICT amp err Examine err to make sure the call was successful Seconds if Seconds gt 59 Seconds Minutes 3 if Minutes gt 59 Minutes Hours 3 if Hours gt 23 Hours Listing Faulty Time Of Day clock task The most common methods of obtaining exclusive access to shared resources and to create critical sections are e disabling interrupts e disabling the scheduler using semaphores using mutual exclusion semaphores a k a a mutex The mutual exclusion mechanism used depends on how fast the code will access a shared resource as shown in the table below Copyright 2015 Micrium Inc 208 uC OS III User s Manual Resource Sharing Method Disable Enable Interrupts Locking Unlocking the Scheduler Semaphores Mutual Exclusion Semaphores Copyright
210. esource Management a semaphore is a protocol mechanism offered by most multitasking kernels Semaphores were originally used to control access to shared resources However better mechanisms exist to protect access to shared resources Semaphores are best used to synchronize an ISR to a task or synchronize a task with another task as shown in the figure below Note that the semaphore is drawn as a flag to indicate that it is used to signal the occurrence of an event The initial value for the semaphore is typically zero 0 indicating the event has not yet occurred The value N next to the flag indicates that the semaphore can accumulate events or credits An ISR or a task can post or signal multiple times to a semaphore and the semaphore will remember how many times it was posted It is possible to initialize the semaphore with a value other than zero indicating that the semaphore initially contains that number of events Also the small hourglass close to the receiving task indicates that the task has an option to specify a timeout This timeout indicates that the task is willing to wait for the semaphore to be signaled or posted to within a certain amount of time If the semaphore is not signaled within that time uC OS III resumes the task and returns an error code indicating that the task was made ready to run because of a timeout and not the semaphore was signaled OSSemCreate OSSemDel OSSemPendAbort OSSemPost
211. essage queue used by the task and compile the application code with 0S_CFG_TASK_Q_EN set to DEF_ENABLED The differences between using message queues and the task s message queue will be explained Copyright 2015 Micrium Inc 299 uC OS III User s Manual OS_TCB RPM_TCB 1 OS_STK RPM_Stk 1000 CPU_INT32U DeltaCounts CPU_INT32U CurrentCounts CPU_INT32U PreviousCounts void main void OS_ERR err OSInit amp err void OSTaskCreate OS_TCB amp RPM_TCB 2 CPU_CHAR RPM Task OS_TASK_PTR RPM_Task void O OS_PRIO 10 CPU_STK amp RPM_Stk Q CPU_STK_SIZE 100 CPU_STK_SIZE 1000 OS_MSG_QTY 10 OS_TICK e void e OS_OPT OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR OS_ERR amp err OsStart amp err void RPM_ISR void OS_ERR err Clear the interrupting from the sensor CurrentCounts Read the input capture DeltaCounts CurrentCounts PreviousCounts PreviousCounts CurrentCounts OSTaskQPost OS_TCB amp RPM_TCB 3 void DeltaCounts OS_MSG_SIZE sizeof DeltaCounts OS_OPT OS_OPT_POST_FIFO OS_ERR amp err void RPM_Task void p_arg CPU_INT32U delta OS_ERR err OS_MSG_SIZE size CPU_TS ts DeltaCounts 0 PreviousCounts Q CurrentCounts while DEF_ON delta CPU_INT32U OSTaskQPend OS_TICK OS_CFG_TICK_RATE 10 4 OS_OPT OS_OPT_PEND_BLOCKING OS_MSG SIZE amp size CPU_TS amp ts
212. et don Doe eee ee eae eae Cad 230 1 14 4 Mutual Exclusion Semaphores 0 0 ccc ccc ete ene ence nee 232 1 14 4 1 Mutual Exclusion Semaphore Internals 0 0 0 cee cece eee eee nee 237 1 14 5 Should You Use a Semaphore Instead of a Mutex 0 0 0 243 1 146 Deadlocks sc3 ei ice tek eee De Ea th A aN wt AEA ER E e iS 244 LAS Synchronization sess ge gave geek eee oa Wee de Desi Sek Gears died SHR eS a eae Seeds Cees 247 FAS V Semaphores sisotssss wise de tsb ees Sate age ce beta a ee ae eo 248 115 2 Fask Semaphore aisan ea ete AA aie eh bite ba dole aba ica nates 262 1 15 3 EventFlags sc tiea ouia eka eo hadi Gaede Pan Gee is peed Gael Dae ee Hedge ees 268 1 15 4 Synchronizing Multiple Tasks 2 2 2 ee cc cece eect eens 281 T 16 Message Passing aimore Pio bald ia aA rege oe aden gavel Golan cals Rea ee 283 1 161 Messages 3 02 6 5084 Secreted E Ga EE pee Be HOP See ae EEE bed Bens Hoke 284 116 2 Message Quetes sia e ie Seaton tage ee Res ee a DRE ST a oki bat MARL we A 285 1 16 3 Fask Message Queue va o oe eiee e kene Soon ben Hed She Hee bowed edwin ete ene coe 287 1 16 4 Bilateral Rendez Vous 1 2 o 82 cc ena Ga ate teh a Bia de ik dent eee e e 288 1 16 5 FlOw Control cicg iisa dca teed dake esc hehe Se he gaa a stage eed eee eas 290 1 16 6 Keeping the Datain Scope 0 0 cece cece ete e eee nent n nee 292 1 16 7 Using M ssage Queues sumce ticie si iiei Sond COR ee Ce bh Shoe Pa tee ae 2
213. eue or increasing the priority of the receiving task The first application task is created The listing below shows how to create other tasks once multitasking as started Copyright 2015 Micrium Inc 60 uC OS III User s Manual static void AppTaskStart void p_arg 1 2 Copyright 2015 Micrium Inc OS ERR err p_arg p_arg BSP_Init CPU_Init BSP_OS_TickInit OSTaskCreate OS_TCB amp AppTask1_TCB 1 CPU_CHAR App Task 1 OS_TASK_PTR AppTask1 void 0 OS_PRIO 5 CPU_STK amp AppTask1_Stk CPU_STK_SIZE CPU_STK_SIZE 128 OS_MSG QTY Q OS_TICK e void 0 OS_OPT OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR OS_ERR amp err OSTaskCreate OS_TCB amp AppTask2_TCB 2 CPU_CHAR App Task 2 OS_TASK_PTR AppTask2 void 0 OS_PRIO 6 CPU_STK amp AppTask2_Stk CPU_STK_SIZE CPU_STK_SIZE 128 OS_MSG QTY Q OS_TICK o void 0 OS_OPT OS_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR OS_ERR amp err BSP_LED_Off while 1 BSP_LED_Toggle OSTimeDlyHMSM CPU_INT16U CPU_LINT16U CPU_LINT16U 2 CPU_INT32U 100 OS_OPT OS_OPT_TIME_HMSM_STRICT OS_ERR amp err Listing app c 3rd Part Task 1 is created by calling OSTaskCreate If this task happens to have a higher priority than the task that creates it wC OS II will immediately start Task 1 If the created task has a
214. f a task for n ticks OSTimeD1lyHMSM Delay a task for a user specified time in HH MM SS mmm OSTimeDlyResume Resume a delayed task OSTimeGet Obtain the current value of the tick counter OSTimeSet Set the tick counter to a new value OSTimeTick Signal the occurrence of a clock tick Table Time Services API summary The application programmer should refer to uC OS HI API Reference for a detailed description of these services OSTimeDly Delay a Task A task calls this function to suspend execution until some time expires The calling function will not execute until the specified time expires This function allows three modes relative periodic and absolute The listing below shows how to use OSTimeD1y in relative mode Copyright 2015 Micrium Inc 185 uC OS III User s Manual void MyTask void p_arg 1 2 3 4 OS_ERR err while DEF_ON OSTimeDly 2 1 0S_OPT_TIME_DLY 2 amp err 3 Check err 4 Listing OSTimeDly Relative The first argument specifies the amount of time delay in number of ticks from when the function is called For the example above if the tick rate OS_CFG_TICK_RATE_HZ in os_cfg_app h is set to 1000 Hz the user is asking to suspend the current task for approximately 2 milliseconds However the value is not accurate since the count starts from the next tick which could occur almost immediately This will be explained sh
215. facts You can determine the interrupt latency interrupt response interrupt recovery and task latency by adding the execution times of the code involved for each as shown below Interrupt Latency Maximum interrupt disable time Copyright 2015 Micrium Inc 172 uC OS III User s Manual Interrupt Response Interrupt latency Vectoring to the interrupt handler ISR prologue Interrupt Recovery Handling of the interrupting device Posting a signal or a message to a task OSIntExit OSIntCtxSw Task Latency Interrupt response Interrupt recovery Time scheduler is locked The execution times of the uwC OS HI ISR prologue ISR epilogue OSIntExit and OSIntCtxSw can be measured independently and should be fairly constant It should also be easy to measure the execution time of a post call by using 0S_TS_GET In the Direct Post Method the scheduler is locked only when handling timers and therefore task latency should be fast if there are few timers with short callbacks expiring at the same time See Timer Management wC OS III is also able to measure the amount of time the scheduler is locked providing task latency Copyright 2015 Micrium Inc 173 uC OS III User s Manual Direct vs Deferred Post Method In the Direct Post Method uC OS III disables interrupts to access critical sections In comparison while in the Deferred Post Method uC OS III locks the scheduler to access the sa
216. fically we don t use the C data types int short long char etc at Micrium Instead clearer data types are defined Consult your compiler documentation to determine whether the standard declarations described below need to be changed for the CPU compiler you are using You should note that the typedefs below are not all grouped together in cpu h and also cpu h contains additional comments about these data types Copyright 2015 Micrium Inc 336 uC OS III User s Manual typedef void CPU_VOID typedef unsigned char CPU_CHAR typedef unsigned char CPU_BOOLEAN typedef unsigned char CPU_INT 8U typedef signed char CPU_INT 8S typedef unsigned short CPU_INT16U typedef signed short CPU_INT16S typedef unsigned int CPU_INT32U typedef signed int CPU_INT32S 1 2 3 typedef unsigned long long CPU_INT64U typedef signed long long CPU_INT64S typedef float CPU_FP32 typedef double CPU_FP64 typedef volatile CPU_INT 8U CPU_REGQ8 typedef volatile CPU_INT16U CPU_REG16 typedef volatile CPU_INT32U CPU_REG32 typedef volatile CPU_INT64U CPU_REG64 typedef void CPU_FNCT_VOID void typedef void CPU_FNCT_PTR void typedef CPU_INT32U CPU_ADDR typedef CPU_INT32U CPU_DATA typedef CPU_DATA CPU_ALIGN typedef CPU_ADDR CPU_SIZE_T typedef CPU_INT32U CPU_STK 1 typedef CPU_ADDR CPU_STK_SIZE typedef CPU_INT16U CPU_ERR typedef CPU_INT32U CPU_SR 2 typedef CPU_INT32U CPU_TS 3 Listing uC CPU Data Typ
217. for When waiting for the event to occur the task does not consume CPU time When the event occurs the task is placed back into the ready list and wC OS III decides whether the newly readied task is the most important ready to run task If this is the case the currently running task will be preempted placed back in the ready list and the newly readied task is given control of the CPU In other words the newly readied task will run immediately if it is the most important task Note that the OSTaskSuspend function unconditionally blocks a task and this task will not actually wait for an event to occur but in fact waits until another task calls OSTaskResume to make the task ready to run Assuming that CPU interrupts are enabled an interrupting device will suspend execution of a task and execute an Interrupt Service Routine ISR ISRs are typically events that tasks wait for Generally speaking an ISR should simply notify a task that an event occurred and let the task process the event ISRs should be as short as possible and most of the work of handling the interrupting devices should be done at the task level where it can be managed by uC OS III ISRs are only allowed to make Post calls i e OSFlagPost OSQPost OSSemPost OSTaskQPost and OSTaskSemPost The only post call not allowed to be made from an ISR is OSMutexPost since mutexes as will be addressed later are assumed to be services that are only accessible at
218. from the list This field is useful when debugging and serves no other purpose otherwise This field is only present when OS_CFG DBG_EN is set to 1 inos_cfg h 4 The NbrUpdated field in each list contains the number of 0S_TCBs updated whenever a tick occurs This field is useful when debugging and serves no other purpose otherwise This field is only present when 0S_CFG_DBG_EN is set to 1 in os_cfg h 5 The TCB_List contains a pointer to a doubly linked list of 0s_TcBs that are placed in the list Copyright 2015 Micrium Inc 114 uC OS III User s Manual 6 OSTickCtr is incremented by 0S_TickTask each time the task is signaled by the tick ISR osTickctr simply keeps track of the number of ticks since startup and its value can be ready by calling oSTimeGet or changed by calling oSTimeSet Tasks are automatically inserted in the proper tick list when the application programmer calls a OSTimeDly function or when an 0S Pend call is made with a non zero timeout value If the users application does not need time delays or timeouts the user can remove the Tick Task from uC OS HII see the wC OS III Configuration Manual for more information Example Using an example to illustrate the process of inserting a task in the delayed tick list Here we assume that the OSTickListD1ly list is completely empty as shown in the figure below A task is placed in the tick list when OSTimeD1ly is called and let s assume OSTi
219. fy the ASCII string to parse and a list of token delimiters As soon as the function finds the first token it returns The function remembers where it was last so when called again it can extract additional tokens which is clearly non reentrant The use of an infinite loop is more common in embedded systems because of the repetitive Copyright 2015 Micrium Inc 72 uC OS III User s Manual work needed in such systems reading inputs updating displays performing control operations etc This is one aspect that makes a task different than a regular C function Note that one could use a while 1 or for to implement the infinite loop since both behave the same The one used is simply a matter of personal preference At Micrium we like to use while DEF_ON The infinite loop must call a uC OS III service i e function that will cause the task to wait for an event to occur It is important that each task wait for an event to occur otherwise the task would be a true infinite loop and there would be no easy way for other lower priority tasks to execute This concept will become clear as more is understood regarding uwC OS III void MyTask void p_arg Local variables Lyf Do something with p_arg W Task initialization ay while DEF_ON Task body as an infinite loop Cy Task body do work ayi Must call one of the following services Ef If OSFlagPend Cy le OSMutexPe
220. fy that it is willing to wait a certain amount of time for the event to occur If the event is not posted within that time the task is readied then the task is notified that a timeout occurred Again the pend terminates when the event occurs i e a task or an ISR performs a post the object awaited is deleted or another task decides to abort the pend A task can suspend itself or another task by calling oSTaskSuspend The only way the task is allowed to resume execution is by calling OSTaskResume Suspending a task means that a task will not be able to run on the CPU until it is resumed If a task suspends itself then it must be resumed by another task A delayed task can also be suspended by another task In this case the effect is additive In other words the delay must complete or be resumed by OSTimeDlyResume and the suspension must be removed by another task which would call OSTaskResume in order for the task to be able to run A task waiting on an event to occur may be suspended by another task Again the effect is additive The event must occur and the suspension removed by another task in order for the task to be able to run Of course if the object that the task is pending on is deleted or the pend is aborted by another task then one of the above two condition is removed The suspension however must be explicitly removed A task can wait for an event but only for a certain amount of time and th
221. ge to arrive on the bottom message queue Similarly when the task on the right reaches its rendez vous point it sends a message to the message queue on the bottom and waits for a message to arrive on the top message queue The figure below shows how to use task message queues to perform a bilateral rendez vous Copyright 2015 Micrium Inc 288 uC OS III User s Manual Figure Figure Bilateral Rendez vous with task message queues Copyright 2015 Micrium Inc 289 uC OS III User s Manual Flow Control Task to task communication often involves data transfer from one task to another One task produces data while the other consumes it However data processing takes time and consumers might not consume data as fast as it is produced In other words it is possible for the producer to overflow the message queue if a higher priority task preempts the consumer One way to solve this problem is to add flow control in the process as shown in the figure below Message Queue AT OSQPost OSOPend OSSemPend OSSemPost N Figure Producer and consumer tasks with flow control Here a counting semaphore is used initialized with the number of allowable messages that can be sent by the consumer If the consumer cannot queue more than 10 messages the counting semaphore contains a count of 10 As shown in the pseudo code of the listing below the producer must wait on the semaphore before it is allowed to send a message
222. gister saved onto the task s stack The program counter PC or R15 and status register SR are the first registers saved onto the stack In fact these are saved automatically by the CPU when an exception or interrupt occurs assuming interrupts are enabled while the other registers are pushed onto the stack by software in the exception handler The stack pointer SP or R14 is not actually saved on the stack but instead is saved in the task s OS_TCB The interrupt stack pointer points to the current top of stack for the interrupt stack which is a Copyright 2015 Micrium Inc 148 uC OS III User s Manual different memory area When an ISR executes the processor uses R14 as the stack pointer for function calls and local arguments Task Stack Pointer TSP Top Of Interrupt Stack Stack Pointer ISP Program Counter High Memory Address Status Register Figure CPU register stacking order of ready task There are two types of context switches one performed from a task and another from an ISR The task level context switch is implemented by the code in osctxSw which is actually invoked by the macro 0S_TASK_SW A macro is used as there are many ways to invoke OSCtxSw such as software interrupts trap instructions or simply calling the function The ISR context switch is implemented by oSIntctxsw The code for both functions is typically written in assembly language and is found in a file called os_cp
223. gnal the task in CPU_TS units This variable is declared only when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h State This variable indicates the current state of a task The possible values are e 0 Ready e 1 Delayed e 2 Pending 3 Pending with Timeout e 4 Suspended e 5 Delayed and Suspended e 6 Pending and Suspended 7 Pending Delayed and Suspended StkFree This variable indicates the amount of stack space in number of stack entries unused by a task This value is determined by the statistic task if 0S_CFG_TASK_STAT_STK_CHK_EN is set Copyright 2015 Micrium Inc 393 uC OS III User s Manual to DEF_ENABLED inos cfg h StkUsed This variable indicates the maximum stack usage in number of stack entries of a task This value is determined by the statistic task if OS_CFG_TASK_STAT_STK_CHK_EN is set to DEF_ENABLED inos_cfg h TickRemain This variable indicates the amount of time left in clock ticks until a task time delay expires or the task times out waiting on a kernel object such as a semaphore message queue or other This value is actually a relative value based on the position of the OS_TCB in the delta list In other words TickRemain does not contain the actual count left Copyright 2015 Micrium Inc 394 uC OS III User s Manual Kernel Object Run Time It is possible to examine the run time values of certain kernel objects as described in the following topics
224. has one entry in its pend list Therefore the PrevPtr and NextPtr both point to NULL OSPendMulti links back each OS_PEND_DATA entry to the task that is waiting on the two semaphores The figure below is a more complex example where one task is pending on two semaphores while another task also pends on one of the two semaphores The examples presented so far only show semaphores but they could be combinations of semaphores and message queues Copyright 2015 Micrium Inc 311 uC OS III User s Manual OS_SEM TailPtr i ifi Type Hea TS OS_PEND_DATA 0 0 TCBPtr OS_SEM E PendObjPtr Type RdyObjPtr RdyMsoPtr TailPtr RdyMsgSize RdyTS t ifi 1 wo le TCBPtr T3 PendObjPtr RdyObjPtr RdyMsgPtr RdyMsgSize PendDataTbiPtr PendDataTblEntries 2 OS_TCB High Priority Task Figure Tasks pending on semaphores OS_PEND_DATA o TCBPtr m AAA Z 2 PendObjPtr RdyMsgPtr RdyMsgSize RdyTS PendDataTbiPtr PendDataTblEntries 1 OS_TCB Low Priority Task When either an ISR or a task signals or sends a message to one of the objects that the task is pending on OSPendMulti returns indicating in the OS_PEND_DATA table which object was posted This is done by only filling in one of the RdyObjPtr entries the one that corresponds to the object posted Only one of the entries in the 0S_PEND_DATA table will have a RdyObjPtr with a non
225. he APIs provided with uC OS IIL As previously mentioned semaphores must be created before they can be used by an application A task waits on a semaphore before accessing a shared resource by calling OSSemPend as shown in the listing below Copyright 2015 Micrium Inc 226 uC OS III User s Manual OS_SEM MySem 1 Copyright 2015 Micrium Inc void MyTask void p_arg OS_ERR err CPU_TS ts while DEF_ON OSSemPend amp MySem 1 Pointer to semaphore Hf 10 fe Wait up until this time for the semaphore SA OS_OPT_PEND_BLOCKING Option s amp ts ie Returned timestamp of when sem was released amp err jf Pointer to Error returned E Check err JEE NC ae OSSemPost amp MySem 3 Pointer to semaphore Hf OS_OPT_POST_1 Option s always OS_OPT_POST_1 amp err if Pointer to Error returned ff Check err Listing Pending on and Posting to a Semaphore When called OSSemPend starts by checking the arguments passed to this function to make sure they have valid values assuming OS_CFG_ARG_CHK_EN is set to 1 in os_cfg h If the semaphore counter Ctr of OS_SEM is greater than zero the counter is decremented and OSSemPend returns If OSSemPend returns without error then the task now owns the shared resource If the semaphore counter is zero then another task owns the semaphore and the calling task will need to wait for the semaphore to be rel
226. he C handler only needs to call this function In both of the above cases all interrupt handlers need to be declared as follows void MyISRHandler void There is one such handler for each possible interrupt source obviously each having a unique name The while loop terminates when there are no other interrupting devices to service 6 The uC OS II ISR epilogue is executed to see if it is necessary to return to the interrupted task or switch to a more important one A couple of interesting points to note If another device caused an interrupt before the C handler had a chance to query the interrupt controller most likely the interrupt controller will capture that interrupt In fact if that second device happens to be a higher priority interrupting device it will most likely be serviced first as the interrupt controller will prioritize the interrupts The loop will not terminate until all pending interrupts are serviced This is similar to allowing nested interrupts but better since it is not necessary to redo the ISR prologue and epilogue The disadvantage of this method is that a high priority interrupt that occurs after the servicing of another interrupt that has already started must wait for that interrupt to complete before it will be serviced So the latency of any interrupt regardless of priority can be as long as it takes to process the longest interrupt One more reason to keep your ISRs sho
227. he Deferred Post method is currently DEPRECATED and will be removed in a future uwC OS III release As far as application code and ISRs are concerned these two methods are completely transparent It is not necessary to change anything except the configuration value OS_CFG_ISR_POST_DEFERRED_EN to switch between the two methods Of course changing the configuration constant will require recompiling the product and wC OS III Before explaining why to use one versus the other let us review their differences Deferred Post Method In the Deferred Post Method 0S_CFG_ISR_POST_DEFERRED_EN is set to DEF_ENABLED instead of disabling interrupts to access critical sections uwC OS HI locks the scheduler This avoids having other tasks access critical sections while allowing interrupts to be recognized and serviced In the Deferred Post Method interrupts are almost never disabled The Deferred Post Method is however a bit more complex as shown in the figure below Note that the Deferred Post method is currently DEPRECATED and will be removed in a future uC OS III release Copyright 2015 Micrium Inc uC OS III User s Manual ueue 1 3 4 2 K 1 2 3 4 Copyright 2015 Micrium Inc High Priority Task 6 i Interrupt VO O A N Interrupted uC OS III Task Disables N Interrupts wW Senge yC OS ll Locks the Scheduler Figure Deferred Post Method block diagram A dev
228. he delta counts are sent to a message queue Since a message is actually a pointer if the pointer is 32 bits wide on the processor in use you can simply cast the 32 bit delta counts to a pointer and send this through the message queue A safer and more portable approach is to dynamically allocate storage to hold the delta counts using a memory block from uC OS II s memory management services see Memory Management API Changes and send the address of the allocated memory block The counts read are then saved in Previous Counts to be used on the next interrupt Copyright 2015 Micrium Inc 295 uC OS III User s Manual 7 When the message is sent the RPM measurement task wakes up and computes the RPM as follows RPM 60 Reference Frequency Delta Counts The user may specify a timeout on the pend call and the task will wake up if a message is not sent within the timeout period This allows the user to easily detect that the wheel is not rotating and therefore the RPM is 0 8 Along with computing RPM the task can also compute average RPM maximum RPM and whether the speed is above or below thresholds etc A few interesting things are worth noting about the above example First the ISR is very short it reads the input capture and post the delta counts to the task so it can computer the time consuming math Second with the timeout on the pend it is easy to detect that the wheel is stopped Finally the task can perf
229. he following functions macros OSInit os_core c OSStartHighRdy OS_cpu_a asm OSTaskStkInit OS_cpu_c c OSCtxSw oS_cpu_a asm OS_CTX_SAVE os_cpu_a inc OS_CTX_RESTORE os_cpu_a inc CPU_SR_Save cpu_a asm CPU_SR_Restore cpu_a asm Our first test is to verify that uC OS III gets properly initialized and that the code in OSTaskStkInit properly initializes a task s stack Recall that our application consist of app c which contains the code shown below void main void OS_ERR err OSInit amp err OsStart amp err lt Set a BREAKPOINT here STEP 1 You now need to build and download this project to your target Building is obviously highly toolchain specific Of course if you encounter errors during the build you will need to resolve those before being able to move to the next step Once all build errors have been resolved you need to download the target code onto the Copyright 2015 Micrium Inc 372 uC OS III User s Manual evaluation board you selected for the tests STEP 2 You then need to set a breakpoint at the osstart line In other words have your target stop AFTER executing oSInit You should then examine the contents of err and confirm that it has the value 0S_ERR_NONE or If you get anything other than 0S_ERR_NONE the error code will tell you where the problem is see section A 20 STEP 3 If err is OS_ERR_NONE then you can Step Into osstart
230. he highest rate of execution are given the highest priority However RMS makes a number of assumptions including e All tasks are periodic they occur at regular intervals e Tasks do not synchronize with one another share resources or exchange data e The CPU must always execute the highest priority task that is ready to run In other words preemptive scheduling must be used Given a set of n tasks that are assigned RMS priorities the basic RMS theorem states that all task hard real time deadlines are always met if the following inequality holds true lt n 2 1 Where Ei corresponds to the maximum execution time of task i and Ti corresponds to the execution period of task i In other words Ei Ti corresponds to the fraction of CPU time required to execute task i The table below shows the value for size n 2 1 n 1 based on the number of tasks The upper bound for an infinite number of tasks is given by 1n 2 or 0 693 which means that you meet all hard real time deadlines based on RMS CPU usage of all time critical tasks should be less than 70 percent Note that you can still have non time critical tasks in a system and thus use close to 100 Copyright 2015 Micrium Inc 79 uC OS III User s Manual percent of the CPU s time However using 100 percent of your CPU s time is not a desirable goal as it does not allow for code changes and added features As a rule of thumb always design a system to use less th
231. he receiving task will know when the message was posted Once the message is complete it is posted to the task that will handle such error messages Of course the receiving task needs to know how the information is placed in the message Once the message is sent the analog input task is no longer allowed by convention to access the memory block since it sent it out to be processed The error handler task on the right normally pends on the message queue This task will not execute until a message is sent to it When a message is received the error handler task reads the contents of the message and 323 uC OS III User s Manual 7 performs necessary action s As indicated once sent the sender will not do anything else with the message Once the error handler task is finished processing the message it simply returns the memory block to the memory partition The sender and receiver therefore need to know about the memory partition or the sender can pass the address of the memory partition as part of the message and the error handler task will know where to return the memory block to Sometimes it is useful to have a task wait for a memory block in case a partition runs out of blocks uC OS III does not support pending on partitions but it is possible to support this requirement by adding a counting semaphore see Resource Management to guard the memory partition The initial value of the counting semaphore would be
232. he semaphore by calling osSemPost You specify the semaphore to post by passing its address The semaphore must have been previously created The next argument specifies how the task wants to post There are a number of options to choose from When you specify 0S_OPT_POST_1 you are indicating that you want to post to only one task in case there are multiple tasks waiting on the semaphore The task that will be made ready to run will be the highest priority task waiting on the semaphore If there are multiple tasks at the same priority only one of them will be made ready to run As 260 uC OS III User s Manual Copyright 2015 Micrium Inc shown in the figure below tasks waiting are in priority order HPT means High Priority Task and LPT means Low Priority Task So it is a fast operation to extract the HPT from the list If specifying OS_OPT_POST_ALL all tasks waiting on the semaphore will be posted and made ready to run The calling task can add the option 0S_OPT_POST_NO_SCHED to either of the two previous options to indicate that the scheduler is not to be called at the end of oSSemPost possibly because additional postings will be performed and rescheduling should only take place when finished This means that the signal is performed but the scheduler is not called even if a higher priority task was waiting for the semaphore to be signaled This allows the calling task to perform other post functions if needed a
233. he task See About Task Management for more details on using this feature In the code above the value represents the amount of stack space in CPU_STK elements before the stack is empty In other words in the example the limit is reached when there is 10 of the stack left The eighth argument to OSTaskCreate specifies the size of the task s stack in number of CPU_STK elements not bytes For example if you want to allocate 1 Kbyte of stack 54 uC OS III User s Manual space for a task and the CPU_STK is a 32 bit word then you need to pass 256 11 The next three arguments are skipped as they are not relevant for the current discussion The 12th argument to OSTaskCreate specifies options In this example we specify that the stack will be checked at run time assuming the statistic task was enabled in os_cfg h and that the contents of the stack will be cleared when the task is created 12 The last argument of OSTaskCreate is a pointer to a variable that will receive an error code If oSTaskCreate is successful the error code will be OS_ERR_NONE otherwise you can look up the value of the error code in os h see OS_ERR_xxxx to determine the cause of the error 13 The final step in main is to call osstart which starts the multitasking process Specifically wC OS III will select the highest priority task that was created before calling osStart You should note that the highest priority task is always 0
234. hed several kernel articles and this was just one more Convinced that my article was unique I offered it to Embedded Systems Programming The editor of this periodical likewise expressed misgivings but I convinced him that wC OS was attention worthy I explained that the operating system was comparable in quality to products that major embedded software companies offered and better than at least two I also explained that the source code for uC OS could actually be placed on the publication s bulletin board service BBS Embedded Systems Programming published a trimmed down version of the paper as a two part series Both issues generated strong responses Engineers were grateful that the inner workings of a high quality kernel were revealed and they downloaded the uC OS source code in droves kernel vendors on the other hand were less than thrilled with the article In fact the vendor of the low cost kernel was especially upset claiming that I had copied his work Imagine that I would base uC OS on software that didn t work There would soon be even more reason for the kernel vendors to be upset Shortly after my Copyright 2015 Micrium Inc uC OS III User s Manual article appeared in Embedded Systems Programming R amp D Publications publisher of C User s Journal contacted me and they were interested in printing an entire uC OS book Originally the plan for the book simply involved printing all of the material that I had
235. heduling does not occur if one specifies as part of the post call to not invoke the scheduler i e by setting the option argument to OS_OPT_POST_NO_SCHED A task calls 0STimeDly or OSTimeD1yHMSM If the delay is non zero scheduling always occurs since the calling task is placed in a list waiting for time to expire Scheduling occurs as soon as the task is inserted in the wait list and this call will always result in a context switch to the next task that is ready to run at the same or lower priority than the task that called OSTimeDly or OSTimeDlyHMSM A task waits for an event to occur and the event has not yet occurred This occurs when one of the 0S Pend functions are called The task is placed in the wait list for the event and if a non zero timeout is specified the task is also inserted in the list of tasks waiting to timeout The scheduler is then called to select the next most important task to run If a task aborts a pend A task is able to abort the wait i e pend of another task by calling 0S PendAbort Scheduling occurs when the task is removed from the wait list for the specified kernel object If a task is created The newly created task may have a higher priority than the task s creator In this case the scheduler is called If a task is deleted When terminating a task the scheduler is called if the current task is deleted If a kernel object is deleted If you delete an event flag group
236. hen called oSPendMulti first starts by validating that all of the objects specified in the OS_PEND_DATA table are either an OS_SEM or an OS_Q If not an error code is returned Next OSPendMulti goes through the 0S_PEND_DATA table to see if any of the objects have already posted If so osPendMulti fills the following fields in the table RdyobjPtr RdyMsgPtr RdyMsgSize and RdyTS RdyObjPtr Copyright 2015 Micrium Inc is a pointer to the object if the object has been posted For example if the first object in the table is a semaphore and the semaphore has been posted to 308 uC OS III User s Manual my_pend_multi_tb1 RdyObjPtr is set to my_pend_multi_tb1 PendObjPtr RdyMsgPtr is a pointer to a message if the object in the table at this entry is a message queue and a message was received from the message queue RdyMsgSize is the size of the message received if the object in the table at this entry is a message queue and a message was received from the message queue RdyTS is the timestamp of when the object posted This allows the user to know when a semaphore or message queue was posted If there are no objects posted then OSPendMulti places the current task in the wait list of all the objects that it is pending on This is a complex and tedious process for OSPendMulti since there can be other tasks in the pend list of some of these objects we are pending on To indicate how tricky
237. her or not your processor offers assembly language instructions to count the number of consecutive zeros from the left most bit position of an integer CPU_CFG_TRAIL_ZEROS_ASM_PRESENT This define specifies whether or not your processor offers assembly language instructions to count the number of consecutive zeros from the right most bit position of an integer Copyright 2015 Micrium Inc 334 uC OS III User s Manual Cpu_core c This file is generic and does not need to be changed However it must be included in all builds cpu_core c defines such functions as CPU_Init CPU_CntLeadZeros and code to measure maximum CPU interrupt disable time A few functions are explained here since they are used in uC OS III based applications CPU_Init CPU_Init must be called before calling osInit CPU_CntLeadZeros CPU_CntLeadZeros is used by the pwC OS III scheduler to find the highest priority ready task see Scheduling cpu_core c implements a count leading zeros in C However if the processor used provides a built in instruction to count leading zeros define CPU_CFG_LEAD_ZEROS_ASM_PRESENT and replace this function by an assembly language equivalent in cpu_a asm It is important to properly declare CPU_CFG_DATA_SIZE in cpu h for this function to work CPU_TS_TmrFreqGet CPU_TS_TmrFreqGet is a function that can be called by your application so it knows what the timestamp increment frequency is set to In other words if th
238. here it will wait for two ticks to expire The delayed task consumes zero CPU time while waiting for the time to expire The next tick occurs If there are HPTs waiting for this particular tick wC OS II will schedule them to run at the end of the ISR The HPTs execute 187 uC OS III User s Manual 7 The next tick interrupt occurs This is the tick that the LPT was waiting for and will now be made ready to run by uC OS II 8 Since there are no HPTs to execute on this tick uC OS III switches to the LPT 9 Given the execution time of the HPTs the time delay is not exactly two ticks as requested In fact it is virtually impossible to obtain a delay of exactly the desired number of ticks You might ask for a delay of two ticks but the very next tick could occur almost immediately after calling OSTimeD1ly Just imagine what might happen if all HPTs took longer to execute and pushed 3 and 4 further to the right In this case the delay would actually appear as one tick instead of two OSTimeDly can also be called with the 0S_OPT_TIME_PERIODIC option as shown in the listing below This option allows delaying the task until the tick counter reaches a certain periodic match value and thus ensures that the spacing in time is always the same as it is not subject to CPU load variations uC OS III determines the match value of OSTickCtr to determine when the task will need to wake up based on the desired period This is shown
239. hitectures In this chapter we will discuss the context switching process in generic terms using a fictitious CPU as shown in Figure 8 1 Our fictitious CPU contains 16 integer registers RO to R15 a separate ISR stack pointer and a separate status register SR Every register is 32 bits wide and each of the 16 integer registers can hold either data or an address The program counter or instruction pointer is R15 and there are two separate stack pointers labeled R14 and R14 R14 represents a task stack pointer TSP and R14 represents an ISR stack pointer ISP The CPU automatically switches to the ISR stack when servicing an exception or interrupt The task stack is accessible from an ISR i e we can push and pop elements onto the task stack when in an ISR and the interrupt stack is also accessible from a task Copyright 2015 Micrium Inc 147 uC OS III User s Manual 32bit gt Task Stack Pointer TSP ISR Stack Pointer ISP PR O Program Counter Figure Fictitious CPU In uwC OS III the stack frame for a ready task is always setup to look as if an interrupt has just occurred and all processor registers were saved onto it Tasks enter the ready state upon creation and thus their stack frames are pre initialized by software in a similar manner Using our fictitious CPU we ll assume that a stack frame for a task that is ready to be restored is shown in Figure 8 2 The task stack pointer points to the last re
240. hould be an empty file for now 5 The remaining files are copied from the directories shown in the listing at the top of this lt stdarg h gt lt stdio h gt lt stdlib h gt lt math h gt lt cpu h gt lt lib_def h gt lt lib_ascii h gt lt lib_math h gt lt lib_mem h gt lt lib_str h gt lt app_cfg h gt lt os_cfg_app h gt lt os_bsp h gt lt bsp h gt lt os h gt Listing Deprecated includes h example page and should not be changed at this point 6 You need to edit os_cfg h and set the following defines to the values shown below OS_CFG_ISR_POST_DEFERRED_EN OS_CFG_PRIO_MAX OS_CFG_STAT_TASK_EN OS_CFG_TMR_EN OS_CFG_SCHED_ROUNDROBIN_EN This is done to ensure that we only have two tasks in the test application 0S_IdleTask and OS_TickTask For this test you need to add one line of code in OSIdleTaskHook as shown below Once we verify OSInit OSTaskStkInit OSCtxSw OS_CTX_SAVE and OS_CTX_RESTORE we ll remove this code Copyright 2015 Micrium Inc DEF_DISABLED 32u DEF_DISABLED DEF_DISABLED DEF_DISABLED 371 uC OS III User s Manual void OSIdleTaskHook void OSTimeTick if OS_CFG_APP_HOOKS EN gt u if OS_AppIdleTaskHookPtr OS_APP_HOOK_VOID 0S_AppIdleTaskHookPtr endif Listing Testing the application with OSIdleTaskHook Verifying Task Context Switches In this section we will verify the proper operation of t
241. hronized to Task 1 If Task 1 is higher in priority than Task 2 wC OS II will switch back to Task 1 If not Task 2 continues execution Copyright 2015 Micrium Inc 267 uC OS III User s Manual Event Flags About Event Flags Event flags are used when a task needs to synchronize with the occurrence of multiple events The task can be synchronized when any of the events have occurred which is called disjunctive synchronization logical OR A task can also be synchronized when all events have occurred which is called conjunctive synchronization logical AND Disjunctive and conjunctive synchronization are shown in the figure below The application programmer can create an unlimited number of event flag groups limited only by available RAM Event flag services in C OS III start with the OSFlag prefix The services available to the application programmer are described in uC OS III API Reference The code for event flag services is found in the file os_flag c and is enabled at compile time by setting the configuration constant 0S_CFG_FLAG_EN to DEF_ENABLED in os_cfg h 1 Event Flag Group OS_FLAG GRP ama PendGetFlagsRdy 4 Pend OSFlagCreate OSFlagDel OSFlagPendAbort p PS OSFlagPost 2 2 OSFlagPendGetFlagsRdy sna Pe owe Timeout Figure Event Flags 1 AC OS II event flag group is a kernel object of type OS_FLAG_GRP see os h and Copyright 2015 Micrium Inc 268 uC OS
242. ice generates an interrupt The ISR responsible for handling the device executes assuming interrupts are enabled The device interrupt is the event that a task was waiting for The task waiting for this interrupt to occur is either higher in priority than the interrupted task lower or equal in priority The ISR calls one of the post services to signal or send a message to a task However instead of performing the post operation the ISR queues the actual post call along with arguments in a special queue called the Interrupt Queue The ISR then makes the Interrupt Queue Handler Task ready to run This task is internal to uC OS III and is always the highest priority task i e Priority 0 At the end of the ISR wC OS III always context switches to the interrupt queue handler task which then extracts the post command from the queue We disable interrupts to prevent another interrupt from accessing the interrupt queue while the queue is being 169 uC OS III User s Manual 5 6 All the extra processing is performed to avoid disabling interrupts during critical sections of code The extra processing time only consist of copying the post call and arguments into the queue extracting it back out of the queue and performing an extra context switch Similar to the Direct Post Method it is easy to determine interrupt latency interrupt response interrupt recovery and task latency by adding execution times of the pieces of code
243. igher priority task ready to run uC OS II will context switch to the new higher priority task since the more important task was waiting for this device interrupt 5 Inthe Direct Post Method wC OS HI must protect critical sections by disabling interrupts as some of these critical sections can be accessed by ISRs The above discussion assumed that interrupts were enabled and that the ISR could respond quickly to the interrupting device However if the application code makes uC OS III service calls and it will at some point it is possible that interrupts would be disabled When OS_CFG_ISR_POST_DEFERRED_EN is set to DEF_DISABLED wC OS III disables interrupts while accessing critical sections Thus interrupts will not be responded to until wC OS HI re enables interrupts Of course everything was done to keep interrupt disable times as short as possible but there are complex features of uC OS II that disable interrupts for relatively long periods of time The key factor in determining whether to use the Direct Post Method is generally the uC OS III interrupt disable time This is fairly easy to determine since the wC CPU files provided with the uC OS III port for the processor used includes code to measure maximum interrupt disable time This code can be enabled testing purposes and removed when ready to deploy the product The user would typically not want to leave measurement code in production code to avoid introducing measurement arti
244. igure Stack Frame pointed to by OSTCBHighRdy gt StkPtr OSCtxSw This function implements the task level context switch which is invoked by the 0S_TASK_SW macro declared in os_cpu h The pseudo code for this function is shown below the C like code needs to be implemented in assembly language You should also refer to Chapter 8 Copyright 2015 Micrium Inc 359 uC OS III User s Manual OSCtxSw 1 OS_CTX_SAVE 2 OSTCBCurPtr gt StkPtr SP 3 OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr 4 OS_CTX_RESTORE 5 Return from Interrupt Exception 6 1 2 3 4 5 6 Copyright 2015 Micrium Inc Listing OSCtxSw Pseudo Code OSCtxSw is invoked by 0S_TASK_SW which is typically implemented as a software interrupt instruction or a trap instruction These types of instructions generally simulate the behavior of an interrupt but is synchronous with the code osctxSw is thus the entry point for this instruction In other words if a software interrupt or TRAP is used then you would most likely need to add the address of osctxSw in the interrupt vector table OS_CTX_SAVE is a macro see os_cpu_a inc that saves the CPU context onto the current task s stack For our generic 32 bit CPU 0S_CTX_SAVE would push Re through R13 onto the stack in that order OSCtxSw then needs to save the current top of stack pointer i e R14 or SP
245. ile p_tbl CPU_DATA 1 prio DEF_INT_CPU_NBR_BITS 2 p_tbl t prio OS_PRIO CPU_CntLeadZeros p_tbl 3 return prio Listing Finding the highest priority level 1 OS_PrioGetHighest scans the table from OSPrioTb1 until a non zero entry is found The loop will always terminate because there will always be a non zero entry in the table because of the idle task 2 Each time a zero entry is found we move to the next table entry and increment prio by the width in number of bits of each entry If each entry is 32 bits wide prio is incremented by 32 3 Once the first non zero entry is found the number of leading zeros of that entry is simply added and we return the priority level back to the caller Counting the number of zeros is a CPU specific function so that if a particular CPU has a built in CLZ Copyright 2015 Micrium Inc 129 uC OS III User s Manual instruction it is up to the implementer of the CPU port to take advantage of this feature If the CPU used does not provide that instruction the functionality must be implemented in C The function CPU_CntLeadZeros simply counts how many zeros there are in a CPU_DATA entry starting from the left i e most significant bit For example assuming 32 bits exFeee1234 results in 0 leading zeros and xeeFe1234 results in 8 leading zeros At first view the linear path through the table might seem inefficient However if th
246. ill handle this accordingly Multiple Tasks Waiting on a Semaphore It is possible for more than one task to wait on the same semaphore each with its own timeout as illustrated in the figure below Copyright 2015 Micrium Inc 254 uC OS III User s Manual Timeout OSSemPend OSSemPost Pd OSSemPend A OSSemPost eehese N ae Timeout OSSemPend Q C Timeout Figure Multiple Tasks waiting on a Semaphore When the semaphore is signaled whether by an ISR or task uwC OS II makes the highest priority task waiting on the semaphore ready to run However it is also possible to specify that all tasks waiting on the semaphore be made ready to run This is called broadcasting and is accomplished by specifying OS_OPT_POST_ALL as an option when calling OSSemPost If any of the waiting tasks has a higher priority than the previously running task uC OS III will execute the highest priority task made ready by OSSemPost Broadcasting is a common technique used to synchronize multiple tasks and have them start executing at the same time However some of the tasks that we want to synchronize might not be waiting for the semaphore It is fairly easy to resolve this problem by combining semaphores and event flags This will be described after examining event flags Semaphore Internals for synchronization Note that some of the material presented in this section is also contained in Resource Manag
247. in also returns if the scheduler is locked Next OS_SchedRoundRobin moves the oS_TcB of the current task from the head of the ready list to the end The time quanta for the task at the head of the list is loaded Each task may specify its own time quanta when the task is created or through OSTaskTimeQuantaSet If you set the task time quanta to 0 then wC OS III assumes the default time quanta which corresponds to the value in the variable oSSchedRoundRobinDf1tTimeQuanta 145 uC OS III User s Manual Copyright 2015 Micrium Inc 146 uC OS III User s Manual Context Switching When uC OS II decides to run a different task see Scheduling it saves the current task s context which typically consists of the CPU registers onto the current task s stack and restores the context of the new task and resumes execution of that task This process is called a Context Switch Context switching adds overhead The more registers a CPU has the higher the overhead The time required to perform a context switch is generally determined by how many registers must be saved and restored by the CPU The context switch code is generally part of a processor s port of uC OS III A port is the code needed to adapt uC OS III to the desired processor This code is placed in special C and assembly language files os_cpu h os_cpu_c c and os_cpu_a asm Porting uC OS ILII provides more details on the steps needed to port uC OS III to different CPU arc
248. ing below and the code listing itself OS_TMR MyTmr1 OS_TMR MyTmr2 void MyTmrCallbackFnct1 void p_arg Do something when timer 1 expires void MyTmrCallbackFnct2 void p_arg Do something when timer 2 expires void MyTask void p_arg OS_ERR err while DEF_ON OSTmrCreate OS_TMR amp MyTmr1 OS_CHAR My Timer 1 OS_TICK 1 OS_TICK e OS_OPT OS_OPT_TMR_ONE_SHOT OS_TMR_CALLBACK_PTR MyTmrCallbackFnct1 void 0 OS_ERR amp err Check err OSTmrStart OS_TMR amp MyTmr1 OS_ERR amp err Check err Continues in the next code listing Listing Creating and Starting a timer Since this is the first timer inserted in the timer list the NextPtr and NULL Copyright 2015 Micrium Inc PrevPtr both point to 204 uC OS III User s Manual OSTmrListEntries OSTmrListPtr Remain 1 OSTmrTickCtr 22 OS_TMR Figure Inserting a timer in the timer list The code below shows creating and starting another timer This is performed before the timer task is signaled Continuation of code from previous code listing OSTmrCreate OS_TMR amp MyTmr2 OS_CHAR My Timer 2 OS_TICK 10 OS_TICK e OS_OPT OS_OPT_TMR_ONE_SHOT OS_TMR_CALLBACK_PTR MyTmrCallbackFnct2 void 22 OS_ERR amp err Check err OSTmrStart OS_TMR amp MyTmr OS_ERR a
249. ing by walking the stack of each task to determine the usage of each This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TaskChangePrioEn CPU_INT 8U OS_CFG_TASK_CHANGE_PRIO_EN When 1 this variable indicates that the function OSTaskChangePrio is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TaskDelEn CPU_INT 8U OS_CFG_TASK_DEL_EN When 1 this variable indicates that the function OSTaskDel is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TaskQEn CPU_INT 8U OS_CFG_TASK_Q_EN When 1 this variable indicates that oSTaskQ services are available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TaskQPendAbortEn CPU_INT 8U OS_CFG_TASK_Q PEND _ABORT_EN When 1 this variable indicates that the function OSTaskQPendAbort is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TaskProfileEn CPU_INT 8U OS_CFG_TASK_PROFILE_EN When 1 this variable indicates that task profiling is enabled and that uC OS II will perform run time performance measurements on a per task basis Specifically when 1 uC OS III will keep track of how many context switches each task makes how long a task disables interrupts how long a task locks the scheduler and more This value is set in os_cfg h Copyright 2015 Micrium Inc 407 uC OS III
250. into the OS_TCB of the current task The stack pointer for the new task is retrieved from the os_TCB of the new current task OS_CTX_RESTORE is a macro see os_cpu_a inc that restores the context of the CPU from the new task s stack For our generic 32 bit CPU 0S_CTX_RESTORE would pop CPU registers R13 through Re from the stack in that order The Return from Interrupt Exception restores the Program Counter PC and the Status Register SR in a single instruction At this point the new task will resume execution exactly where it was preempted 360 uC OS III User s Manual OSIntCtxSw This function implements the interrupt level context switch which is called by OSIntExit see os_core c The pseudo code for this function is shown below the C like code needs to be implemented in assembly language Refer also to Context Switching OSIntCtxSw 1 OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr 2 OS_CTX_RESTORE 3 Return from Interrupt Exception 4 1 2 3 4 Listing OSIntCtxSw Pseudo Code OSIntCtxSw is called by OSIntExit at the end of all nested ISRs The ISR is assumed to have saved the context of the interrupted task onto that task s stack Also the ISR is assumed to have saved the new top of stack of the interrupted task into the os_TcB of that task The stack pointer for the new task is then retrieved from the 0S_TcB of
251. ip The figure below shows timing diagram associated with the timer management task Copyright 2015 Micrium Inc 201 uC OS III User s Manual Priority tog All 4 2 Higher Y ii aez Priority Tasks A ee Qo PO at a a Timer Task A A A A 4 5 6 7 Figure Timing Diagram 1 The tick ISR occurs and assumes interrupts are enabled and executes 2 The tick ISR signals the tick task that it is time for it to update timers 3 The tick ISR terminates however there might be higher priority tasks that need to execute assuming the timer task has a lower priority Therefore uC OS III runs the higher priority task s 4 When all higher priority tasks have executed uC OS III switches to the timer task and determines that there are three timers that expired 5 The callback for the first timer is executed 6 The callback for the second expired timer is executed 7 The callback for the third expired timer is executed There are a few interesting things to notice e Execution of the callback functions is performed within the context of the timer task This means that the application code will need to make sure there is sufficient stack space for the timer task to handle these callbacks Copyright 2015 Micrium Inc 202 uC OS III User s Manual The callback functions are executed one after the other based on the order they are found in the timer list The execution time of the timer task gr
252. is a simple program that thinks it has the Central Processing Unit CPU all to itself On a single CPU only one task can execute at any given time uC OS III supports multitasking and allows the application to have any number of tasks The maximum number of task is actually only limited by the amount of memory both code and data space available to the processor Multitasking is the process of scheduling and switching the CPU between several tasks this will be expanded upon later The CPU switches its attention between several sequential tasks Multitasking provides the illusion of having multiple CPUs and actually maximizes the use of the CPU Multitasking also helps in the creation of modular applications One of the most important aspects of multitasking is that it allows the application programmer to manage the complexity inherent in real time applications Application programs are typically easier to design and maintain when multitasking is used Tasks are used for such chores as monitoring inputs updating outputs performing computations control loops update one or more displays reading buttons and keyboards communicating with other systems and more One application may contain a handful of tasks while another application may require hundreds The number of tasks does not establish how good or effective a design may be it really depends on what the application or product needs to do The amount of work a task performs also depend
253. is the first nested interrupt you need to save the current value of the stack pointer of the interrupted task into its os_TcB The global pointer osTcBCurPtr conveniently points to the interrupted task s os_TcB The very first field in 0S_TCB is where the stack pointer needs to be saved In other words OSTCBCurPtr gt StkPtr happens to be at offset 0 in the 0S_TCB this greatly simplifies assembly language At this point you need to clear the interrupting device so that it does not generate the same interrupt However most people defer the clearing of the source and prefer to perform the action within the user ISR handler in C At this point it is safe to re enable kernel aware interrupts if you want to support nested interrupts This step is optional At this point further processing can be deferred to a C function called from assembly language This is especially useful if there is a large amount of processing to do in the ISR handler However as a general rule keep the ISRs as short as possible In fact it is best to simply signal or send a message to a task and let the task handle the details of servicing the interrupting device The ISR must call one of the following functions OSSemPost OSTaskSemPost OSFlagPost OSQPost or OSTaskQPost This is necessary since the ISR will notify a task which will service the interrupting device These are the only functions able to be called from an ISR and they are used to
254. is value is called the Tick Step and represents the minimum delay needed to wake up a task present in either the timeout tick list or the delay tick list The operating frequency of the dynamic tick timer can be higher than 0S_CFG_TICK_RATE_HZ Which means that once converted to a dynamic tick count a delay in 0S_TICKs could overflow the counter used by the dynamic tick timer For example suppose the dynamic tick timer uses a 16 bit counter and operates at 10 kHz and that 0S_CFG_TICK_RATE_HZ is set to 1000 A delay of 7 seconds or 7000 os_TICKs would need 7000 10000 1000 or 70000 dynamic timer ticks This is because one 0S_TICK is worth 10 dynamic timer ticks since the dynamic tick timer operates at a frequency that is 10 times faster than 0S_CFG_TICK_RATE_HZ In this case 70000 is effectively higher than the maximum value that the 16 bit counter can contain BSP_OS_TickNextSet would then set the dynamic tick timer to interrupt in the maximum number of 0S_TICKs it can contain Doing so BSP_OS_TickNextSet would set the number of effective OS ticks that will elapse to 6553 This is because even though the maximum value of a 16 bit timer is 65535 once this value is converted to OS_TICKS it is not even One needs to find the maximum number of 0S_TICKs the dynamic tick timer counter can contain without overflowing and without yielding an odd 0s_TICK count equivalent In this example its 65530 since divided by 10 it gives an even 6553 OS_TICKs
255. isable status is returned to the caller and in fact it is stored onto the caller s stack in a variable called cpu_sr OS_CRITICAL_EXIT and OS_CRITICAL_EXIT_NO_SCHED both invoke the uC CPU macro CPU_CRITICAL_EXIT which maps to CPU_SR_Restore CPU_SR_Restore is passed the value of the saved cpu_sr variable to re establish interrupts the way they were prior to calling OS_CRITICAL_ENTER The typical code for the macros is shown in the listing below define OS_CRITICAL_ENTER CPU_CRITICAL_ENTER define OS_CRITICAL_EXIT CPU_CRITICAL_EXIT define OS_CRITICAL_EXIT_NO_SCHED CPU_CRITICAL_EXIT Listing Critical section code Disabling interrupts Copyright 2015 Micrium Inc uC OS III User s Manual Measuring Interrupt Disable Time uC CPU provides facilities to measure the amount of time interrupts are disabled This is done by setting the configuration constant CPU_CFG_INT_DIS_MEAS_EN to 1 in cpu_cfg h The measurement is started each time interrupts are disabled and ends when interrupts are re enabled The measurement keeps track of two values a global interrupt disable time and an interrupt disable time for each task Therefore it is possible to know how long a task disables interrupts enabling the user to better optimize their code The per task interrupt disable time is saved in the task s 0S_TCB during a context switch see OSTaskSwHook in os_cpu_c c and described in
256. k from ever running the value would be 0 This variable is declared only when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h IntDisTimeMax This variable keeps track of the maximum interrupt disable time of a task in CPU_TS units This variable shows how each task affects interrupt latency Copyright 2015 Micrium Inc 390 uC OS III User s Manual The variable is declared only when CPU_CFG_INT_DIS_MEAS_EN in cpu_cfg h is set to DEF_ENABLED MsgQ NbrEntries This variable indicates the number of entries currently waiting in the message queue of a task This variable is declared only when 0S_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h MsgQ NbrEntriesMax This variable indicates the maximum number of entries placed in the message queue of a task This variable is declared only when 0S_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h MsgQ NbrEntriesSize This variable indicates the maximum number of entries that a task message queue is able to accept before it is full This variable is declared only when 0S_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg h MsgQPendTime This variable indicates the amount of time it took for a task or an ISR to send a message to the task in CPU_TS units The variable is declared only when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h MsgQPendTimeMax This variable indicates the maximum amount of time it took for a task or an ISR to send a message to th
257. k that is ready to run When the semaphore is released and the task that called OSSemPend is again the highest priority task uC OS III examines the task status to determine the reason why OSSemPend is returning to its caller The possibilities are 1 The semaphore was given to the waiting task This is the preferred outcome 2 The pend was aborted by another task 3 The semaphore was not posted within the specified timeout 4 The semaphore was deleted When 0SSemPend returns the caller is notified of the above outcome through an appropriate error code If OSSemPend returns with err set to OS_ERR_NONE your code can assume that it now has access to the resource If err contains anything else OSSemPend either timed out if the timeout argument was non zero the pend was aborted by another task or the semaphore was deleted by another task It is always important to examine the returned error code and not assume that everything went well When the task is finished accessing the resource it needs to call oSSemPost and specify the same semaphore Again OSSemPost starts by checking the arguments passed to this 228 uC OS III User s Manual Copyright 2015 Micrium Inc function to make sure there are valid values assuming OS_CFG_ARG_CHK_EN is set to 1 in os_cfg h OSSemPost then calls OS_TS_GET to obtain the current timestamp so it can place that information in the semaphore to be used by oSSemPend
258. ks represents 10 milliseconds Specifying a timeout of zero 0 means waiting forever for the semaphore 3 The third argument specifies how to wait There are two options OS_OPT_PEND_BLOCKING and OS_OPT_PEND_NON_BLOCKING The blocking option means that if the semaphore is not available the task calling OSSemPend will wait until the semaphore is posted or until the timeout expires The non blocking option indicates that if the semaphore is not Copyright 2015 Micrium Inc 217 uC OS III User s Manual 4 5 6 7 8 9 Copyright 2015 Micrium Inc available OSSemPend will return immediately and not wait This last option is rarely used when using a semaphore to protect a shared resource When the semaphore is posted uC OS III reads a timestamp and returns this timestamp when OSSemPend returns This feature allows the application to know when the post happened and the semaphore was released At this point OS_TS_GET is read to get the current timestamp and you can compute the difference indicating the length of the wait OSSemPend returns an error code based on the outcome of the call If the call is successful err will contain OS_ERR_NONE If not the error code will indicate the reason for the error See Appendix A wC OS III Configuration Manual for a list of possible error code for OSSemPend Checking for error return values is important since other tasks might delete or otherwise ab
259. l nesting counter to 1 2 You should check the error return value If no errors exist MyTask owns MySharedResource 3 A function is called that will perform additional work 4 The designer of MyLibFunction knows that to access MySharedResource it must acquire the mutex Since the calling task already owns the mutex this operation should not be necessary However MyLibFunction could have been called by yet another function that might not need access to MySharedResource uC OS III allows nested mutex pends so this is not a problem The mutex nesting counter is thus incremented to 2 5 MyLibFunction can access the shared resource 6 The mutex is released and the nesting counter is decremented back to 1 Since this indicates that the mutex is still owned by the same task nothing further needs to be done and OSMutexPost simply returns MyLibFunction returns to its caller 7 The mutex is released again and this time the nesting counter is decremented back to 0 indicating that other tasks can now acquire the mutex You should always check the return value of OSMutexPend and any kernel call to ensure that the function returned because you properly obtained the mutex and not because the return from OSMutexPend was caused by the mutex being deleted or because another task called OSMutexPendAbort on this mutex As a general rule do not make function calls in critical sections All mutual exclusion se
260. l As we have seen each task is assigned a priority based on its importance The priority for each task depends on the application and uC OS III supports multiple tasks at the same priority level The word preemptive means that when an event occurs and that event makes a more important task ready to run then uC OS II will immediately give control of the CPU to that task Thus when a task signals or sends a message to a higher priority task the current task is suspended and the higher priority task is given control of the CPU Similarly if an Interrupt Service Routine ISR signals or sends a message to a higher priority task when the message has been sent the interrupted task remains suspended and the new higher priority task resumes Copyright 2015 Micrium Inc 136 uC OS III User s Manual Preemptive Scheduling uC OS III handles event posting from interrupts using two different methods Direct and Deferred Post These will be discussed in greater detail in Interrupt Management From a scheduling point of view the end result of the two methods is the same the highest priority ready task will receive the CPU as shown in the figures below 3 4 Y uC OS Ill lo 9 A 6 2 g re ap 1 11 Low Priorit enn n Task s Figure Preemptive scheduling Direct Method 1 A low priority task is executing and an interrupt occurs 2 Tf interrupts are enabled the CPU vectors i e jumps to the ISR that is respo
261. l then run the next highest priority task that is ready to run When the semaphore is signaled and the task that called OSSemPend is again the highest priority task a task status is examined to determine the reason why OSSemPend is returning to its caller The possibilities are 1 The semaphore was signaled which is the desired outcome 2 The pend was aborted by another task 3 The semaphore was not signaled within the specified timeout 4 The semaphore was deleted 259 uC OS III User s Manual 2 When 0SSemPend returns the caller is notified of the above outcome through an appropriate error code If OSSemPend returns with err set to OS_ERR_NONE you can assume that the semaphore was signaled and the task can proceed with servicing the ISR or task that caused the signal If err contains anything else OSSemPend either timed out if the timeout argument was non zero the pend was aborted by another task or the semaphore was deleted by another task It is always important to examine returned error code and not assume everything went as expected To signal a task either from an ISR or a task simply call OSSemPost as shown in the listing below OS_SEM MySem 1 2 Copyright 2015 Micrium Inc void MyISR void OS_ERR err OSSemPost amp MySem 1 OS_OPT_POST_1 2 amp err 3 Check err Listing Posting or signaling a Semaphore Your task signals or posts to t
262. ll then run the next highest priority task that is ready to run When the mutex is finally released and the task that called oSMutexPend is again the highest priority task a task status is examined to determine the reason why OSMutexPend is returning to its caller The possibilities are 1 The mutex was given to the waiting task This is the desired outcome 240 uC OS III User s Manual 2 3 Copyright 2015 Micrium Inc 2 The pend was aborted by another task 3 The mutex was not posted within the specified timeout 4 The mutex was deleted When oSMutexPend returns the caller is notified of the outcome through an appropriate error code If oSMutexPend returns with err set to OS_ERR_NONE assume that the calling task now owns the resource and can proceed with accessing it If err contains anything else then OSMutexPend either timed out if the timeout argument was non zero was aborted by another task or the mutex was deleted by another task It is always important to examine returned error codes and not assume everything went as planned If err is OS_ERR_MUTEX_NESTING then the caller attempted to pend on the same mutex When your task is finished accessing the resource it must call OSMutexPost and specify the same mutex Again OSMutexPost starts by checking the arguments passed to this function to make sure they contain valid values Assuming 0S_CFG_ARG_CHK_EN is set to DEF_ENABLED in
263. llows users to log the data displayed into a file for analysis of the collected data at a later time uC Probe also provides uC OS III kernel awareness as a built in feature The trial version that accompanies the book is limited to the display or change of up to eight 8 variables uC Probe is a tool that serious embedded software engineers should have in their toolbox The full version of uC Probe is available from Micrium see www micrium com for more details Copyright 2015 Micrium Inc uC OS III User s Manual Documentation Conventions There are a number of conventions in this documentation You will notice that when a specific element in a figure is referenced the element has a number next to it in parenthesis A description of this element follows the figure Code quality is something I ve been avidly promoting throughout my whole career At Micrim we pride ourselves in having the cleanest code in the industry Examples of this are seen in this book I created and published a coding standard in 1992 that was published in the original C OS book This standard has evolved over the years but the spirit of the standard has been maintained throughout The Micrim coding standard is available for download from the Micrim website www micrium com One of the conventions used is that all functions variables macros and define constants are prefixed by OS which stands for Operating System followed by the acronym of th
264. lower priority OSTaskCreate will return to AppTaskStart and continue execution Task 2 is created and if it has a higher priority than AppTaskStart wC OS II will immediately switch to that task 61 uC OS III User s Manual static void AppTask1 void p_arg OS_ERR err CPU_TS ts p_arg p_arg while 1 OSTimeDly OS_TICK jal 1 OS_OPT OS_OPT_TIME_DLY OS_ERR amp err OSQPost 0S_Q amp AppQ 2 void aly OS_MSG_SIZE sizeof void OS_OPT OS_OPT_POST_FIFO OS_ERR amp err OSMutexPend OS_MUTEX amp AppMutex 3 OS_TICK Je OS_OPT OS_OPT_PEND_ BLOCKING CPU_TS amp ts OS_ERR amp err Access shared resource 4 OSMutexPost OS_MUTEX amp AppMutex 5 OS_OPT OS_OPT_POST_NONE OS_ERR amp err Listing app c 4th Part 1 The task starts by waiting for one tick to expire before it does anything useful If the uC OS III tick rate is configured for 1000 Hz the task will be suspended for 1 millisecond 2 The task then sends a message to another task using the message queue Appa In this case the example sends a fixed message of value 1 but the message could have consisted of the address of a buffer the address of a function or whatever would need to be sent 3 The task then waits on the mutual exclusion semaphore since it needs to access a shared resource with another task If the resource is already owned by another task AppTask1 will
265. lution greatly depends on the tick rate For example if the tick rate OS_CFG_TICK_RATE_HZ in os_cfg_app h is set to 1000 Hz there is technically a resolution of 1 millisecond If the tick rate is 100 Hz then the delay of the current task is in increments of 10 milliseconds Again given the relative nature of this call the actual delay may not be accurate 2 Specifying 0S_OPT_TIME_HMSM_STRICT verifies that the user strictly passes valid values for Copyright 2015 Micrium Inc 190 uC OS III User s Manual hours minutes seconds and milliseconds Valid hours are 0 to 99 valid minutes are 0 to 59 valid seconds are 0 to 59 and valid milliseconds are 0 to 999 If specifying OS_OPT_TIME_HMSM_NON_STRICT the function will accept nearly any value for hours between 0 to 999 minutes from 0 to 9999 seconds any value up to 65 535 and milliseconds any value up to 4 294 967 295 OSTimeDlyHMSM 2 3 101 69 10000 may be accepted Whether or not this makes sense is a different story The reason hours is limited to 999 is that time delays typically use 32 bit values to keep track of ticks If the tick rate is set at 1000 Hz then it is possible to only track 4 294 967 seconds which corresponds to 1 193 hours and therefore 999 is a reasonable limit 3 As with most uC OS III services the user will receive an error return value The example should return 0S_ERR_NONE since the arguments in the listing are all valid Refer to uC
266. m being accessed by more than one task A task that wants to access the shared resource must obtain the mutex before it is allowed to proceed The owner of the resource relinquishes the mutex when it has finished accessing the resource This process is demonstrated in this example 3 A message queue is a kernel object through which Interrupt Service Routines ISRs and or tasks send messages to other tasks The sender formulates a message and sends it to the message queue The task s wanting to receive these messages wait on the Copyright 2015 Micrium Inc 58 uC OS III User s Manual message queue for messages to arrive If there are already messages in the message queue the receiver immediately retrieves those messages If there are no messages waiting in the message queue then the receiver will be placed in a wait list associated with the message queue This process will be demonstrated in this example 4 A stack is allocated for each task 5 The prototype of the tasks are declared The listing below shows the C entry point i e main void main void OS_ERR err BSP_IntDisA11 OSInit amp err Check for err OSMutexCreate OS_MUTEX CPU_CHAR OS_ERR Check for err OSQCreate OS_Q CPU_CHAR OS_MSG_QTY OS_ERR Check for err OSTaskCreate OS_TCB CPU_CHAR amp AppMutex 1 My App Mutex amp err amp AppQ 2 My App Queue
267. m c typedef struct os_sem OS_SEM 1 struct os_sem 3 1 2 3 Copyright 2015 Micrium Inc OS_OBJ_TYPE Type 2 CPU_CHAR NamePtr 3 OS_PEND_LIST PendList 4 OS _SEM_CTR ctr 5 CPU_TS TS 6 Listing OS_SEM data type In uC OS III all structures are given a data type In fact all data types start with os_ and are all uppercase When a semaphore is declared simply use 0S_SEM as the data type of the variable used to declare the semaphore The structure starts with a Type field which allows it to be recognized by uC OS III as a semaphore In other words other kernel objects will also have a Type as the first member of the structure If a function is passed a kernel object wC OS HI will confirm that it is being passed the proper data type assuming O0S_CFG_OBJ_TYPE_CHK_EN is set to DEF_ENABLED in os_cfg h For example if passing a message queue 0S_Q toa semaphore service for example OSSemPend wC OS III will recognize that an invalid object was passed and return an error code accordingly Each kernel object can be given a name to make them easier to be recognized by debuggers or uC Probe This member is simply a pointer to an ASCII string which is 256 uC OS III User s Manual assumed to be NUL terminated 4 Since it is possible for multiple tasks to be waiting or pending on a semaphore the semaphore object contains a pend list as described in Pend Lists 5
268. maphore calls should be in the leaf nodes of the source code e g in the low level drivers that actually touches real hardware or in other reentrant function libraries There are a number of operations that can be performed on a mutex as summarized in the table below However in this chapter we will only discuss the three functions that are most often used OSMutexCreate OSMutexPend and OSMutexPost Other functions are described in uC OS III API Reference Copyright 2015 Micrium Inc 235 uC OS III User s Manual Function Name Operation Create a mutex OSMutexCreate OSMutexDel Delete a mutex OSMutexPend Wait on a mutex OSMutexPendAbort Abort the wait on a mutex OSMutexPost Release a mutex Table Mutex API summary Copyright 2015 Micrium Inc 236 uC OS III User s Manual Mutual Exclusion Semaphore Internals A mutex is a kernel object defined by the 0S_MUTEX data type which is derived from the structure os_mutex see os h as shown in the listing below typedef struct os_mutex OS MUTEX 1 struct os_mutex J a 2 3 4 5 Copyright 2015 Micrium Inc OS_OBJ_TYPE Type 2 CPU_CHAR NamePtr 3 OS_PEND_LIST PendList 4 OS_MUTEX MutexGrpNextPtr 5 OS_TCB OwnerTCBPtr 6 OS_NESTING_CTR OwnerNestingCtr 7 CPU_TS TS 8 Listing OS_MUTEX data type In uC OS III all structures are given a data type All data types begin with os_ and are upper
269. mber of times that it was acquired Nesting can be performed up to usually 250 levels deep 8 A mutex contains a timestamp used to indicate the last time it was released wC OS TII assumes the presence of a free running counter that allows applications to make time measurements When the mutex is released the free running counter is read and the value is placed in this field which is returned when OSMutexPend returns Application code should never access any of the fields in this data structure directly Instead you should always use the API provided with wC OS IIL A mutual exclusion semaphore mutex must be created before it can be used by an application The listing below shows how to create a mutex OS_MUTEX MyMutex 1 void MyTask void p_arg OS_ERR err OSMutexCreate amp MyMutex 2 My Mutex 3 amp err 4 Check err Listing Creating a mutex 1 The application must declare a variable of type 0S_MUTEX This variable will be referenced by other mutex services 2 You create a mutex by calling oSMutexCreate and pass the address to the mutex allocated in 1 Copyright 2015 Micrium Inc 238 uC OS III User s Manual 3 4 You can assign an ASCII name to the mutex which can be used by debuggers or uC Probe to easily identify this mutex There are no practical limits to the length of the name since uC OS III stores a pointer to the ASCII string and not to the actu
270. me The files in this directory contain the wC CPU port see Porting uC OS III for details on the contents of these files cpu h contains type definitions to make uC OS III and other modules independent of the CPU and compiler word sizes Specifically one will find the declaration of the CPU_INT16U CPU_INT32U CPU_FP32 and many other data types This file also specifies whether the CPU is a big or little endian machine defines the CPU_STK data type used by wC OS III defines the macros CPU_CRITICAL_ENTER and CPU_CRITICAL_EXIT and contains function prototypes for functions specific to the CPU architecture and more cpu_a asm contains the assembly language functions to implement code to disable and enable CPU interrupts count leading zeros if the CPU supports that instruction and other CPU specific functions that can only be written in assembly language This file may also contain code to enable caches setup MPUs and MMU and more The functions provided in this file are accessible from C cpu_c c contains C code of functions that are based on a specific CPU architecture Copyright 2015 Micrium Inc 45 uC OS III User s Manual Copyright 2015 Micrium Inc but written in C for portability As a general rule if a function can be written in C then it should be unless there is significant performance benefits available by writing it in assembly language 46 uC OS III User s Manual uC LIB Portable Library Functions
271. me critical sections In the Deferred Post Method uwC OS HI must still disable interrupts to access the interrupt queue However the interrupt disable time is very short and fairly constant Note that the Deferred Post method is currently DEPRECATED and will be removed in a future uC OS III release ie 1 1 1 1 I i i i i I i t i sue H 1 i uC OS IIl h 1 I Disables i Interrupts 1 7 f 4 r 7 Y 4 oy 4 r s f we P S r pr of ow a aa l uC OS III uC OS III Disables Interrupts aiavaie Direct Post Method Deferred Post Method Figure Direct vs Deferred Post Methods If interrupt disable time is critical in the application because there are very fast interrupt sources and the interrupt disable time of uC OS III is not acceptable using the Direct Post Method use the Deferred Post Method Nonetheless if you are planning on using the features listed in the table below consider using the Deferred Post Method As a general rule you should always start with the Direct Post Method and see if the performance meets your expectations Copyright 2015 Micrium Inc 174 uC OS III User s Manual Feature Multiple tasks at the same priority Event Flags Synchronization Pend on multiple objects Pending on Multiple Objects Broadcast on Post calls See OSSemPost and OSQPost descriptions Reason Although this is an important fea
272. meD1y is called as follows OSTimeDly 1 OS_OPT_TIME_DLY amp err Referring to the wC OS III API Reference Manual that this action indicates that wC OS III has to delay the current task for 10 ticks Since this is the first task inserted in the tick list the TickNextPtr and TickPrevPtr of the task s oS_TcB both point to NULL OSTickListDly NbrEntries 1 NbrUpdated TCB_Ptr TickListPtr 0 TickPrevPtr TickNextPtr TickRemain 10 OS _TCB 10 ticks to expiration gt Figure Inserting a task in the delayed tasks tick list Copyright 2015 Micrium Inc 115 uC OS III User s Manual OSTimeDly takes care of a few other details Specifically the task is removed from uC OS III s ready list described in The Ready List since the task is no longer eligible to run because it is waiting for time to expire Also the scheduler is called because wC OS II will need to run the next most important ready to run task If the next task to run also happens to call OSTimeDly before the next tick arrives and calls OSTimeDly as follows OSTimeDly 7 OS_OPT_TIME_DLY amp err uC OS III will place this new task at the head of the list and replace the remaining counts for the first task to 3 In other words the timeout for the first task is the sum of the two values 7 3 When the tick task runs it only needs to decrement the TickRemain of the 0S_TCB which is at the head of the list an
273. mp err Check err Listing Creating and Starting a timer continued The second timer is inserted at the head of the list as shown in the figure below OSTmrListEntries OSTmrListPtr Second timer created First timer created 0 Remain 10 0 OSTmrTickCtr 22 OS_TMR OS_TMR Figure Inserting a second timer in the tick list When the timer task executes see 0S_TmrTask in os_tmr c it starts by incrementing Copyright 2015 Micrium Inc 205 uC OS III User s Manual OSTmrTickCtr and goes through the list linearly and decrements each of the Remain field When the Remain field reaches zero the timer manager executes the callback function associated with the timer and if the timer is set to periodic reloads the Remain field with the time remaining to expiration If the timer is configured as a one shot timer then the timer is removed from the list upon expiration Timer management occurs at the task level The list is protected using an internal mutual exclusion semaphore mutex when 0S_CFG_MUTEX_EN is set to DEF_ENABLED in os_cfg h or by locking the scheduler if mutexes are not enabled It s highly recommend that you use and thus enable mutexes because locking the scheduler impacts task responsiveness of other higher priority tasks in your application Copyright 2015 Micrium Inc 206 uC OS III User s Manual Resource Management This chapter will discuss services provided by uC
274. mply look at the register contents with a debugger and confirm that all registers have the proper values 6 Here we place the return address of the task into the location where the Link Register LR will be retrieved from In this case we force the return address to actually be OS_TaskReturn allowing uC OS III to catch a task that is attempting to return You should recall that this is not allowed with uwC OS IIL 7 OSTaskStkInit needs to return the new top of stack location In this case the top of stack points at the last element placed onto the stack The figure below shows how the stack frame looks like just before the function returns OSTaskCreate will actually save the new top of stack p_stk into the oS_TcB of the task being created Copyright 2015 Micrium Inc 354 uC OS III User s Manual Le E e p stk R7 0x07070707 R6 0x06060606 R4 0x04040404 R3 0x03030303 R2 0x02020202 R5 0x05050505 R1 0x01010101 PF High Memory Figure Stack frame created by OSTaskStkInit OSTaskSwHook The typical code for uC OS IIT s context switch hook is shown below What OSTaskSwHook does is highly dependent on a number of configuration options Copyright 2015 Micrium Inc 355 uC OS III User s Manual void OSTaskSwHook void if OS_CFG_TASK_PROFILE_EN gt u CPU_TS ts endif ifdef CPU_CFG_INT DIS MEAS EN CPU_TS int_dis_time endif if OS_CFG_APP_HOOK
275. n such as this is not as reliable as a hardware based detection mechanism but still prevents a possible stack overflow Of course the StkLimitPtr field would be set using OSTaskCreate as shown above but this time with a location further away from amp MyTaskStk Copyright 2015 Micrium Inc uC OS III User s Manual Stack RAM Low Memory amp MyTaskStk 0 StkLimitPtr SP Current Stack Stack Growth Usage amp MyTaskStk N 1 High Memory CPU_STK gt Figure Software detection of stack overflows monitoring lt StkLimitPtr 4 Redzone stack overflow detection The Redzone Stack Overflow detection mechanism is built in within uwC OS III This software based approach implements something defined in the previous section and is enabled by setting OS_CFG_TASK_STK_REDZONE_EN to DEF_ENABLED in os_cfg h When enabled wC OS III creates a monitored zone at the end of a task s stack This zone the Redzone is filled upon task creation with a special canary like value The zone is identified in red in the next figure The figure assumes a stack that grows towards lower addresses Every time a task needs to be switched out either at the task level or at the interrupt level wC OS III checks if the Redzone has been overwritten and checks if the stack pointer is still within the limits of the stack If the zone has been overwritten or if the stack pointer is out of bounds uC OS III informs the user by calling OSRedzoneHitHook
276. n this value would be set to 1 This field is only available when OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h OSTickListTimeout NbrEntries This variable indicates the number of tasks currently in the list of task that are pending on an object and have specified a non zero timeout value This number is updated whenever tasks are inserted or removed from that list This field is only available when OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h OSTickListTimeout NbrUpdated This variable indicates the number of 0S_TcBs in the list of tasks pending on an object and have specified a non zero timeout value that were last updated by 0S_TickTask In other words if OS_TickTask updated three 0S_TCBs then this value would be set to 3 This field is only available when 0S_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h Copyright 2015 Micrium Inc 388 uC OS III User s Manual Timer Task OSTmrCtr This variable is incremented every time the timer task executes OSTmrListEntries This variable contains the number of timers currently in the timer list It is declared only if OS_CFG_TMR_EN is set to DEF_ENABLED in os_cfg h OSTmrTaskTimeMax This variable contains the maximum execution time of the timer task in CPU_TS units It is declared only if OS_CFG_TMR_EN is set to DEF_ENABLED in os_cfg h The total time also includes the time of any ISR that occurred while the timer task was running Miscellaneous OSIdleTaskCtr This variable c
277. name of the manufacturer of the evaluation board The lt and 66099 gt are not part of the actual name lt board name gt This is the name of the evaluation board A board from Micrium will typically be called 66 99 uC Eval xxxx where xxxx represents the CPU or MCU used on the board The lt and gt are not part of the actual name lt compiler gt Copyright 2015 Micrium Inc 34 uC OS III User s Manual This is the name of the compiler or compiler manufacturer used to build the code for the evaluation board The lt and gt are not part of the actual name lt project name gt The name of the project that will be demonstrated For example a simple wC OS TII project might have a project name of os Ex1 The Ex1 represents a project containing only wC OS IIL These are the project source files Main files can optionally be called app This directory also contains configuration files os_cfg h os_cfg_app h and other required source files Copyright 2015 Micrium Inc 35 uC OS III User s Manual uC S III Board Support Package BSP The Board Support Package BSP is generally found with the evaluation or target board as it is specific to that board In fact when well written the BSP should be used for multiple projects Micrium Software EvalBoards lt manufacturer gt lt board name gt lt compiler gt BSP Micrium
278. nd i e OSPendMulti ie OSQPend Ife OSSemPend Cy j OSTimeDly a OSTimeD1yHMSM i OSTaskQPend 2 ie OSTaskSemPend a ie OSTaskSuspend Suspend self yp if OSTaskDel Delete self z Task body do work ni Listing Infinite Loop task The event the task is waiting for may simply be the passage of time when OSTimeDly or OSTimeDlyHMSM is called For example a design may need to scan a keyboard every 100 milliseconds In this case you would simply delay the task for 100 milliseconds then see if a key was pressed on the keyboard and possibly perform some action based on which key was pressed Typically however a keyboard scanning task should just buffer an identifier unique to the key pressed and use another task to decide what to do with the key s pressed Similarly the event the task is waiting for could be the arrival of a packet from an Ethernet controller In this case the task would call one of the 0S Pend calls pend is synonymous Copyright 2015 Micrium Inc uC OS III User s Manual with wait The task will have nothing to do until the packet is received Once the packet is received the task processes the contents of the packet and possibly moves the packet along a network stack It s important to note that when a task waits for an event it does not consume CPU time Tasks must be created in order for wC OS III to know about tasks You create a task by sim
279. nd make all the posts take effect simultaneously Note that 0S_OPT_POST_NO_SCHED is additive meaning that it can be used with either of the previous options You can thus specify OS_OPT_POST_1 OS_OPT_POST_ALL OS_OPT_POST_1 OS_OPT_POST_NO_SCHED OS_OPT_POST_ALL OS_OPT_POST_NO_SCHED 261 uC OS III User s Manual Task Semaphore About Task Semaphores Signalling a task using a semaphore is a very popular method of synchronization and in uC OS III each task has its own built in semaphore This feature not only simplifies code but is also more efficient than using a separate semaphore object The semaphore which is built into each task is shown in the figure below Task semaphore services in uC OS III start with the oSTaskSem prefix and the services available to the application programmer are described in Appendix A wC OS II API Reference Task semaphores are built into uC OS III and cannot be disabled at compile time as can other services The code for task semaphores is found in os_task c You can use this feature if your code knows which task to signal when the event occurs For example if you receive an interrupt from an Ethernet controller you can signal the task responsible for processing the received packet as it is preferable to perform this processing using a task instead of the ISR OSTaskSemPendAbor St OSTaskSemPost OSTaskSemSet eee pe Bee y Pd S
280. ndows based platform and makes references to typical Windows type directory structures also called Folder However since wC OS III is provided in source form it can also be used on Unix Linux or other development platforms Copyright 2015 Micrium Inc 30 uC OS III User s Manual Configuration Files 9 Application Code 1 cpu_cfg h lib cfg h pC OS III 4 pC LIB 7 CPU Independent os_cfg_app c Libraries lib ascii c pypesi lib_ i h lib def h lib _math c non lib math h os_int c lib _mem_a asm Ob mem lib_mem c os_msg c lib _mem h mutex c lib str id multi c 3 lib str h _prio c i Compiler TLS os_tis c pC CPU 3 pC OS III CPU Specific BSP CPU Specific eae Board Support Package cpu_c c bsp os c cpu_core h Software Firmware Hardware Interrupt Controller Figure wC OS III Architecture 1 The application code consists of project or product files For convenience these are simply called app c and app h however an application can contain any number of files that do not have to be called app The application code is typically where one would find the main Copyright 2015 Micrium Inc 31 uC OS III User s Manual 2 3 4 5 6 7 8 9 Copyright 2015 Micrium Inc Semiconductor manufacturers often provide library functions in source form for accessing the peripherals on their CPU or MCU These libraries are quite useful
281. nsible for servicing the interrupting device 3 The ISR services the device and signals or sends a message to a higher priority task waiting to service this device This task is thus ready to run 4 When the ISR completes its work it makes a service call to wC OS III 5 6 Since there is a more important ready to run task uC OS III decides to not return to the interrupted task but switches to the more important task See Context Switching for Copyright 2015 Micrium Inc 137 uC OS III User s Manual details on how this works 7 8 The higher priority task services the interrupting device and when finished calls uC OS III asking it to wait for another interrupt from the device 9 10 uC OS III blocks the high priority task until the next time the device needs servicing Since the device has not interrupted a second time uC OS III switches back to the original task the one that was interrupted 11 The interrupted task resumes execution exactly at the point where it was interrupted The figure below shows that uC OS III performs a few extra steps when it is configured for the Deferred Post method Notice that the end results is the same the high priority task preempts the low priority one 1 2 y uC OS III 4 Y uC OS III ISR Handler 6 Y a Task Task Task Low Priority ua ae Figure Preemptive scheduling Deferred Post Method Copyright 2015 Micrium Inc 138 uC OS III Use
282. nt Flag Group A task posts to the event flag group by calling OSFlagPost Specify the desired event flag group to post by passing its address Of course the event flag group must have been previously created OSFlagPost returns the current value of the event flags in the event flag group after the post has been performed The next argument specifies which bit s the ISR or task will be setting or clearing in the event flag group You can specify OS_OPT_POST_FLAG_SET or OS_OPT_POST_FLAG_CLR If you specify OS_OPT_POST_FLAG_SET the bits specified in the second arguments will set the corresponding bits in the event flag group For example if MyEventFlagGrp Flags contains 0x03 the code in the listing will change MyEventFlagGrp Flags to x F If you specify OS_OPT_POST_FLAG_CLR the bits specified in the second arguments will clear the corresponding bits in the event flag group For example if MyEventFlagGrp Flags contains x F the code in the listing will change MyEventFlagGrp Flags to 0x03 When calling OSFlagPost you can specify as an option i e OS_OPT_POST_NO_SCHED to not call the scheduler This means that the post is performed but the scheduler is not called even if a higher priority task was waiting for the event flag group This allows the calling task to perform other post functions if needed and make all the posts take effect simultaneously Copyright 2015 Micrium Inc 275 uC OS III User s Manual 4
283. nt from one another Copyright 2015 Micrium Inc 332 uC OS III User s Manual cpu_bsp c This file contains skeleton functions for CPU_TS_TmrInit CPU_TS_TmrRd and other time stamp related functions You can copy this file to your Board Support Package BSP directory modify its content and add it to your build cpu_def h This file should not require any changes cpu_def h declares define constants that are used by Micrium software components cpu_cfg h This is a configuration file to be copied into the product directory and changed based on the options to exercise in wC CPU cpu_cfg h is not considered a port file but more an application specific file However it s discussed here for completeness The file contains define constants that may need to be changed based on the desired use of uC CPU CPU_CFG_NAME_EN This define determines whether you will be assigning a name to the CPU port This name can then be read by application code CPU_CFG_NAME_ SIZE This define specifies the length of the ASCII string used to assign a name to the CPU CPU_CFG_TS_32_EN This define specifies whether 32 bit time stamps are available for this CPU A 32 bit timestamp is typically the value of a free running 32 bit counter that is used to make accurate time measurements The application code can obtain the current value of this free running timer at any point in time and use such value to determine when an event occurred
284. nual 5 6 7 8 9 10 11 Copyright 2015 Micrium Inc most important task and context switch to that task The low priority task executes The event that the original task was waiting for occurs The lower priority task is immediately preempted assuming interrupts are enabled and the CPU vectors to the interrupt handler for the event The ISR handles the interrupting device and then calls OSSemPost to signal the semaphore When the ISR completes wC OS III is called i e OSIntExit uC OS III notices that a higher priority task is waiting for this event to occur and context switches back to the original task The original task resumes execution immediately after the call to OSSemPend 251 uC OS III User s Manual OS_SEM MySem void MyISR void OS_ERR err Clear the interrupting device OSSemPost amp MySem 7 OS_OPT_POST_1 amp err Check err void MyTask void p_arg OS_ERR err CPU_TS ts while DEF_ON OSSemPend amp MySem 1 10 OS_OPT_PEND_BLOCKING amp ts amp err Check err 11 Listing Pending or waiting on a Semaphore A few interesting things are worth noting about this process First the task does not need to know about the details of what happens behind the scenes As far as the task is concerned it called a function OSSemPend that will return when the event it is waiting for occurs Second
285. nvoke the scheduler to see if the created task is now the highest priority task and if so will context switch to this new task The body of the task can invoke other services provided by uC OS III Specifically a task can create another task i e call OSTaskCreate suspend and resume other tasks i e call OSTaskSuspend and OSTaskResume respectively post signals or messages to other tasks i e call OS Post share resources with other tasks and more In other words tasks are not limited to only make wait for an event function calls The figure below shows the resources with which a task typically interacts Copyright 2015 Micrium Inc 76 uC OS III User s Manual 1 2 Copyright 2015 Micrium Inc Task Stack RAM 4 CPU_STK MyTaskStk Task Code 1 m MyTask void p_arg Local variables Task Initialization while DEF_ON Wait for event to occur Process event P Variables essed EN iai Optional I O Registers 3 Optional Figure Tasks interact with resources An important aspect of a task is its code As previously mentioned the code looks like any other C function except that it is typically implemented as an infinite loop and a task is not allowed to return Each task is assigned a priority based on its importance in the application wC OS III s job is to decide which task will run on the CPU The general rule is that uC OS I
286. o Task L Task H ownae done with Done by Mutex 12 pCc Os lll TaskH pciosi lowers preempts raised ssi d Task M TaskL priority qasi 13 f ask L 4 5 Task H Task L resumes to that of and now owns Task H Mutex Task L 0 Task L gets Mutex 2 Figure Using a mutex to share a resource 1 Task H and Task M are both waiting for an event to occur and Task L is executing 2 At some point Task L acquires a mutex which it needs before it is able to access a shared resource 3 Task L performs operations on the acquired resource 4 The event that Task H waited for occurs and the kernel suspends Task L and begins executing Task H since Task H has a higher priority 5 Task H performs computations based on the event it just received Copyright 2015 Micrium Inc 232 uC OS III User s Manual 6 Task H now wants to access the resource that Task L currently owns i e it attempts to get the mutex from Task L Given that Task L owns the resource uC OS III raises the priority of Task L to the same priority as Task H to allow Task L to finish with the resource and prevent Task L from being preempted by medium priority tasks 7 Task L continues accessing the resource however it now does so while it is running at the same priority as Task H Note that Task H is not actually running since it is waiting for Task L to release the mutex In other words Task H is in the mutex wait list 8
287. occurs C OS III uses this function to update time delays and timeouts used by other system calls OSTimeTick is considered an internal function to C OS II Copyright 2015 Micrium Inc uC OS III User s Manual Timer Management Timer Services uC OS III provides timer services to the application programmer and code to handle timers is found in os_tmr c Timer services are enabled when setting 0S_CFG_TMR_EN to DEF_ENABLED in os_cfg h Timers are down counters that perform an action when the counter reaches zero The user provides the action through a callback function or simply callback A callback is a user declared function that will be called when the timer expires The callback can be used to turn a light on or off start a motor or perform other actions However it is important to never make blocking calls within a callback function i e call OSTimeDly OSTimeD1lyHMSM 0S Pend or anything that causes the timer task to block or be deleted Timers are useful in protocol stacks retransmission timers for example and can also be used to poll I O devices at predefined intervals An application can have any number of timers limited only by the amount of RAM available Timer services i e functions in wC OS III start with the osTmr prefix and the services available to the application programmer are described in uC OS III API Reference The resolution of all the timers managed by uC OS III is determined by the
288. ock time is saved in the task s 0S_TcB during a context switch see OSTaskSwHook in os_cpu_c c and described in Context Switching The unit of measure for the measured time is in CPU_TS timestamp units so it is necessary to find the resolution of the timer used to measure the timestamps For example if the timer used for the timestamp is incremented at 1 MHz then the resolution of CPU_TS is 1 microsecond Measuring the scheduler lock time adds measurement artifacts and thus increases the amount of time the scheduler is actually locked However measurement overhead is accounted for and the measured value represents the actual scheduler lock time as if the measurement was not present Copyright 2015 Micrium Inc uC OS III User s Manual uC OS Ill Features with Longer Critical Sections The table below shows several uC OS III features that have potentially longer critical sections Knowledge of these will help the user decide whether to direct uC OS II to use one critical section over another Feature Multiple tasks at the same priority Event Flags See Synchronization Pend on multiple objects See Pending on Multiple Objects Broadcast on Post calls See OSSemPost and OSQPost descriptions uC OS III API Reference Reason Although this is an important feature of uC OS III multiple tasks at the same priority create longer critical sections However if there are only a few tasks at the same priority int
289. ode four times and pass it different data for each serial port that each instance will manage A run to completion task must delete itself by calling OSTaskDe1 The task starts performs its function and terminates There would typically not be too many such tasks in the embedded system because of the overhead associated with creating and deleting tasks at run time In the task body you can call most of uC OS III s functions to help perform the desired operation of the task void MyTask void p_arg OS_ERR err Local variables yi Do something with p_arg ty Task initialization Ez Task body do work ty OSTaskDel OS_TCB amp err Listing Run To Completion task With uC OS III you either can call a C or assembly language functions from a task In fact it is possible to call the same C function from different tasks as long as the functions are reentrant A reentrant function is a function that does not use static or otherwise global variables unless they are protected uC OS III provides mechanisms for this from multiple access If shared C functions only use local variables they are generally reentrant assuming that the compiler generates reentrant code An example of a non reentrant function is the famous strtok provided by most C compilers as part of the standard library This function is used to parse an ASCII string for tokens The first time you call this function you speci
290. oes just that For our generic 32 bit CPU 0S_CTX_RESTORE would pop CPU registers R13 through Re from the stack in that order Finally the Return from Interrupt Exception restores the Program Counter Pc and the Status Register SR in a single instruction At this point the interrupted task will resume execution exactly where it was interrupted It is actually possible to simplify the code for BSP_OS_TickISR or any of your ISRs Notice that the code at the beginning and end of the ISR is common for all ISRs Because of that it s possible to create two assembly language macros OS_ISR_ENTER and OS_ISR_EXIT in os_cpu_a inc The new BSP_OS TickISR code would now look as shown below Copyright 2015 Micrium Inc 345 uC OS III User s Manual BSP_OS_TickISR OS_ISR_ENTER Clear tick interrupt OSTimeTick OS_ISR_EXIT Listing BSP_OS_TickISR Pseudo Code using the OS_ISR_ENTER and OS_ISR_EXIT macros bsp_os c bsp_os_a asm and bsp_os h Dynamic Tick Board Support Package BSP specific code is needed to provide uwC OS II with a dynamic time source To use the dynamic ticking feature a programmable timer is necessary This timer has to be precise enough to guarantee the execution of the Tick task at least 1000 times per second In other words the frequency of the dynamic tick timer must be an integer multiple of OS_CFG_TICK_RATE_HZ to properly manage single os_TICK delays When the OS_CFG_DYN_TICK_EN option is set
291. of the CPU architecture that uC OS III was ported to The lt and gt are not part of the actual name lt compiler gt The name of the compiler or compiler manufacturer used to build code for the port The lt and gt are not part of the actual name Copyright 2015 Micrium Inc 42 uC OS III User s Manual Copyright 2015 Micrium Inc The files in this directory contain the uC OS III port see Porting uC OS III for details on the contents of these files os_cpu h contains a macro declaration for 0S_TASK_SW as well as the function prototypes for at least the following functions OSCtxSw OSIntCtxSw and OSStartHighRdy os_cpu_a asm contains the assembly language functions to implement at least the following functions OSCtxSw OSIntCtxSw and OSStartHighRdy os_cpu_c c contains the C code for the port specific hook functions and code to initialize the stack frame for a task when the task is created 43 uC OS III User s Manual uC CPU CPU Specific Source Code uC CPU consists of files that encapsulate common CPU specific functionality and CPU and compiler specific data types See Porting uC OS III Micrium Software uC CPU cpu_core c cpu_core h cpu_def h Cfg Template cpu_cfg h lt architecture gt lt compiler gt cpu h cpu_a asm cpu_c c Micrium Contains all software components and projects provided by Micrium Software This sub directory contains all
292. ointer to the task s OS_TCB in p_mutex gt OwnerTcPPtr It also adds the mutex to the calling task list of owned mutex and sets the mutex nesting counter to 1 OSMutexPend then returns to its caller with an error code of OS_ERR_NONE If the task that calls oSMutexPend already owns the mutex OSMutexPend simply increments a nesting counter In this case the error returned will indicate OS_ERR_MUTEX_OWNER Applications can nest calls to oSMutexPend up to usually 250 levels deep If the mutex is already owned by another task and 0S_OPT_PEND_NON_BLOCKING is specified OSMutexPend returns since the task is not willing to wait for the mutex to be released by its owner If the mutex is owned by a task that currently has a lower priority wC OS II will raise the priority of the owner to match the priority of the current task If you specify OS_OPT_PEND_BLOCKING as the option the calling task will be inserted in the list of tasks waiting for the mutex to be available The task is inserted in the list by priority order and thus the highest priority task waiting on the mutex is at the beginning of the list If you further specify a non zero timeout the task will also be inserted in the tick list A zero value for a timeout indicates a willingness to wait forever for the mutex to be released The scheduler is then called since the current task is no longer able to run it is waiting for the mutex to be released The scheduler wi
293. on Copyright 2015 Micrium Inc 154 uC OS III User s Manual Interrupt Management An interrupt is a hardware mechanism used to inform the CPU that an asynchronous event occurred When an interrupt is recognized the CPU saves part or all of its context i e registers and jumps to a special subroutine called an Interrupt Service Routine ISR The ISR processes the event and upon completion of the ISR the program either returns to the interrupted task or the highest priority task if the ISR made a higher priority task ready to run Interrupts allow a microprocessor to process events when they occur i e asynchronously which prevents the microprocessor from continuously polling looking at an event to see if it occurred Task level response to events is typically better using interrupt mode as opposed to polling mode Microprocessors allow interrupts to be ignored or recognized through the use of two special instructions disable interrupts and enable interrupts respectively In a real time environment interrupts should be disabled as little as possible Disabling interrupts affects interrupt latency possibly causing interrupts to be missed Processors generally allow interrupts to be nested which means that while servicing an interrupt the processor recognizes and services other more important interrupts One of the most important specifications of a real time kernel is the maximum amount of time that interr
294. on programmer This value is set in os_cfg h ROM Variable Data Type Value OSDbg_FlagDelEn CPU_INT 8U OS_CFG_FLAG_DEL_EN When 1 this variable indicates that the OSFlagDel function is available to the application programmer This value is set in os_cfg h ROM Variable Data Type Value OSDbg_FlagModeClrEn CPU_INT 8U OS_CFG_FLAG_MODE_CLR_EN When 1 this variable indicates that you can either clear or set flags when posting and pending on event flags This value is set in os_cfg h ROM Variable Data Type Value Copyright 2015 Micrium Inc 400 uC OS III User s Manual OSDbg_FlagPendAbortEn CPU_INT 8U OS_CFG_FLAG_PEND_ABORT_EN When 1 this variable indicates that the OSFlagPendAbort function is available to the application programmer This value is set in os_cfg h ROM Variable Data Type Value CPU_INT16U sizeof OS_FLAG_GRP OSDbg_FlagGrpSize This variable indicates the memory footprint in RAM of an event flag group in bytes This data type is declared in os h ROM Variable Data Type Value OSDbg_FlagWidth CPU_INT16U sizeof OS_FLAGS This variable indicates the word width in bytes of event flags If event flags are declared as CPU_INT 8U this variable will be 1 if declared as a CPU_INT16U this variable will be 2 etc This 0S_FLAGS data type is declared in os_type h ROM Variable Data Type Value OSDbg_IntQ CPU_INT16U sizeof OS_INT_Q This variable indicates the size in bytes of the 0S_INT_Q data type
295. ons to make library functions thread safe The adaptation of those functions is performed in the os_t1s c file which is found under the uCOS III TLS lt tool gt folder lt tool gt is the name of the tool manufacturer or the tool name Configuration files are used to define wC OS III features os_cfg h to include in the application specify the size of certain variables and data structures expected by 32 uC OS III User s Manual uC OS III os_cfg_app h such as idle task stack size tick rate size of the message pool configure the uC CPU features available to the application programmer cpu_cfg h and also configure uC LIB options lib_cfg h Copyright 2015 Micrium Inc 33 uC OS III User s Manual Application Code When Micrium provides example projects they are placed in a directory structure shown below Of course a directory structure that suits a particular project product can also be used Micrium Software EvalBoards lt manufacturer gt lt board_name gt lt compiler gt lt project name gt Micrium This is where we place all software components and projects provided by Micrium This directory generally starts from the root directory of the computer Software This sub directory contains all software components and projects EvalBoards This sub directory contains all projects related to evaluation boards supported by Micrium lt manufacturer gt 6699 This is the
296. ontain multiple header files bsp h is shown generically here os h is the main header file for uC OS III and includes the following header files os_cfg h cpu h cpu_core h lib_def h Copyright 2015 Micrium Inc uC OS III User s Manual os_type h os_cpu h 2 We will be creating an application task and it is necessary to allocate a task control block oS_TcB for this task The oS_TcB data type will be described in About Task Management 3 Each task created requires its own stack A stack must be declared using the CPU_STK data type as shown The stack can be allocated statically as shown here or dynamically from the heap using malloc It should not be necessary to free the stack space because the task should never be destroyed and thus the stack would always be used 4 This is the function prototype of the task that we will create Most C applications start at main as shown in in the listing below void main void OS_ERR err BSP_IntDisA11 OSInit amp err if err OS_ERR_NONE Something didn t get initialized correctly a7 check os h for the meaning of the error code see OS_ERR_xxxx OSTaskCreate OS_TCB amp AppTaskStartTCB CPU_CHAR App Task Start OS_TASK_PTR AppTaskStart void OS_PRIO APP_TASK_START_PRIO CPU_STK amp AppTaskStartStk CPU_STK_SIZE APP_TASK_START_STK_SIZE 10 CPU_STK_SIZE APP_TASK_START_STK_SIZE OS_MSG QTY
297. ontains a counter that is incremented every time the idle task infinite loop runs OSRunning When non zero this variable indicates that multitasking has started OSTaskCtxSwCtr This variable accumulates the number of context switches performed by C OS IIL Copyright 2015 Micrium Inc 389 uC OS III User s Manual Per Task Statistics Run Time uC OS III maintains statistics for each task at run time This information is saved in the task s OS_TCB CPUUsage This variable keeps track of CPU usage of the task multiplied by 100 For example if the task s cPUUsage is 200 then the task consumes 2 00 of total CPU usage The variable is declared only when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CPUUsageMax This variable keeps track of the maximum i e peak CPU usage of the task multiplied by 100 For example if the task s cPUUsageMax is 571 then the task maximum CPU usage that the task consumed at any given time is 5 71 of total CPU usage This variable is reset by oSStatReset The variable is declared only when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CtxSwCtr This variable keeps track of the number of times a task is context switched in This variable should increment If it does not increment the task is not running At a minimum the counter should at least have a value of one since a task is always created ready to run However if higher priority tasks prevent the tas
298. ontext switch into 0S_TickTask In fact you will be in the context of OS_TickTask but you will not be in the 0S_TickTask code itself This is because uC OS III is actually returning to the point where it invoked the scheduler to switch to the idle task uC OS III is simply returning to that point You can step through code to see the path uC OS III is taking However this corresponds to quite a few lines of code It s probably simpler to simply run the CPU at full speed and have the debugger stop when you hit the breakpoint in 0S_TickTask If you were to repeatedly run the target at full speed your debugger should now stop at the following breakpoints OSTickISR OSIntCtxSw OS _TickTask BSP_OS_TickISR Copyright 2015 Micrium Inc 381 uC OS III User s Manual OSIntCtxSw etc At this point the port tests are complete You should be able to use the uwC OS III port in your target application Copyright 2015 Micrium Inc 382 uC OS III User s Manual Run Time Statistics uC OS III performs substantial run time statistics that can be displayed by kernel aware debuggers and or uC Probe Specifically it is possible to ascertain the total number of context switches maximum interrupt disable time maximum scheduler lock time CPU usage stack space used on a per task basis the RAM used by wC OS II and much more No other real time kernel provides as much run time information as uC OS III
299. or example if the system does not contain an application task and osstatTaskCtr counts from 0 to 10 000 000 for 1 0S_CFG_STAT_TASK_RATE_HZ second when adding tasks and the test is redone every 1 0S_CFG_STAT_TASK_RATE_HZ second the oSStatTaskCtr will not reach 10 000 000 and actual CPU utilization is determined as follows 100x OSStatTaskCtr OSStatTaskCtrMax CPU _Utilization 100 For example if when redoing the test oSStatTaskCtr reaches 7 500 000 the CPU is busy 25 of its time running application tasks 25 100 199 7 590 000 10 000 000 You should call this function to reset the statistics counter so that you are not getting incorrect values from the startup code AppTaskStart can then create other application tasks as needed As previously described uC OS III stores run time statistics for each task in each task s 121 uC OS III User s Manual OS_TCB OS_StatTask also computes stack usage of all created tasks by calling OSTaskStkChk see os_task c and stores the return values of this function free and used stack space in the StkFree and StkUsed field of the task s 0S_TCB respectively Copyright 2015 Micrium Inc 122 uC OS III User s Manual The Timer Task uC OS III provides timer services to the application programmer and this code is found in os_tmr c The timer task is optional in a wC OS II application and its presence is controlled by the compile time configuration cons
300. or error conditions that are sent to it by other tasks or ISRs clients For example a client detects whether the RPM of the rotating wheel has been exceeded another client detects whether an over temperature exists and yet another client detects that a user pressed a shutdown button When the clients detect error conditions they send a message through the message queue The message sent indicates the error detected which threshold was exceeded the error code that is associated with error conditions or even suggests the address of a function that will handle the error and more Message osaPost Queue A Error OSQPost gt osaPend Handler osapost Task Timeout Figure Clients and Servers Copyright 2015 Micrium Inc 302 uC OS III User s Manual Message Queues Internals As previously described a message consists of a pointer to actual data a variable indicating the size of the data being pointed to and a timestamp indicating when the message was actually sent When sent a message is placed in a data structure of type 0S_MsG shown in the figure below The sender and receiver are unaware of this data structure since everything is hidden through the APIs provided by wC OS II Pointer to next OS_MSG Pointer to message contents Figure OS_MSG structure uC OS III maintains a pool of free oS_MsGs The total number of available messages in the pool is determined by the value of 0S_CFG_MSG_POOL_
301. orm additional calculations and can further detect such errors as the wheel spinning too fast or too slow In fact the task can notify other tasks about these errors if needed The listing below shows how to implement the RPM measurement example using uC OS III s message queue services Some of the code is pseudo code while the calls to uC OS III services are actual calls with their appropriate arguments Copyright 2015 Micrium Inc 296 uC OS III User s Manual osQ CPU_ CPU_ CPU_ void void RPM_Q 1 INT32U DeltaCounts INT32U CurrentCounts INT32U PreviousCounts main void OS_ERR err OSInit amp err 2 osocreate 0S_Q amp RPM_Q CPU_CHAR My Queue OS_MSG_QTY 10 OS_ERR amp err OSStart amp err RPM_ISR void 3 OS_ERR err Clear the interrupt from the sensor CurrentCounts Read the input capture DeltaCounts CurrentCounts PreviousCounts PreviousCounts CurrentCounts OSQPost O0S_Q amp RPM_Q 4 void DeltaCounts OS_MSG_SIZE sizeof void OS_OPT OS_OPT_POST_FIFO OS_ERR amp err void RPM_Task void p_arg Copyright 2015 Micrium Inc CPU_INT32U delta OS_ERR err OS MSG SIZE size CPU_TS ts DeltaCounts PreviousCounts Q CurrentCounts while DEF_ON delta CPU_INT32U 0SQPend OS_Q amp RPM_Q 5 OS_TICK OS_CFG_TICK_RATE_HZ 10 OS_OPT OS_OPT_PEND_BLOCKING OS_MSG SIZE amp size CP
302. ort the pend However it is not a recommended practice to delete kernel objects at run time as the action may cause serious problems The resource can be accessed when OSSemPend returns if there are no errors When finished accessing the resource you simply call oSSemPost and specify the semaphore to be released OS_OPT_POST_1 indicates that the semaphore is signaling a single task if there are many tasks waiting on the semaphore In fact you should always specify this option when a semaphore is used to access a shared resource As with most uC OS III functions you specify the address of a variable that will receive an error message from the call 218 uC OS III User s Manual void Task2 void p_arg OS ERR err CPU_TS ts while DEF_ON OSSemPend amp MySem 1 OS_OPT_PEND_BLOCKING amp ts amp err switch err case OS_ERR_NONE Access Shared Resource OSSemPost amp MySem OS_OPT_POST_1 amp err Check err break case OS_ERR_PEND_ ABORT The pend was aborted by another task vf break case OS_ERR_OBJ_DEL The semaphore was deleted Sif break default Other errors ay Listing Using a semaphore to access a shared resource 1 Another task wanting to access the shared resource needs to use the same procedure to access the shared resource Semaphores are especially useful when tasks share I O devices Imagine what would happen if two tasks were
303. ortly Specifying OS_OPT_TIME_DLY indicates that the user wants to use relative mode As with most uC OS III services an error return value will be returned The example should return 0S_ERR_NONE because the arguments are all valid You should always check the error code returned by wC OS IIL If err does not contain OS_ERR_NONE OSTimeDly did not perform the intended work For example another task could remove the time delay suspension by calling OSTimeDlyResume and when MyTask returns it would not have returned because the time had expired As mentioned above the delay is not accurate Refer to the figure below and its description below to understand why Copyright 2015 Micrium Inc 186 uC OS III User s Manual 1 2 3 4 5 6 Copyright 2015 Micrium Inc wt Priority 1 5 7 Tick l l a 2 P E e ticks Figure OSTimeDly Relative We get a tick interrupt and uC OS III services the ISR At the end of the ISR all Higher Priority Tasks HPTs execute The execution time of HPTs is unknown and can vary Once all HPTs have executed wC OS III runs the task that has called OSTimeD1ly as shown in the listing above For the sake of discussion it is assumed that this task is a lower priority task LPT The task calls OSTimeDly and specifies to delay for two ticks in relative mode At this point wC OS II places the current task in the tick list w
304. os_cfg h OSMutexPost now calls 0S_TS_GET to obtain the current timestamp and place that information in the mutex which will be used by OSMutexPend OSMutexPost decrements the nesting counter and if still non zero OSMutexPost returns to the caller In this case the current owner has not fully released the mutex The error code will be OS_ERR_MUTEX_NESTING OSMutexPost removes the mutex from the calling tasks mutex group If there are no tasks waiting for the mutex OSMutexPost sets p_mutex gt OwnerTCBPtr to a NULL pointer and clears the mutex nesting counter If uC OS III had to raise the priority of the mutex owner uC OS III sets the priority of the calling task to the highest priority in the calling task s owned mutex group or its base priority whichever is higher 241 uC OS III User s Manual The highest priority task waiting on the mutex is then extracted from the pend list and given the mutex This is a fast operation since the pend list is sorted by priority If the option to OSMutexPost is not OS_OPT_POST_NO_SCHED then the scheduler is called to execute the next highest priority task Copyright 2015 Micrium Inc 242 uC OS III User s Manual Should You Use a Semaphore Instead of a Mutex A semaphore can be used instead of a mutex if none of the tasks competing for the shared resource have deadlines to be satisfied However if there are deadlines to meet you should use a mutex prior to
305. pHC OS HM The Real Time Kernel User s Manual Jean J Labrosse Micripm L Press nE FL 33326 uC OS II User s Manual Ts p OS UT User Manal seon 49 6 a eee Oa eee E Le Bale SAGE VOLE AE SEEN 4 LT Preface xtc striae oar e tae Aware anak eee sche eke EEA O EE eee ee 5 2 Introduction is eaa Send Magee Dewees wae E EE E ae oa Me E A 13 1 2 1 Foreground Background Systems 0 cece ccc eee 15 12 2 Reak Time Kernels spiron ppr teaa Daa E E Stet EEE pt E TOE sta tehee RDE 16 1 2 3 RTOS Real Time Operating System 0 ee eee eee ene 19 FACOS wee hee ee emt ne Bae BA SR Be Re Ca Bat hl nt PAR E da eet 20 1 2 5 uC OS uC OS II and uC OS III Features Comparison 0 0 cee eee eee 25 1 2 6UC Probe a sacona ned ene sweatin 4 Lea aan ds owen aes aada Mee Mea aiagaea lings 28 1 2 7 Documentation Conventions 0 0 cece ce eee cece bene n ene nee 29 1 3 Directonies and Piles i058 eta wig ste petting eh she Rone oot Ea fee eae hee ote wee a atege 30 1 3 1 Application Code sm 3 654 a4 sb Wasa d dane oy bene Wea Se woe eee ete eae wees 34 1 3 2 uC OS III Board Support Package BSP 0 eee eee 36 1 3 3 uC OS III CPU Independent Source Code 0 eect ee nee 38 1 3 4 uC OS III CPU Specific Source Code 0 2 ec eeenen ene 42 1 3 5 uC CPU CPU Specific Source Code 2 0 2 eee cece nee nee 44 1 3 6 uC LIB Portable Library Functions 0 0 0 cece cece ences 47 1 4 Getting Started with uC
306. perations that should be performed at the task level must unfortunately be handled by the ISRs to ensure that they are dealt with in a timely fashion This causes ISRs to take longer than they should Also information for a background module that an ISR makes available is not processed until the background routine gets its turn to execute which is called the task level response The worst case task level response time depends on how long a background loop takes to execute and since the execution time of typical code is not constant the time for successive passes through a portion of the loop is nondeterministic Furthermore if a code change is made the timing of the loop is affected Most high volume and low cost microcontroller based applications e g microwave ovens telephones toys etc are designed as foreground background systems Super Loop Background Task 3 ISR Time Foreground _ gt 1 i i i Infinite 4 Loop Task 3 ob Nested ISR Foreground pmd _ ee Figure Foreground Background SuperLoops systems Copyright 2015 Micrium Inc 15 uC OS III User s Manual Real Time Kernels A real time kernel is software that manages the time and resources of a microprocessor microcontroller or Digital Signal Processor DSP The design process of a real time application involves splitting the work into tasks each responsible for a portion of the job A task also called a thread is a
307. plate file contains the following code void OSInitHook void Listing Typical OSInitHook OSRedzoneHitHook If Redzone Stack Checking is enabled OS_CFG_TASK_STK_REDZONE_EN set to DEF_ENABLED in is os_cfg h this function is called when uC OS III determines that a task s stack has overflowed its Redzone The function calls an application hook if defined If not it calls a software exception The application hook could try to fix the stack report an error or simply call the software exception void OSRedzoneHitHook OS_TCB p_tcb if OS_CFG_APP_HOOKS_EN gt u if OS_AppRedzoneHitHookPtr OS_APP_HOOK_TCB 0S_AppRedzoneHitHookPtr p_tcb endif void p_tcb CPU_SW_EXCEPTION Listing Typical OSRedzoneHitHook Copyright 2015 Micrium Inc 350 uC OS III User s Manual OSStatTaskHook This function is called when the statistic task executes This hook allows the port developer the opportunity to add his or her own statistics The template file contains the following code void OSStatTaskHook void if OS_CFG_APP_HOOKS_EN gt u if OS_AppStatTaskHookPtr OS_APP_HOOK_VOID 0S_AppStatTaskHookPtr endif Listing Typical OSStatTaskHook OSTaskCreateHook This function is called by OSTaskCreate and is passed the address of the oS_TcB of the newly created task OSTaskCreateHook is called by OSTaskCreate after initializing the 0S_TCB fields and setting up
308. ply calling OSTaskCreate as we ve seen in the Getting Started section The function prototype for OSTaskCreate is shown below void OSTaskCreate OS_TCB OS_CHAR OS_TASK_PTR void OS_PRIO CPU_STK CPU_STK_SIZE CPU_STK_SIZE OS_MSG_QTY OS_TICK void OS_OPT OS_ERR p tcb p_name p_task p_arg prio p_ stk_base stk_limit stk_size q_size time_slice p ext opt p err Listing OSTaskCreate A complete description of OSTaskCreate and its arguments is provided in uC OS III API Reference However it is important to understand that a task needs to be assigned a Task Control Block i e TCB a stack a priority and a few other parameters which are initialized by OSTaskCreate as shown in the figure below Copyright 2015 Micrium Inc 74 uC OS III User s Manual 1 2 3 Copyright 2015 Micrium Inc RAM p_stk_base 0 Low Memory 1 0 1 0 0 p_stk_limit 4 1 0 OS_OPT_TASK_STK_CLR 0 0 2 0 0 0 stk_size 0 1 0 Stack Growth 0 0 i SP TCB RAM 0 4 CPU Registers 3 High Memory 4 CPU_STK gt All fields initialized 5 Figure OSTaskCreate initializes the task s TCB and stack When calling OSTaskCreate you pass the base address of the stack p_stk_base that will be used by the task the watermark limit for stack growth stk_limit which is expressed in number of CPU_STK entries before the stack is empty and the size of that stack stk_
309. portant tasks OS_TickTask is used by uC OS III to keep track of tasks waiting for time to expire or for tasks that are pending on kernel objects with a timeout 0S_TickTask is a periodic task and it waits for signals from the tick ISR described in Interrupt Management as shown in the figure 10 to 1000 Hz below List of tasks waiting for time to expire or to timeout 2 NN oe en Figure Tick ISR and Tick Task relationship 1 A hardware timer is generally used and configured to generate an interrupt at a rate between 10 and 1000 Hz see 0S_CFG_TICK_RATE_HZ in os_cfg_app h This timer is generally called the Tick Timer The actual rate to use depends on such factors as processor speed desired time resolution and amount of allowable overhead to handle the tick timer etc The tick interrupt does not have to be generated by a timer and in fact it can come from other regular time sources such as the power line frequency 50 or 60 Hz which are Copyright 2015 Micrium Inc 112 uC OS III User s Manual known to be fairly accurate over long periods of time 2 Assuming CPU interrupts are enabled the CPU accepts the tick interrupt preempts the current task and vectors to the tick ISR The tick ISR must call OSTimeTick see os_time c which accomplishes most of the work needed by wC OS HI The tick ISR then clears the timer interrupt and possibly reloads the timer for the next interrupt However some
310. proximately 100 bytes of code space Application code can examine these variables and the application does not need to access them in acritical region since they reside in code space and are therefore not changeable ROM Variable Data Type Value oscfg_IdleTaskStkSizeRAM CPU_INT32U sizeof OSCfg_IdleTaskStk This variable indicates the RAM footprint in bytes of the wC OS III idle task stack ROM Variable Data Type Value OSCfg_IntQSizeRAM CPU_INT32U sizeof OSCfg_IntQ This variable indicates the RAM footprint in bytes of the wC OS II interrupt handler task queue ROM Variable Data Type Value oscfg_IntQTaskStkSizeRAM CPU_INT32U sizeof OSCfg_IntQTaskStk This variable indicates the RAM footprint in bytes of the wC OS III interrupt queue handler task stack ROM Variable Data Type Value OSCfg_ISRStkSizeRAM CPU_INT32U sizeof OSCfg_ISRStk This variable indicates the RAM footprint in bytes of the dedicated Interrupt Service Routine ISR stack ROM Variable Data Type Value Copyright 2015 Micrium Inc 410 uC OS III User s Manual OSCfg_MsgPoolSizeRAM CPU_INT32U sizeof OSCfg_MsgPool This variable indicates the RAM footprint in bytes of the message pool ROM Variable Data Type Value OSCfg_StatTaskStkSizeRAM CPU_INT32U sizeof OSCfg_StatTaskStk This variable indicates the RAM footprint in bytes of the wC OS III statistic task stack ROM Variable Data Type Value oscfg_TickTaskStkSizeRAM CPU_INT32U siz
311. r of stack bytes used and the amount of stack space still unused by the task These fields only exist in a TCB if the statistic task is enabled at compile time OS_CFG_STAT_TASK_STK_CHK_EN is set to DEF_ENABLED in os_cfg h IntDisTimeMax This field keeps track of the maximum interrupt disable time of the task The field is updated only if wC CPU supports interrupt disable time measurements This field is available only if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h and uC CPU s CPU_CFG_INT_DIS_MEAS_EN is defined in cpu_cfg h SchedLockTimeMax The field keeps track of the maximum scheduler lock time of the task In other words the maximum amount of time the task locks the scheduler This field is available only if you set OS_CFG_TASK_PROFILE_EN to DEF_ENABLED and OS_CFG_SCHED_LOCK_TIME_MEAS_EN is set to DEF_ENABLED in os_cfg h DbgNextPtr This field contains a pointer to the next 0S_TCB in a doubly linked list of 0S_TCBs OS_TCBs Copyright 2015 Micrium Inc 107 uC OS III User s Manual are placed in this list by OSTaskCreate This field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h DbgPrevPtr This field contains a pointer to the previous OS_TCB in a doubly linked list of os_TCBs os_TCBs are placed in this list by OSTaskCreate This field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg h DbgNamePtr This field contains a pointer to the name of the object that the t
312. r points to a lower or equal priority task waiting on the kernel object TCBPtr Is a pointer to the 0S_TcB of the task waiting on the pend list PendObjPtr Is a pointer to the kernel object that the task is pending on In other words this pointer can point to an OS_SEM OS_MUTEX OS_FLAG_GRP or OS_Q by using an OS_PEND_OBJ as the common data structure RdyObjPtr Is a pointer to the kernel object that is ready if the task actually waits for multiple kernel objects See Pending on Multiple Objects for more on this RdyMsgPtr Copyright 2015 Micrium Inc 181 uC OS III User s Manual Is a pointer to the message posted through oSQPost if the task is pending on multiple kernel objects Again see Pending on Multiple Objects RdyTS Is a timestamp of when the kernel object was posted This is used when a task pends on multiple kernel objects as described in Pending on Multiple Objects The figure below shows how all data structures connect to each other when tasks are inserted in a pend list This drawing assumes that there are two tasks waiting on a semaphore 1 OS_SEM TailPtr HeadPtr TCBPtr TCBPtr PendObjPtr PendObjPtr RdyObjPtr RdyObjPtr RdyMsgPtr RdyMsgPtr RdyMsgSize RdyMsgSize RdyTS RdyTS OS_PEND_DATA 5 OS_PEND_DATA OS_TCB OS_TCB Higher Priority Task Lower Priority Task Figure Pend Data Copyright 2015 Micrium Inc 182 uC OS III User s
313. r s Manual a 2 3 4 5 6 Copyright 2015 Micrium Inc The ISR services the device and instead of signaling or sending the message to the task uC OS III through the POST call places the post call into a special queue and makes a very high priority task actually the highest possible priority ready to run This task is called the JSR Handler Task When the ISR completes its work it makes a service call to wC OS III Since the ISR made the ISR Handler Task ready to run wC OS II switches to that task The ISR Handler Task then removes the post call from the message queue and reissues the post This time however it does it at the task level instead of the ISR level The reason this extra step is performed is to keep interrupt disable time as small as possible See Interrupt Management to find out more on the subject When the queue is emptied uC OS III removes the ISR Handler Task from the ready list and switches to the task that was signaled or sent a message 139 uC OS III User s Manual Scheduling Points Scheduling occurs at scheduling points and nothing special must be done in the application code since scheduling occurs automatically based on the conditions described below A task signals or sends a message to another task This occurs when the task signaling or sending the message calls one of the post services 0S Post Scheduling occurs towards the end of the 0S Post call Note that sc
314. rce called the clock tick or system tick A hardware timer configured to generate an interrupt at a rate between 10 and 1000 Hz provides the clock tick A tick source may also be obtained by generating an interrupt from an AC power line typically 50 or 60 Hz In fact you can easily derive 100 or 120 Hz by detecting zero crossings of the power line That being said if your product is subject to be used in regions that use both power line frequencies then you may need to have the user specify which frequency to use or have the product automatically detect which region it s in The clock tick interrupt can be viewed as the system s heartbeat The rate is application specific and depends on the desired resolution of this time source However the faster the tick rate the higher the overhead imposed on the system The clock tick interrupt allows uC OS III to delay tasks for an integral number of clock ticks and provide timeouts when tasks are waiting for events to occur The clock tick interrupt must call OSTimeTick The pseudocode for OSTimeTick is shown in the listing below void OSTimeTick void OSTimeTickHook 1 if OS_CFG_ISR_POST DEFERRED EN gt Qu Get timestamp 2 Post time tick to the Interrupt Queue else Signal the Tick Task 3 Run the round robin scheduling algorithm 4 Signal the timer task 5 endif Listing OSTimeTick pseudocode 1 The time tick ISR starts by calling a
315. ready list 1 Before calling oSTaskCreate in this example two tasks were in the ready list at priority prio Copyright 2015 Micrium Inc 134 uC OS III User s Manual 2 Anew TCB is passed to OSTaskCreate and uC OS III initialized the contents of that TCB 3 OSTaskCreate calls OS_RdyListInsertTail which links the new TCB to the ready list by setting up four pointers and also incrementing the Entries field of OSRdyList prio Not shown in Figure 6 6 is that OSTaskCreate also calls 0S_PrioInsert to set the bit in the bitmap table Of course this operation is not necessary as there are already entries in the list at this priority However 0S_PrioInsert is a very fast call and thus it should not affect performance The reason the new TCB is added to the end of the list is that the current head of the list could be the task creator and it could be at the same priority So there is no reason to make the new task the next task to run In fact a task being made ready will be inserted at the tail of the list if the current task is at the same priority However if a task is being made ready at a different priority than the current task it will be inserted at the head of the list Copyright 2015 Micrium Inc 135 uC OS III User s Manual Scheduling The scheduler also called the dispatcher is a part of uC OS III responsible for determining which task runs next wC OS III is a preemptive priority based kerne
316. red timer rate is 10 Hz the timer task will be signaled every 100th tick interrupt as shown in the figure below Copyright 2015 Micrium Inc 123 uC OS III User s Manual OS_CFG_TICK_RATE_HZ 7 10 to 1000 Hz Signaled every a S a a 3 x5 ae a a OS_CFG_TICK_RATE_HZ OS_CFG_TMR_TASK_RATE_HZ List of timers to update Figure Tick ISR and Timer Task relationship 124 Copyright 2015 Micrium Inc uC OS III User s Manual The ISR Handler Task When setting the compile time configuration constant 0S_CFG_ISR_POST_DEFERRED_EN in os_cfg h to DEF_ENABLED uC OS III creates a task called 0S_IntQTask responsible for deferring the action of OS post service calls from ISRs As described in Critical Sections uC OS III manages critical sections either by disabling enabling interrupts or by locking unlocking the scheduler If selecting the latter method i e setting OS_CFG_ISR_POST_DEFERRED_EN to DEF_ENABLED uC OS III post functions called from interrupts are not allowed to manipulate such internal data structures as the ready list pend lists and others When an ISR calls one of the post functions provided by uC OS III a copy of the data posted and the desired destination is placed in a special holding queue When all nested ISRs complete uC OS II context switches to the ISR handler task OS_IntQTask which re posts the information placed in the holding queue to
317. rent toolchain uses The table below shows where you can find template files that will help you create a uwC OS III port from scratch You would simply copy these files in a folder specific to your processor compiler as shown in the table above and then change the contents of these files per your processor compiler File os_cpu h os_cpu_a asm os_cpu_a inc os_cpu_c c Copyright 2015 Micrium Inc Directory Micrium Software uCOS III Ports Template Micrium Software uCOS III Ports Template Micrium Software uCOS III Ports Template Micrium Software uCOS III Ports Template Table uC OS III template files 342 uC OS III User s Manual bsp_os c bsp_os_a asm and bsp_os h Periodic Tick Board Support Package BSP specific code is generally needed to provide uC OS III with a periodic time source This is typically obtained from a hardware timer that is configured to generate a tick rate between 10 and 1000 Hz By convention we decided to call these files bsp_os c bsp_os_a asm optional and bsp_os h These files part of the BSP typically contain code for just a couple of functions BSP_OS_TickInit and BSP_OS_TickISR BSP_OS_Ticklnit This function must be called by the first task that executes under uC OS III and after you called CPU_Init Alternatively you can place BSP_OS_TickInit in os_cpu_c c depending on whether or not the tick ISR is generic for the CPU architecture you are using In other
318. right 2015 Micrium Inc 363 uC OS III User s Manual OS_ISR_ENTER MACRO ENDM OS_ISR_EXIT This macro allows you to simplify your assembly language ISRs OS_ISR_EXIT is basically the last line of code you would add to the ISR The pseudo code for OS_ISR_EXIT is shown below PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH PUSH OSIntNestingCtr RO R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 if OSIntNestingCtr 1 OS_ISR_EXIT Assuming our generic 32 bit CPU 0S_ISR_EXIT would be implemented as follows You should note that the C like code would actually be implemented in assembly language Copyright 2015 Micrium Inc OSIntExit OS_CTX_RESTORE OSTCBCurPtr gt StkPtr SP Listing OS_ISR_ENTER assuming generic 32 bit CPU Return from Interrupt Exception Listing OS_ISR_EXIT macro Pseudo Code 364 uC OS III User s Manual OS_ISR_EXIT MACRO OSIntExit ENDM Copyright 2015 Micrium Inc POP POP POP POP POP POP POP POP POP POP POP POP POP POP R13 R12 R11 R10 R9 R8 R7 R6 R5 R4 R3 R2 R1 RO Return from Interrupt Exception Listing OS_ISR_EXIT assuming generic 32 bit CPU 365 uC OS III User s Manual Board Support Package About BSPs A board support package refers to code associated with the actual evaluation board or the target board used For example the BSP defines functions to turn LEDs on or off reads push b
319. rowth High Memory lt 4 CPU_STK gt NextPtr and PrevPtr These pointers are used to doubly link 0s_TcBs in the ready list A doubly linked list allows 0S_TCBs to be quickly inserted and removed from the list TickNextPtr and TickPrevPtr These pointers are used to doubly link 0S_TcBs in the list of tasks waiting for time to expire or to timeout from pend calls Again a doubly linked list allows 0s_TcBs to be quickly inserted and removed from the list TickListPtr This pointer points to one of two tick lists either the list of tasks delayed waiting for time to expire OSTickListDly or tasks pending on an object with a timeout OSTickListTimeout This field is used to easily remove the 0S_TcB from the list NamePtr Copyright 2015 Micrium Inc 98 uC OS III User s Manual This pointer allows a name an ASCII string to be assigned to each task Having a name is useful when debugging since it is user friendly compared to displaying the address of the os_TcB Storage for the ASCII string is assumed to be in user space either in code memory ASCII string declared as a const or in RAM StkBasePtr This field points to the base address of the task s stack The stack base is typically the lowest address in memory where the stack for the task resides A task stack is declared as follows CPU_STK MyTaskStk CPU_STK is the data type you must use to declare task stacks and is the size of the stack associated with
320. rs 317 uC OS III User s Manual 6 You then need to pass the base address of the storage area reserved for the memory blocks 7 Here you specify how many memory blocks are available from this memory partition Hard coded numbers are used for the sake of the illustration but you should instead use define constants 8 You need to specify the size of each memory block in the partition Again a hard coded value is used for illustration which is not recommended in real code 9 As with most uC OS III services OSMemCreate returns an error code indicating the outcome of the service The call is successful if err contains OS_ERR_NONE The listing below shows how to create a memory partition with wC OS III but this time using malloc to allocate storage Do not deallocate the memory control block or the storage for the partition OS_MEM MyPartitionPtr 1 void main void OS_ERR err void p_storage OSInit amp err MyPartitionPtr OS_MEM malloc sizeof OS_MEM 2 if MyPartitionPtr OS_MEM p_storage malloc 12 100 3 if p_storage void OSMemCreate OS_MEM MyPartitionPtr 4 CPU_CHAR My Partition void p_storage 5 OS_MEM QTY 12 6 OS_MEM_SIZE 1 0 6 OS_ERR amp err Check err OsStart amp err Listing Creating a memory partition Copyright 2015 Micrium Inc 318 uC OS III User s Manual 1 2
321. rs to the ISR responsible for servicing the interrupting device The ISR services the interrupt device but actually does very little work The ISR will typically signal or send a message to a higher priority task that will be responsible for most of the processing of the interrupting device For example if the interrupt comes from an Ethernet controller the ISR simply signals a task which will process the received packet When the ISR finishes wC OS II notices that a more important task has been made ready to run by the ISR and will not return to the interrupted task but instead context switch to the more important task The higher priority task executes and performs the necessary processing in response to the interrupt device When the higher priority task completes its work it loops back to the beginning of the task code and makes a wC OS III function call to wait for the next interrupt from the device The low priority task resumes exactly at the point where it was interrupted not knowing what happened Kernels such as uC OS III are also responsible for managing communication between tasks and managing system resources memory and I O devices A kernel adds overhead to a system because the services provided by the kernel require time to execute The amount of overhead depends on how often these services are invoked Ina well designed application a kernel uses between 2 and 4 of a CPU s time And since
322. rt Copyright 2015 Micrium Inc 166 uC OS III User s Manual Every Interrupt Vectors to a Unique Location If the interrupt controller vectors directly to the appropriate interrupt handler each of the ISRs that are actually used in the application must be written in assembly language as described in Typical uC OS III Interrupt Service Routine This of course slightly complicates the design However you can copy and paste the majority of the code from one handler to the other and just change what is specific to the actual device If the interrupt controller allows the user to query it for the source of the interrupt it may be possible to simulate the mode in which all interrupts vector to the same location by simply setting all vectors to point to the same location Most interrupt controllers that vector to a unique location however do not allow users to query it for the source of the interrupt since by definition having a unique vector for all interrupting devices should not be necessary Copyright 2015 Micrium Inc uC OS III User s Manual Direct and Deferred Post Methods uC OS III handles event posting from interrupts using two different methods Direct and Deferred Post The method used in the application is selected by changing the value of OS_CFG_ISR_POST_DEFERRED_EN in os_cfg h When set to DEF_DISABLED uC OS III uses the Direct Post Method and when set to DEF_ENABLED uC OS III uses the Deferred Post Method Note that t
323. rt executing that task The pseudo code for this function is shown below the C like code needs to be implemented in assembly language Copyright 2015 Micrium Inc 357 uC OS III User s Manual OSStartHighRdy OSTaskSwHook SP OSTCBHighRdyPtr gt StkPtr 1 OS_CTX_RESTORE 2 Return from Interrupt Exception 3 Listing OSStartHighRdy Pseudo Code 1 The Stack Pointer SP for the first task to execute is retrieved from the os_TcB of the highest priority task that was created prior to calling osstart The figure below shows the stack frame as pointed to by OSTCBHighRdy gt StkPtr 2 OS_CTX_RESTORE is a macro see os_cpu_a inc that restores the context of the CPU Re through R13 from the new task s stack 3 The Return from Interrupt Exception restores the Program Counter PC and the Status Register SR in a single instruction At this point the task will start executing In fact the task will think it was called by another function and thus will receive p_arg as its argument Of course the task must not return Copyright 2015 Micrium Inc 358 uC OS III User s Manual R13 LR OS_TaskReturn 4 OS TCBHighRdy StkPtr R12 0x12121212 R11 0x11111111 R10 0x10101010 R9 0x09090909 R8 0x08080808 R7 0x07070707 R6 0x06060606 R5 0x05050505 R4 0x04040404 R3 0x03030303 R2 0x02020202 R1 0x01010101 RO p arg R15 PC p _ task SR 0x00000000 High Memory F
324. s to dynamically allocate and free memory blocks used to pass the data The figure below shows an example For sake of illustration assume that a device is sending data bytes to the UART in packets using some protocol In this case the first byte of a packet is unique and the end of packet byte is also unique 2 s 1 UART UART Rx ISR ida paii Rx Task 4 xX Timeout OSMemPut Figure Using memory partitions for message contents 1 Here a UART generates an interrupt when characters are received 2 The pseudo code in the listing below shows what the UART ISR code might look like There are a lot of details omitted for sake of simplicity The ISR reads the byte received from the UART and sees if it corresponds to a start of packet If it is a buffer is obtained from the memory partition 3 The received byte is then placed in the buffer Copyright 2015 Micrium Inc 292 uC OS III User s Manual 4 If the data received is an end of packet byte you would simply post the address of the buffer to the message queue so that the task can process the received packet 5 If the message sent makes the UART task the highest priority task wC OS III will switch to that task at the end of the ISR instead of returning to the interrupted task The task retrieves the packet from the message queue Note that the osQPend call also returns the number of bytes in the packet and a time stamp indicating when the message
325. s a CPU_TS_TMR data type which can be configured to be either a CPU_TS32 or a CPU_TS64 If a 16 bit timer is used the implementer of this function must accumulate 16 bit values into a 32 bit accumulator in order to always have 32 bit timestamps The timer used for timestamps must count up 0 1 2 3 and must rollover automatically when the maximum count for the resolution of the timer is reached In other words a 16 bit counter should go from x eee to xFFFF and then roll back to 0x0000 Note that a skeleton of CPU_TS_TmrRd is can be found in the template file Micrium Software uC CPU BSP Template cpu_bsp c bsp_os c bsp_os_a asm amp bsp_os h These are discussed in uC OS III Port Copyright 2015 Micrium Inc 367 uC OS III User s Manual Testing a Port Testing a port is fairly easy to do if you have the proper tools Here we will assume that you have access to a good debugging tool preferably built around an Integrated Development Environment IDE The debugger should allow you to load your code into your target single step through your code set breakpoint examine CPU registers look at memory contents and more Creating a Simple Test Project At this point you should have the wC CPU and uC OS III port file created To test the port files you need to create a simple project When you download and unzip the uC OS III source code you will have a directory structure similar to what is shown on the next page When you see
326. s are necessary prior to calling osstart However when the statistic task is used to compute overall CPU utilization it is necessary to create only one task 120 uC OS III User s Manual 4 5 6 7 8 Copyright 2015 Micrium Inc You need to call osstart to let wC OS II start the highest priority task which in our case is AppTaskStart At this point there should be either four 4 to six 6 tasks created depending on configuration option 0S_IdleTask OS_TickTask OS_StatTask OS_TmrTask optional OS_IntQTask optional and now AppTaskStart The start task should then configure and enable tick interrupts This most likely requires that the user initialize the hardware timer used for the clock tick and have it interrupt at the rate specified by 0S_CFG_TICK_RATE_HZ see os_cfg_app h Additionally Micrium provides sample projects that include a basic board support package BSP The BSP initializes many aspects of the CPU as well as the periodic time source required by uC OS III If available the user may utilize BSP services by calling BSP_Init from the startup task After this point no further time source initialization is required by the user OSStatTaskCPUUsageInit is called to determine the maximum value that oSStatTaskCtr see OS_IdleTask can count up to for 1 0S_CFG_STAT_TASK_RATE_HZ second when there are no other tasks running in the system apart for the other uC OS III tasks F
327. s just prior to calling osIntctxSw OSTCBHighRdyPtr gt Low Low Memory S fe emery aoe za a a sis nuon ma High meron seo Oe y Address Address aa Figure Variables and data structures prior to calling OSIntCtxSw uC OS III assumes that CPU registers are saved onto the task s stack at the beginning of an ISR see Interrupt Management Because of this notice that OSTCBCurPtr gt StkPtr contains a pointer to the top of stack pointer of the task being suspended the one on the left OSIntCtxSw does not have to worry about saving the CPU registers of the suspended task since that has already been done The figure below shows the operations performed by osIntctxSw to complete the second half of the context switch This is exactly the same process as the second half of osctxSw Copyright 2015 Micrium Inc 153 uC OS III User s Manual OSTCaHghRayetr gt Ed ss CPU meray O C Ce e Oe Ce Ze e Ce Oe a p Ce e C e Ce Oe Ce e C e Ce i run o weer mea Ce RAM Figure Operations performed by OSIntCtxSw 1 OSIntCtxSw loads the CPU stack pointer with the saved top of stack from the new task s OS_TCB R14 OSTCBHighRdyPtr gt StkPtr 2 OSIntctxSw then retrieves the CPU register contents from the new stack The program counter and status registers are generally retrieved at the same time by executing a return from interrupt instructi
328. s now a feature of wC OS IIL uC OS III also provides additional features that better exploit the capabilities of today s newer processors Specifically wC OS HI was designed with 32 bit processors in mind although it certainly works well with 16 and even several 8 bit processors uC OS III Goals The main goal of uC OS III is to provide a best in class real time kernel that literally shaves months of development time from an embedded product schedule Using a commercial real time kernel such as uC OS III provides a solid foundation and framework to the design engineer dealing with the growing complexity of embedded designs Another goal for uC OS III and therefore this documentation is to explain inner workings of a commercial grade kernel This understanding will assist the reader in making logical design decisions and informed tradeoffs between hardware and software that make sense Copyright 2015 Micrium Inc uC OS III User s Manual Intended Audience This documentation is written for embedded systems programmers consultants hobbyists and students interested in understanding the inner workings of a real time kernel uC OS III is not just a great learning platform but also a commercial grade software package ready to be part of a range of products To get the most from this documentation it is assumed that the reader has a good working knowledge of microprocessors microcontrollers and or Digital Signal Processors DSPs
329. s of a function call is placed in the Link Register LR The program counter or instruction pointer is R15 and there are two separate stack pointers labeled R14 and R14 R14 represents a task stack pointer TSP and R14 represents an ISR stack pointer ISP The CPU automatically switches to the ISR stack when servicing an exception or interrupt The task stack is accessible from an ISR i e we can push Copyright 2015 Micrium Inc 341 uC OS III User s Manual and pop elements onto the task stack when in an ISR and the interrupt stack is also accessible from a task The Status Register SR contains the interrupt mask as well as various status such as the Carry Zero Sign Overflow Parity etc File bsp_os c bsp_os h bsp_os_a asm os_cpu h os_cpu_a asm os_cpu_a inc os_cpu_c c Directory Micrium Software EvalBoards lt manufacturer gt lt board gt BSP OS uCOS III Micrium Software uCOS III Ports lt processor gt lt compiler gt Micrium Software uCOS III Ports lt processor gt lt compiler gt Micrium Software uCOS III Ports lt processor gt lt compiler gt Micrium Software uCOS III Ports lt processor gt lt compiler gt Table uC OS III files and directories Here lt processor gt is the name of the processor that the os_cpu files apply to and lt compiler gt is the name of the compiler that these files assume because of the different assembly language directives that diffe
330. s on the application One task may have a few microseconds worth of work to perform while another task may require tens of milliseconds Tasks look like just any other C function with a few small differences There are two types of tasks run to completion the first listing below and infinite loop the second listing below In most embedded systems tasks typically take the form of an infinite loop Also no task is allowed to return as other C functions can Given that a task is a regular C function it can declare local variables When a uC OS III task begins executing it is passed an argument p_arg This argument is a pointer to a void The pointer is a universal vehicle used to pass your task the address of a variable a structure or even the address of a function if necessary With this pointer it is Copyright 2015 Micrium Inc 71 uC OS III User s Manual possible to create many identical tasks that all use the same code or task body but with different run time characteristics For example you may have four asynchronous serial ports that are each managed by their own task However the task code is actually identical Instead of copying the code four times you can create the code for a generic task that receives a pointer to a data structure which contains the serial port s parameters baud rate I O port addresses interrupt vector number etc as an argument In other words you can instantiate the same task c
331. s over allocating resources at compile time Unlimited number of tasks uC OS II supports an unlimited number of tasks From a practical standpoint however the number of tasks is actually limited by the amount of memory both code and data space that the processor has access to Each task requires its own stack space and uC OS III provides features to allow stack growth of the tasks to be monitored at run time uC OS III does not impose any limitations on the size of each task except that there be a minimum size based on the CPU used Copyright 2015 Micrium Inc 21 uC OS III User s Manual Unlimited number of priorities uC OS III supports an unlimited number of priority levels However configuring uC OS III for between 32 and 256 different priority levels is more than adequate for most applications Unlimited number of kernel objects uC OS III allows for any number of tasks semaphores mutual exclusion semaphores event flags message queues timers and memory partitions The user allocates all kernel objects at run time Services uC OS III provides all the services expected from a high end real time kernel such as task management time management semaphores event flags mutexes message queues software timers fixed size memory pools etc Mutual Exclusion Semaphores Mutexes Mutexes are provided for resource management Mutexes are special types of semaphores that have built in priority inheritance which elimin
332. s posted to and the task that called OSFlagPend has its desired bits set or cleared a task status is examined to determine the reason why OSFlagPend is returning to its caller The possibilities are 1 The desired bits were set or cleared 2 The pend was aborted by another task 3 The bits were not set or cleared within the specified timeout 4 The event flag group was deleted When OSFlagPend returns the caller is notified of the above outcome through an appropriate error code 2 If OSFlagPend returns with err set to OS_ERR_NONE you can assume that the desired bits were set or cleared and the task can proceed with servicing the ISR or task that created those events If err contains anything else OSFlagPend either timed out if the timeout argument was non zero the pend was aborted by another task or the event flag group was deleted by another task It is always important to examine the returned error code and not assume everything went as planned To set or clear event flags either from an ISR or a task you simply call OSFlagPost as shown in the listing below Copyright 2015 Micrium Inc 274 uC OS III User s Manual OS_FLAG_GRP MyEventFlagGrp void MyISR void 1 2 3 OS_ERR err OS_FLAGS flags_cur flags_cur OSFlagPost amp MyEventFlagGrp 1 OS_FLAGS x C 2 OS_OPT_POST_FLAG SET 3 amp err 4 Check err Listing Posting flags to an Eve
333. s value should always be 0 if the interrupt handler queue is sized large enough If the value is non zero you should increase the size of the interrupt handler queue A non zero value may also indicate that the processor is not fast enough OSIntQTaskTimeMax This variable contains the maximum execution time of the Interrupt Queue Handler Task Copyright 2015 Micrium Inc 384 uC OS III User s Manual in CPU_TS units The total time also includes the time of any ISR that occurred while the Interrupt Handler task was running Number of Kernel Objects OSFlagQty This variable indicates the number of event flag groups created This variable is declared only if OS_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg h OSMemQty This variable indicates the number of fixed sized memory partitions created by the application This variable is declared only if 0S_CFG_MEM_EN is set to DEF_ENABLED in os_cfg h OSMutexQty This variable indicates the number of mutual exclusion semaphores created by the application This variable is declared only if 0S_CFG_MUTEX_EN is set to DEF_ENABLED in os_cfg h OSSemQty This variable indicates the number of semaphores created by your application This variable is declared only if 0S_CFG_SEM_EN is set to DEF_ENABLED in os_cfg h OSTaskQty The variable contains the total number of tasks created in the application OSTmrQty This variable indicates the number of timers created by the application It is declare
334. s with a Type field which allows it to be recognized by uC OS III as an event flag group In other words other kernel objects will also have a Type as the first member of the structure If a function is passed a kernel object uC OS III will be able to confirm that it is being passed the proper data type assuming Copyright 2015 Micrium Inc 270 uC OS III User s Manual 3 4 5 6 OS_CFG_OBJ_TYPE_CHK_EN is set to 1 in os_cfg h For example if passing a message queue 0S_Q to an event flag service for example OSFlagPend uC OS III will be able to recognize that an invalid object was passed and return an error code accordingly Each kernel object can be given a name to make them easier to be recognized by debuggers or uC Probe This member is simply a pointer to an ASCII string which is assumed to be NUL terminated Because it is possible for multiple tasks to be waiting or pending on an event flag group the event flag group object contains a pend list as described in Pend Lists An event flag group contains a series of flags i e bits and this member contains the current state of these flags The flags can be implemented using either an 8 16 or 32 bit value depending on how the data type 0S_FLAGS is declared in os_type h An event flag group contains a timestamp used to indicate the last time the event flag group was posted to uC OS III assumes the presence of a free running counter that
335. s_cfg h os_cfg_app h Source os_cfg_app c os_core c os_dbg c os_flag c os_int c os_mem c os_msg c os_mutex c os_pend_multi c os_prio c os_q c os_sem c os_stat c os_task c os_tick c os_time c os_tmr c OS_VAR os h os_type h TLS lt tool gt os_tls c Micrium Contains all software components and projects provided by Micrium Software This sub directory contains all software components and projects Copyright 2015 Micrium Inc uC OS III User s Manual ucOS III This is the main wC OS IL directory Cfg Template This directory contains examples of configuration files to copy to the project directory You will then modify these files to suit the needs of the application os_app_hooks c shows how to write hook functions that are called by wC OS III Specifically this file contains eight empty functions os_cfg h specifies which features of uC OS III are available for an application The file is typically copied into an application directory and edited based on which features are required from uC OS III See Appendix B uC OS III Configuration Manual os_cfg_app h is a configuration file that is typically copied into an application directory and edited based on application requirements This file enables the user to determine the size of the idle task stack the tick rate the number of messages available in the message pool and more See Appendix B uC OS II Configuration Manual
336. see os h OSIdleTaskCtr is reset once when uC OS III is initialized oSIdleTaskCtr is used to indicate activity Copyright 2015 Micrium Inc 110 uC OS III User s Manual 3 Copyright 2015 Micrium Inc in the idle task In other words if your code monitors and displays OSIdleTaskCtr you should expect to see a value between xeeeee000 and exFFFFFFFF The rate at which OSIdleTaskCtr increments depend on how busy the CPU is at running the application code The faster the increment the less work the CPU has to do in application tasks OSStatTaskCtr is also typically defined as a 32 bit unsigned integer see os h and is used by the statistic task described later to get a sense of CPU utilization at run time Every time through the loop 0S_IdleTask calls OSIdleTaskHook which is a function that is declared in the uwC OS III port for the processor used OSIdleTaskHook allows the implementer of the uC OS III port to perform additional processing during idle time It is very important for this code to not make calls that would cause the idle task to wait for an event This is generally not a problem as most programmers developing uC OS III ports know to follow this simple rule OSIdleTaskHook may be used to place the CPU in low power mode for battery powered applications and thus avoid wasting energy However doing this means that oSStatTaskCtr cannot be used to measure CPU utilization described later void
337. set to the number of blocks in the partition This is illustrated in the figure below 1 Analog Error Inputs Monitoring Analog Inputs OSSemPend See Counting vA Semaphore j A N r ErrMsgPart l I I gt 0 Figure Using a Memory Partition blocking To obtain a memory block your code simply obtain the semaphore by calling OSSemPend and then calls OSMemGet to receive the memory block Copyright 2015 Micrium Inc 324 uC OS III User s Manual 2 To release a block you simply return the memory block by calling OSMemPut and then signal the semaphore by calling OSSemPost The above operations must be performed in order Note that the user may call OSMemGet and OSMemPut from an ISR since these functions do not block and in fact execute very quickly However you cannot use blocking calls from ISRs Copyright 2015 Micrium Inc 325 uC OS III User s Manual Porting uC OS IIl This chapter describes how to adapt uC OS III to different processors Adapting uC OS III to a microprocessor or a microcontroller is called porting Most of uC OS III is written in C for portability However it is still necessary to write processor speci c code in C and assembly language uC OS III manipulates processor registers which can only be done using assembly language unless the C compiler supports inline assembly language extensions Porting uC OS III to different processors is relatively easy as uC
338. should look at the CPU registers and confirm that they all have their expected value x12121212 for R12 0x05050505 for R5 etc If not then something is not quite right with either OSTaskStkInit or the OS_CTX_RESTORE macro Basically OSTaskStkInit sets up the stack and OS_CTX_RESTORE sets up the registers based on what s on the stack STEP 6 If the CPU registers appear to have their proper value then you can Single Step and execute the Return from Interrupt Exception instruction If all is well you should be looking at the 0S_TickTask code which should look something like this void OS_TickTask void p_arg OS_ERR err CPU_LTS ts p_arg p_arg while DEF_ON void OSTaskSemPend OS_TICK OS_OPT OS_OPT_PEND BLOCKING CPU_LTS amp ts OS_ERR amp err if err OS_ERR_NONE lt Set a BREAKPOINT here if OSRunning OS_STATE_OS RUNNING OS_TickListUpdate i t Copyright 2015 Micrium Inc 374 uC OS III User s Manual If the debugger doesn t show you this code then it s possible that the Pc and Psw are not properly setup on the task stack by OSTaskStkInit If you end up in OS_TickTask your code for OSTaskStkInit and the macro 0S_CTX_RESTORE is correct You should now set a breakpoint on the line following OSTaskSemPend STEP 7 You need to set another breakpoint in oSctxSw as shown below OSCtxSw lt Set a BREAKPOINT here OS_CTX_SAVE OSTCBCurP
339. signal or send a message to a task However if the ISR does not need to call one of these functions consider writing the ISR as a Non Kernel Aware Interrupt Service Routine as described in the next section 159 uC OS III User s Manual 9 10 11 Copyright 2015 Micrium Inc When the ISR completes you must call osIntExit to tell uC OS III that the ISR has completed oSIntExit simply decrements OSIntNestingcCtr and if OSIntNestingCtr reaches 0 this indicates that the ISR is about to return to task level code instead of a previously interrupted ISR uwC OS III will need to determine whether there is a higher priority task that needs to run because of one of the nested ISRs In other words the ISR might have signaled or sent a message to a higher priority task waiting for this signal or message In this case uC OS III will context switch to this higher priority task instead of returning to the interrupted task In this latter case OSIntExit does not actually return but takes a different path If the ISR signaled or sent a message to a lower priority task than the interrupted task OSIntExit returns This means that the interrupted task is still the highest priority task to run and it is important to restore the previously saved registers The ISR performs a return from interrupts and so resumes the interrupted task NOTE From this point on 1 to 6 will be referred to as the JSR Prologue and 9 to 11
340. signaling Function Name OSSemCreate OSSemDel OSSemPend OSSemPendAbort OSSemPost OSSemSet Copyright 2015 Micrium Inc Operation Create a semaphore Delete a semaphore Wait on a semaphore Abort the wait on a semaphore Release or signal a semaphore Force the semaphore count to a desired value 214 uC OS III User s Manual Binary Semaphores A task that wants to acquire a resource must perform a Wait or Pend operation If the semaphore is available the semaphore value is greater than 0 the semaphore value is set to and the task continues execution owning the resource If the semaphore s value is 0 the task performing a Wait on the semaphore is placed in a waiting list wC OS II allows a timeout to be specified If the semaphore is not available within a certain amount of time the requesting task is made ready to run and an error code indicating that a timeout has occurred is returned to the caller A task releases a semaphore by performing a Signal or Post operation If no task is waiting for the semaphore the semaphore value is simply set to 1 If there is at least one task waiting for the semaphore the highest priority task waiting on the semaphore is made ready to run and the semaphore value is not incremented If the readied task has a higher priority than the current task the task releasing the semaphore a context switch occurs and the higher priority task resumes execution Th
341. similarly embraced the second edition of MicroC OS II The Real Time Kernel quickly became common sight on the bookshelves of embedded software developers In fact the MicroC OS II book is the most popular embedded systems book ever sold Micrium expanded Engineers were hired to adapt uC OS II to new hardware platforms and develop a bevy of example projects and application notes A long time friend of mine Christian Legare joined Micrium as Vice President in 2002 and his substantial corporate and technical expertise further accelerated the company s rapid growth Since Christian joined Micrium the company expanded from a one product company to one with a portfolio of 15 products Meanwhile new features were added to satisfy the ever evolving needs of uC OS II users including a variety of new API functions to the operating system and expanding the maximum number of tasks supported by the kernel from 64 to 255 As Micripm s president I remain dedicated to writing world class kernel code most recently uC OS III The product of countless hours of meticulous programming and testing this robust operating system has its roots in wC OS IL yet is an entirely new kernel Addressing input received from customers and all of the lessons learned along the way several additional important wC OS II features were included see Introduction Iam highly circumspect of fads and unproven technology as I write new software Although I like to ke
342. simple program that thinks it has the Central Processing Unit CPU completely to itself On a single CPU only one task executes at any given time A task is also typically implemented as an infinite loop The kernel is responsible for the management of tasks This is called multitasking Multitasking is the process of scheduling and switching the CPU between several tasks The CPU switches its attention between several sequential tasks Multitasking provides the illusion of having multiple CPUs and maximizes the use of the CPU Multitasking also helps in the creation of modular applications One of the most important aspects of multitasking is that it allows the application programmer to manage the complexity inherent in real time applications Application programs are easier to design and maintain when multitasking is used uC OS III is a preemptive kernel which means that uC OS III always runs the most important task that is ready to run as shown in Figure 1 2 Wait for Even 2 Low Priority 1 Event that Task High Priority Task is Waiting for i i Time ONS i 1 i I i i i i High Priori i os 7 Infinite Task Infinite i Loop Loop I 1 i i i i _ lt 6 Low Priority Task 7 Figure C OS III is a preemptive kernel Copyright 2015 Micrium Inc 16 uC OS III User s Manual 1 2 3 4 5 6 7 A low priority task is executing An interrupt occurs and the CPU vecto
343. size also in number of CPU_STK elements When specifying 0S_OPT_TASK_STK_CHK OS_OPT_TASK_STK_CLR in the opt argument of OSTaskCreate WC OS III initializes the task s stack with all zeros uC OS III then initializes the top of the task s stack with a copy of the CPU registers in the same stacking order as if they were all saved at the beginning of an ISR This makes it easy to perform context switches as we will see when discussing the context switching 75 uC OS III User s Manual process For illustration purposes the assumption is that the stack grows from high memory to low memory but the same concept applies for CPUs that use the stack in the reverse order 4 The new value of the stack pointer SP is saved in the TCB Note that this is also called the top of stack 5 The remaining fields of the TCB are initialized task priority task name task state internal message queue internal semaphore and many others Next a call is made to a function that is defined in the CPU port OSTaskCreateHook see os_cpu_c c OSTaskCreateHook is passed the pointer to the new TCB and this function allows you or the port designer to extend the functionality of oSTaskCreate For example one could printout the contents of the fields of the newly created TCB onto a terminal for debugging purposes The task is then placed in the ready list see The Ready List and finally if multitasking has started uC OS III will i
344. skSemPost amp MyTaskTCB 1 OS_OPT_POST_NONE 2 amp err 3 Check err Listing Posting or signaling a Semaphore A task posts or signals the task by calling OSTaskSemPost It is necessary to pass the address of the desired task s OS_TCB and of course the task must exist The next argument specifies how the user wants to post There are only two choices Specify 0S_OPT_POST_NONE which indicates the use of the default option of calling the scheduler after posting the semaphore 264 uC OS III User s Manual Or specify 0S_OPT_POST_NO_SCHED to indicate that the scheduler is not to be called at the end of OSTaskSemPost possibly because there will be additional postings and rescheduling would take place when finished the last post would not specify this option 3 OSTaskSemPost returns an error code based on the outcome of the call If the call was successful err will contain OS_ERR_NONE If not the error code will indicate the reason of the error see uC OS III API Reference for a list of possible error codes for OSTaskSemPost Bilateral Rendez Vous Task Synchronization Two tasks can synchronize their activities by using two task semaphores as shown in the figure below and is called a bilateral rendez vous A bilateral rendez vous is similar to a unilateral rendez vous except that both tasks must synchronize with one another before proceeding A bilateral rendez vous cannot be performed
345. software components and projects uC CPU This is the main wC CPU directory cpu_core c contains C code that is common to all CPU architectures Specifically this file contains functions to measure the interrupt disable time of the CPU_CRITICAL_ENTER and CPU_CRITICAL_EXIT macros a function that emulates a count leading zeros instruction in case the CPU does not provide such an instruction and a few other functions cpu_core h contains function prototypes for the functions provided in cpu_core c and allocation of the variables used by the module to measure interrupt disable time cpu_def h contains miscellaneous define constants used by the wC CPU module Copyright 2015 Micrium Inc 44 uC OS III User s Manual Cfg Template This directory contains a configuration template file cpu_cfg h that must be copied to the application directory to configure the uC CPU module based on application requirements cpu_cfg h determines whether to enable measurement of the interrupt disable time whether the CPU implements a count leading zeros instruction in assembly language or whether it will be emulated in C and more lt architecture gt The name of the CPU architecture that uC CPU was ported to The lt and gt are not part of the actual name lt compiler gt The name of the compiler or compiler manufacturer used to build code for the wC CPU port The lt and gt are not part of the actual na
346. sponds to a task that resides in memory but has not been made available to uC OS III A task is made available to wC OS III by calling a function to create the task OSTaskCreate The task code actually resides in code space but uC OS II needs to be informed about it When it is no longer necessary for wC OS III to manage a task your code can call the 90 Copyright 2015 Micrium Inc uC OS III User s Manual 2 3 4 5 Copyright 2015 Micrium Inc task delete function OSTaskDel OSTaskDe1 does not actually delete the code of the task it is simply not eligible to access the CPU A task is in the Ready state when it is ready to run There can be any number of tasks ready and uC OS III keeps track of all ready tasks in a ready list discussed later This list is sorted by priority The most important ready to run task is placed in the Running state On a single CPU only one task can be running at any given time The task selected to run on the CPU is switched in by uC OS III when the application code calls osstart or when uC OS III calls either oSIntExit or OS_TASK_SW As previously discussed tasks must wait for an event to occur A task waits for an event by calling one of the functions that brings the task to the pending state if the event has not occurred Tasks in the Pending state are placed in a special list called a pend list or wait list associated with the event the task is waiting
347. ssembly language functions were implemented by the port developer of the uC LIB module Copyright 2015 Micrium Inc 1ib_mem_a asm contains optimized versions of the 1ib_mem c functions 48 uC OS III User s Manual Copyright 2015 Micrium Inc 49 uC OS III User s Manual Getting Started with uC OS III uC OS III provides services to application code in the form of a set of functions that perform specific operations uC OS III offers services to manage tasks semaphores message queues mutual exclusion semaphores and more As far as the application is concerned it calls the uC OS III functions as if they were any other functions In other words the application now has access to a library of approximately 70 new functions In this section the reader will appreciate how easy it is to start using uC OS III It is assumed that the project setup files and directories is as described in the previous chapter and that a C compiler exists for the target processor that is in use However this chapter makes no assumptions about the tools or the processor that is used Copyright 2015 Micrium Inc 50 uC OS III User s Manual Single Task Application The listing below shows the top portion of a simple application file called app c ips EEEE EEEE er EEEE EE EEEE EEE EEE EEEE EEE EEE EEEE EEEE EEEE E E EEE E E E E E E E E E E E E E E E E K E k k k k k k k k k k kkk z INCLUDE FILES EEE EEEE EE EEEE EE EEEE EEEE EEEE EEE EEEE E
348. ssing os_mutex c contains code to manage mutual exclusion semaphores see Resource Management os_pend_multi c contains the code to allow code to pend on multiple semaphores or message queues This is described in Pending On Multiple Objects os_prio c contains the code to manage the bitmap table used to keep track of which tasks are ready to run see The Ready List This file can be replaced by an assembly language equivalent to improve performance if the CPU used provides bit set clear and test instructions and a count leading zeros instruction os_q c contains code to manage message queues See Message Passing os_sem c contains code to manage semaphores used for resource management and or synchronization See Resource Management and Synchronization os_stat c contains code for the statistic task which is used to compute the global CPU usage and the CPU usage of each task See About Task Management os_task c contains code for managing tasks using OSTaskCreate OSTaskDel OSTaskChangePrio and many more See About Task Management os_tick c contains code to manage tasks that have delayed themselves or that are pending on a kernel object with a timeout See About Task Management 40 uC OS III User s Manual os_time c contains code to allow a task to delay itself until some time expires See Time Management os_tmr c contains code to manage software timers See Timer Management os_var c contains the uC OS
349. stored in this variable A debugger or uC Probe can be used to indicate the time taken for a message to arrive by displaying this field This field is only available if setting 0S_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h MsgQPendTimeMax This field contains the maximum amount of time it takes for a message to arrive It is a peak detector of the value of MsgQPendTime The peak can be reset by calling OSStatReset This field is only available if setting 0S_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h RegTb1 Copyright 2015 Micrium Inc 103 uC OS III User s Manual This field contains a table of registers that are task specific These registers are different than CPU registers Task registers allow for the storage of such task specific information as task ID errno common in some software components and more Task registers may also store task related data that needs to be associated with the task at run time Note that the data type for elements of this array is OS_REG which can be declared at compile time to be nearly anything However all registers must be of this data type This field only exists in a TCB if task registers are enabled at compile time OS_CFG_TASK_REG_TBL_SIZE is greater than 0 in os_cfg h FlagsPend When a task pends on event flags this field contains the event flags i e bits that the task is pending on This field only exists in a TCB if event flags services are enabled at compile tim
350. t controller will latch them and properly prioritize the interrupts The CPU vectors to a single interrupt handler address In other words all interrupts are to be handled by this one interrupt handler The ISR executes the ISR prologue code needed by uwC OS III as previously described This ensures that all ISRs will be able to make uC OS III post calls You call a uC OS III C handler which will continue processing the ISR This makes the code easier to write and read Notice that interrupts are not re enabled The uC OS II C handler then interrogates the interrupt controller and asks it Who caused the interrupt The interrupt controller will either respond with a number to N 1 or with the address of the interrupt handler for the highest priority interrupting device Of course the uC OS III C handler will know how to handle the specific interrupt controller since the C handler is written specifically for that controller 165 uC OS III User s Manual If the interrupt controller provides a number between 0 and N 1 the C handler simply uses this number as an index into a table in ROM or RAM containing the address of the interrupt service routine associated with the interrupting device A RAM table is handy to change interrupt handlers at run time For many embedded systems however the table may also reside in ROM If the interrupt controller responds with the address of the interrupt service routine t
351. t happened while the task was running Copyright 2015 Micrium Inc 356 uC OS III User s Manual We then take a timestamp to mark the beginning of the task being switched in 3 OSTaskSwHook then stores the highest interrupt disable time into the os_TcB of the task being switched out This allows a debugger or uC Probe to display maximum interrupt disable time on a per task basis 4 OSTaskSwHook then captures the highest scheduler lock time and stores that in the os_TCB of the task being switched out 5 If Redzone Stack Checking is enabled the hook checks to see if the task that is about to be switched out has overflowed its stack OSTimeTickHook This function is called by OSTimeTick and is called before any other code is executed in OSTimeTick The template file contains the following code If the application code defines an application hook function then it is called as shown void OSTimeTickHook void if OS_CFG_APP_HOOKS_EN gt u if OS_AppTimeTickHookPtr OS_APP_HOOK_VOID OS_AppTimeTickHookPtr endif J Listing ypical OSTimeTickHook os_cpu_a asm This file contains the implementation of the following assembly language functions OSStartHighRdy This function is called by osstart to start multitasking osstart will have determined the highest priority task OSTCBHighRdyPtr will point to the oS_TcB of that task that was created prior to calling osstart and will sta
352. t share variables or data structures with an ISR you can disable and enable uC OS IIP s scheduler while accessing the resource as shown in the listing below void YourFunction void OS_ERR err 1 OSSchedLock amp err 2 Access the resource 3 OSSchedUnlock amp err 4 Listing Accessing a resource with the scheduler locked Using this method two or more tasks share data without the possibility of contention Note that while the scheduler is locked interrupts are enabled and if an interrupt occurs while in the critical section the ISR is executed immediately At the end of the ISR the kernel always returns to the interrupted task even if a higher priority task is made ready to run by the ISR Since the ISR returns to the interrupted task the behavior of the kernel is similar to that of a non preemptive kernel while the scheduler is locked OSSchedLock and OSSchedUnlock can be nested up to 250 levels deep The scheduler is invoked only when osSchedUnlock is called the same number of times the application called OSSchedLock After the scheduler is unlocked wC OS III performs a context switch if a higher priority task is ready to run uC OS III will not allow the user to make blocking calls when the scheduler is locked If the application were able to make blocking calls the application would most likely fail Although this method works well you can avoid disabling the scheduler as it defeats the
353. t there is no check to see whether the proper memory block is being returned to the proper partition assuming you have multiple different partitions It is therefore important to be careful as is necessary when designing embedded systems You pass the pointer to the data area that is allocated so that it can be returned to the pool Note that a void is assumed You would examine the returned error code to ensure that the call was successful 321 uC OS III User s Manual Using Memory Partitions Memory management services are enabled at compile time by setting the configuration constant OS_CFG_MEM_EN to DEF_ENABLED in os_cfg h There are a number of operations to perform on memory partitions as summarized in the table below Function Name Operation OSMemCreate Create a memory partition OSMemGet Obtain a memory block from a memory partition OSMemPut Return a memory block to a memory partition Table Memory Partition API summary OSMemCreate can only be called from task level code but oSMemGet and OSMemPut can be called by Interrupt Service Routines ISRs The listing show in Returning a Memory Block to a Partition shows an example of how to use the dynamic memory allocation feature of C OS III as well as message passing capabilities see In this example the task on the left reads and checks the value of analog inputs pressures temperatures and voltage and sends a message to the second t
354. table Semaphores Event Flags No Yes Yes Message Mailboxes Yes Yes No not needed Message Queues Yes Yes Yes Fixed Sized Memory No Yes Yes Management Signal a task without No No Yes requiring a semaphore Option to Post without No No Yes scheduling Send messages to a No No Yes task without requiring a message queue Software Timers No Yes Yes Task suspend resume No Yes Yes Nestable Deadlock prevention Yes Yes Yes Scalable Yes Yes Yes Code Footprint 3K to 8K 6K to 26K 6K to 24K Data Footprint 1K 1K 1K ROMable Yes Yes Yes Run time configurable No No Yes Compile time Yes Yes Yes configurable ASCII names for each No Yes Yes kernel object Copyright 2015 Micrium Inc 26 uC OS III User s Manual Pend on multiple objects Task registers Built in performance measurements User definable hook functions Time stamps on posts Built in Kernel Awareness support Optimizable Scheduler in assembly language Catch a task that returns Tick handling at task level Source code available Number of services MISRA C 1998 MISRA C 2004 DO178B Level A and EUROCAE ED 12B Medical FDA pre market notification 510 k and pre market approval PMA SIL3 SIL4 IEC for transportation and nuclear systems IEC 61508 No No No No No No No No No Yes 20 No No No No No No Yes Yes Limited Yes No Yes No No No Yes 90 Yes except 10
355. tant O0S_CFG_TMR_EN defined in os_cfg h Specifically the code is included in the build when OS_CFG_TMR_EN is set to DEF_ENABLED Timers are countdown counters that perform an action when the counter reaches zero The action is provided by the user through a callback function A callback function is a function that the user declares and that will be called when the timer expires The callback can thus be used to turn on or off a light a motor or perform whatever action needed It is important to note that the callback function is called from the context of the timer task The application programmer may create an unlimited number of timers limited only by the amount of available RAM Timer management is fully described in Timer Management and the timer services available to the application programmer are described in the wC OS III API Reference OS_TmrTask is a task created by uC OS III this assumes setting 0S_CFG_TMR_EN to DEF_ENABLED in os_cfg h and its priority is configurable by the user through uC OS II s configuration constant OS_CFG_TMR_TASK_PRIO found in os_cfg_app h OS_TmrTask is typically set to a low to medium priority OS_TmrTask is a periodic task using the same interrupt source that was used to generate clock ticks However timers are generally updated at a slower rate i e typically 10 Hz This is accomplished by dividing down the timer tick rate in software In other words if the tick rate is 1000 Hz and the desi
356. tarts by checking the arguments passed to this function to 258 uC OS III User s Manual Copyright 2015 Micrium Inc make sure they have valid values assuming OS_CFG_OBJ_TYPE_CHK_EN is set to DEF_ENABLED in os_cfg h If the semaphore counter Ctr of OS_SEM is greater than zero the counter is decremented and OSSemPend returns which indicates that the signal occurred This is the outcome that the caller expects If the semaphore counter is zero this indicates that the signal has not occurred and the calling task might need to wait for the semaphore to be released If you specify OS_OPT_PEND_NON_BLOCKING as the option the task is not to block oSSemPend returns immediately to the caller and the returned error code will indicate that the signal did not occur If you specify OS_OPT_PEND_BLOCKING as the option the calling task will be inserted in the list of tasks waiting for the semaphore to be signaled The task is inserted in the list by priority order with the highest priority task waiting on the semaphore at the beginning of the list as shown in the figure at the end of this page If you further specify a non zero timeout the task will also be inserted in the tick list A zero value for a timeout indicates that the calling task is willing to wait forever for the semaphore to be signaled The scheduler is then called since the current task is not able to run it is waiting for the semaphore to be signaled The scheduler wil
357. task assuming interrupts are enabled The ISR executes and posts the semaphore At this point the semaphore count is 1 4 6 uC OS III is called at the end of the ISR to see if the ISR caused a higher priority task to be ready to run Since the ISR was an event that a lower priority task was waiting for uC OS III will resume execution of the higher priority task at the exact point where it Copyright 2015 Micrium Inc 253 uC OS III User s Manual 7 8 9 10 12 13 14 15 16 17 was interrupted The high priority task is resumed and continues execution The interrupt occurs a second time The ISR executes and posts the semaphore At this point the semaphore count is 2 uC OS III is called at the end of the ISR to see if the ISR caused a higher priority task to be ready to run Since the ISR was an event that a lower priority task was waiting for uC OS III resumes execution of the higher priority task at the exact point where it was interrupted The high priority task resumes execution and actually terminates the work it was doing This task will then call one of the uC OS III services to wait for its event to occur uC OS III will then select the next most important task which happens to be the task waiting for the event and will context switch to that task The new task executes and will know that the ISR occurred twice since the semaphore count is two The task w
358. te in periodic mode The value is expressed in multiples of 1 0S_CFG_TMR_TASK_RATE_HZ of a second see os_cfg_app h 200 uC OS III User s Manual 10 The opt field contains options that are passed to OSTmrCreate 11 The State field represents the current state of the timer see the figure in Timer States above Even if the internals of the os_TMR data type are understood the application code should never access any of the fields in this data structure directly Instead you should always use the Application Programming Interfaces APIs provided with wC OS III Timer Task OS_TmrTask is a task created by uC OS III assumes setting 0S_CFG_TMR_EN to DEF_ENABLED in os_cfg h and its priority is configurable by the user through wC OS III s configuration file os_cfg_app h see OS_CFG_TMR_TASK_PRIO OS_TmrTask is typically set to a medium priority OS_TmrTask is a periodic task and uses the same interrupt source used to generate clock ticks However timers are generally updated at a slower rate i e typically 10 Hz or so and thus the timer tick rate is divided down in software If the tick rate is 1000 Hz and the desired timer rate is 10 Hz then the timer task will be signaled every 100th tick interrupt as shown in the 10 to 1000 Hz figure below Signaled every OS_CFG_TICK_RATE_HZ OS_CFG_TMR_TASK RATEHZ CUT tick interrupt List of timers to update Figure Tick ISR and Timer Task relationsh
359. tep to be in increments of 65 milliseconds However I d probably set the maximum increment to 50 making this a clean multiple of 1 second Copyright 2015 Micrium Inc 118 uC OS III User s Manual The Statistic Task uC OS III contains an internal task that provides such run time statistics as overall CPU utilization 0 00 to 100 00 per task CPU utilization 0 00 to 100 00 and per task stack usage As of V3 03 00 CPU utilization is represented as a integer from 0 to 10 000 0 00 to 100 00 Prior to V3 03 00 CPU utilization was represented an integer ranging from 0 to 100 The statistic task is optional in a wC OS II application and its presence is controlled by a compile time configuration constant 0S_CFG_STAT_TASK_EN defined in os_cfg h Specifically the code is included in the build when 0S_CFG_STAT_TASK_EN is set to DEF_ENABLED Also the priority of this task and the location and size of the statistic task s stack is configurable via OS_CFG_STAT_TASK_PRIO declared in os_cfg_app h If the application uses the statistic task it should call osstatTaskCPUUsageInit from the first and only application task created in the main function as shown in the listing below The startup code should create only one task before calling osstart The single task created is of course allowed to create other tasks but only after calling osstatTaskCPUUsageInit Copyright 2015 Micrium Inc 119 uC OS III User s Manual
360. ters should contain the proper register values similar to what we had when we restored the CPU registers for OSTickTask but this time it s for OS_IdleTask STEP 11 Step Into the return from interrupt exception instruction and the CPU should now jump into the idle task os_core c as shown below You should then set a breakpoint as shown void OS_IdleTask void p_arg CPU_SR_ALLOC p_arg p_arg while DEF_ON CPU_CRITICAL_ENTER lt Set a BREAKPOINT here OSIdleTaskCtr if OS_CFG_STAT_TASK_EN gt u OSStatTaskCtr endif CPU_CRITICAL_EXIT lt strong gt OSIdleTaskHook lt strong gt STEP 12 Step Into the idle task and then Step Into OSIdleTaskHook Recall that I had you modify the idle task hook as shown below What we re doing here is simulate the occurrence of the tick interrupt Copyright 2015 Micrium Inc 376 uC OS III User s Manual void OSIdleTaskHook void lt strong gt OSTimeTick lt strong gt if OS_CFG_APP_HOOKS EN gt u if OS_AppIdleTaskHookPtr OS_APP_HOOK_VOID 0S_AppIdleTaskHookPtr endif Listing paramCaptionText STEP 13 Have your debugger run the code at full speed You should actually hit the breakpoint in osctxSw as shown below What happened here is that wC OS III signaled the tick task and since the tick task is more important than the idle task wC OS HI is switching back to the tick task O
361. the code to allocate a more reasonable value either increase or decrease the amount of stack space for each task For this to be effective however you need to run the application long enough for the stack to grow to its highest value This is illustrated in the figure below uC OS III provides a function that performs this calculation at run time OSTaskStkChk and in fact this function is called by 0S_StatTask to compute stack usage for every task created in the application to be described later Copyright 2015 Micrium Inc 86 uC OS III User s Manual Copyright 2015 Micrium Inc Stack RAM amp MyTaskStk 0 0 ti 0 0 0 size free used 0 0 0 free 0 tack initialized to all zeros 0 0 0 0 E Worst Case stack growth 0 Current used Stack Usage Stack Growth High Memory lt 4 CPU_STK gt Figure Software detection of stack overflows walking the stack 87 uC OS III User s Manual Task Management Services uC OS III provides a number of task related services to call from the application These services are found in os_task c and they all start with OSTask The type of service they perform groups task related services Group General Signaling a Task See Synchronization Sending Messages to a Task See Message Passing Functions OSTaskCreate OSTaskDel OSTaskChangePrio OSTaskRegSet OSTaskRegGet OSTaskSuspend OSTaskResume OSTaskTimeQuantaSet OSTaskSemP
362. the new current task OS_CTX_RESTORE is a macro see os_cpu_a inc that restores the context of the CPU from the new task s stack For our generic 32 bit CPU 0S_CTX_RESTORE would pop CPU registers R13 through R from the stack in that order The Return from Interrupt Exception restores the Program Counter PC and the Status Register SR in a single instruction At this point the new task will resume execution exactly where it was preempted Os _cpu_a inc This file contains the implementation of assembly language macros that are used to simplify the implementation of os_cpu_a asm A macro replaces many assembly language instructions with a single macro invocation Copyright 2015 Micrium Inc 361 uC OS III User s Manual OS_CTX_SAVE This macro is used to save the CPU context onto the current stack OS_CTX_SAVE needs to save the CPU registers in the same order as they are pushed in OSTaskStkInit which is described later OS_CTX_SAVE only saves the CPU registers that are not automatically saved by the CPU when the CPU accepts an interrupt In other words if the CPU automatically saves the Psw and PC onto the stack upon initiating an ISR then 0S_CTX_SAVE only needs to save the remaining CPU registers OS_CTX_SAVE Save all the CPU registers onto the current task stack in the same order as in OSTaskStkInit Listing OS_CTX_SAVE macro Pseudo Code Assuming our generic 32 bit CPU 0S_CTX_SAVE would be impl
363. the saved CPU registers Perform a return from interrupt to resume the interrupted task 161 uC OS III User s Manual Processors with Multiple Interrupt Priorities There are some processors that actually supports multiple interrupt levels as shown in Figure 9 2 HIGH Priority Non Kernel Aware 3 Interrupts Interrupt 1 Priorities K erne Aware 2 Interrupts Task Priorities OS_CFG PRIO_MAX 3 LOW OS_CFG_PRIO_MAX 1 Priority a aa Figure Kernel Aware and Non Kernel Aware Interrupts 1 Here we are assuming that the processor supports 16 different interrupt priority levels Priority 0 is the lowest priority while 15 is the highest As shown interrupts are always higher in priority than tasks assuming interrupts are enabled 2 The designer of the product decided that interrupt levels 0 through 12 will be allowed to make uC OS III post calls to notify tasks that are assigned to service these interrupts It s important to note that disabling interrupts when entering critical sections for task aware interrupts means raising the interrupt mask to level 12 this is configured in Copyright 2015 Micrium Inc 162 uC OS III User s Manual 3 uC CPU with the CPU_CFG_KA_IPL_BOUNDARY configuration constant In other words interrupt levels 0 through 11 would be disabled but levels 12 and above would be allowed ISRs at interrupt levels 12 through 15 will not be allowed to make any pC
364. the task The base address is always amp MyTaskStk TLS_Tb1 This field typically contains an array of pointers and is used by compilers for thread safety as described in Chapter 20 Thread Safety of the Compiler s Run Time Library TaskEntryAddr This field contains the entry address of the task As previously mentioned a task is declared as shown below and this field contains the address of MyTask void MyTask void p_arg TaskEntryArg This field contains the value of the argument that is passed to the task when the task starts As previously mentioned a task is declared as shown below and this field contains the value of p_arg void MyTask void p_arg PendDataTb1Ptr Copyright 2015 Micrium Inc 99 uC OS III User s Manual uC OS III allows the task to pend on any number of semaphores or message queues simultaneously This pointer points to a table containing information about the pended objects This is described in Chapter 10 Pend Lists PendOn This field indicates what the task is pending on and contains one of the following values declared in os h OS_TASK_PEND_ON_NOTHING OS_TASK_PEND_ON_FLAG OS_TASK_PEND_ON_TASK_Q OS_TASK_PEND_ON_MULTI OS_TASK_PEND_ON_MUTEX OS_TASK_PEND_ON_Q OS_TASK_PEND_ON_SEM OS_TASK_PEND_ON_TASK_SEM PendStatus This field indicates the outcome of a pend and contains one of the values declared in os h OS_STATUS_PEND_OK OS_STATUS_PEND_ABORT OS_STATUS_PEND_
365. time OS_CFG_TASK_SUSPEND_EN is set to DEF_ENABLED in os_cfg h CPUUsage This field is computed by 0S_StatTask if OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CPUUsage contains the CPU usage of a task in percent 0 to 100 As of version V3 03 00 cPUUsage is multiplied by 100 In other words 10000 represents 100 00 CPUUsageMax This field contains the maximum i e peak detector CPU usage in percentage for the task and is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h This field is computed by 0S_StatTask As of version V3 03 00 cPUUsageMax represents percentage multiplied by 100 In other words 10000 represents 100 00 The peak can be reset by calling osstatReset CtxSwCtr This field keeps track of how often the task has executed not how long it has executed This field is generally used by debuggers or run time monitors to see if a task is executing the value of this field would be non zero and would be incrementing The field is enabled at compile time when 0S_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg h CyclesDelta CyclesDelta is computed during a context switch and contains the value of the current time stamp obtained by calling 0S_TS_GET minus the value of cyclesStart This field Copyright 2015 Micrium Inc 105 uC OS III User s Manual is generally used by debuggers or a run time monitor to see how long a task had control of the CPU until it
366. tions are described in uC OS III API Reference os_cpu_c c can declare any functions needed by the port however the functions described below are mandatory These functions are already implemented in the template file but those can certainly be extended as needed You should not have to change this file unless you have specific requirements OSIdleTaskHook This function is called repeatedly when uC OS III does not have any task ready to run The port implemented might choose to put the processor in low power mode if the product being designed is battery operated However it would be preferable to defer this choice to the application level You can do this by putting the processor in low power mode in a function called App_OS_IdleTaskHook and let the application decide whether or not it is appropriate to place the processor in low power mode The template file contains the following code Copyright 2015 Micrium Inc 349 uC OS III User s Manual void OSIdleTaskHook void if OS_CFG_APP_HOOKS_EN gt u if OS_AppIdleTaskHookPtr OS_APP_HOOK_VOID 0S_AppIdleTaskHookPtr endif Listing Typical OSIdleTaskHook OSInitHook This function is called by OsInit at the very beginning of osInit This is done to allow the port implemented to add functionality to the port while hiding the details from the wC OS III user For one thing the port implementer could setup an ISR stack in OSInitHook The tem
367. tkLimitPtr Why Because if the sequence is not followed the exception could be generated as soon as the stack pointer or the stack overflow detection register is changed You can avoid this problem by first changing the stack overflow detection register to point to a location that ensures the stack pointer is never invalid thus the NULL as described above Note that I assumed here that the stack grows from high memory to low memory but the concept works in a similar fashion if the stack grows in the opposite direction 3 Custom software based stack overflow detection Whenever uC OS III switches from one task to another it calls a hook function OSTaskSwHook which allows the uC OS II port programmer to extend the capabilities of the context switch function So if the processor doesn t have hardware stack pointer overflow detection it s still possible to simulate this feature by adding code in the context switch hook function and perform the overflow detection in software Specifically before a task is switched in the code should ensure that the stack pointer to load into the CPU does not exceed the limit placed in StkLimitPtr Because the software implementation cannot detect the stack overflow as soon as the stack pointer exceeds the value of StkLimitPtr it is important to position the value of StkLimitPtr in the stack fairly far from amp MyTaskStk as shown in the figure below A software implementatio
368. to 1 and this will cause LED 1 to toggle Exactly which LED is LED 1 That depends on the BSP developer Specifically access to LEDs are encapsulated through the functions BSP_LED_On BSP_LED_Off and BSP_LED_Toggle Also for sake of portability we prefer to assign LEDs logical values 1 2 3 etc instead of specifying which port and which bit on each port Finally each task in the application must call one of the uwC OS III functions that will cause the task to wait for an event The task can wait for time to expire by calling OSTimeDly Or OSTimeDlyHMSM or wait for a signal or a message from an ISR or another task In the code shown we used OSTimeDlyHMSM which allows a task to be suspended until the specified number of hours minutes seconds and milliseconds have expired In this case 100 ms Time Management provides additional information about time delays 57 uC OS III User s Manual Multiple Tasks Application with Kernel Objects The code of the listings below shows a more complete example and contains three tasks a mutual exclusion semaphore and a message queue KK KK K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K OK K i INCLUDE FILES FKK KK K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K
369. to DEF_ENABLED in os_cfg h the port developer needs to implement the BSP_OS_DynTickInit BSP_OS_DynTickHandler BSP_OS_TickGet and BSP_OS_TickNextSet functions Otherwise the Dynamic Tick feature will not function properly The following sections contain descriptions of the Dynamic Tick functions BSP_OS_DynTicklnit Like the periodic tick this function must be called by the first task that executes under uC OS III and after you called cPU_Init The pseudo code for this function is similar to the code for the Periodic tick and is shown in the listing below void BSP_OS DynTickInit void Install the interrupt vector BSP_OS DynTickHandler for the timer used to generate tick interrupts Configure the timer to generate interrupts but deactivate its period Enable timer interrupts Listing BSP_OS_DynTickInit Pseudo Code Copyright 2015 Micrium Inc 346 uC OS III User s Manual BSP_OS_DynTickHandler The Dynamic tick ISR is executed when a dynamic tick interrupt occurs This should occur after at least Tick Step OS ticks have elapsed The ISR must inform uC OS III using the OSTimeDynTick function about the effective number of OS ticks that has elapsed since the last time a Dynamic Tick interrupt occurred The Dynamic Tick timer is programmed using the BSP_OS_DynTickNextSet function described below void BSP_OS_DynTickHandler void OSIntEnter Clear tick interrupt OSTimeDynTick Elapsed OS
370. tr gt StkPtr SP OSTaskSwHook OSPrioCur OSPrioHighRdy OSTCBCurPtr OSTCBHighRdyPtr SP OSTCBCurPtr gt StkPtr OS_CTX_RESTORE Return from Interrupt Exception You can now run the code at full speed Because of the breakpoint in osctxSw the debugger should stop and show you the code for osctxsw Basically what s happening here is that OS_TickTask will be waiting for the tick ISR to signal the task that a tick has expired Since we haven t setup the tick interrupt not yet anyway OS_TickTask would never get to execute However I had you modify the idle task hook to simulate signaling the tick task so uC OS III will eventually switch back to this code In the meantime wC OS III will switch to the next task that s ready to run This happens to be the idle task We ll be following the code until we get to 0S_IdleTask STEP 8 You can Step Over 0S_CTX_SAVE and verify that the stack pointed to by sP contains the value of the CPU registers saved in the same order as they are in OSTaskStkInit In fact you can verify this when context switches back out of the idle task in just a few more steps STEP 9 Step Into the code one more time and verify that the SP was saved in OSTickTaskTCB StkPtr Copyright 2015 Micrium Inc 375 uC OS III User s Manual STEP 10 Step Into the code and stop just before executing the Return from Interrupt Exception instruction At this point the CPU regis
371. ts in an assembly language file starts with a semicolon In assembly language there are a number of directives that tell the assembler how to process certain pieces of information Below is a list of such directives and their meaning The assembler you use may use different syntax for these directives but overall they should work and mean the same The PUBLIC directive indicates that you are declaring a symbol to be globally available In other words it s public for all files to see The EXTERN directive indicates that the definition of a symbol is found in another file external to this file The CODE directive indicates that what follows needs to be linked with the rest of your executable code In other words we are not declaring any variables The macro directive is used to define an assembly language macro A macro is basically a series of assembly language instructions that will be replacing the macro name In other words when the assembler sees the macro name being invoked in your code it will replace the macro name with the instructions that are associated with the macro Macros are useful to avoid repeating sequences of assembly language instructions The END directive is generally the last assembly language statement in an assembly language file The END directive should not appear at the end of a file that defines macros because macro files are generally included in other assembly langu
372. ture of uC OS III multiple tasks at the same priority create longer critical sections However if there are only a few tasks at the same priority interrupt latency will be relatively small If the user does not create multiple tasks at the same priority the Direct Post Method is recommended If multiple tasks are waiting on different events going through all of the tasks waiting for events requires a fair amount of processing time which means longer critical sections If only a few tasks approximately one to five are waiting on an event flag group the critical section will be short enough to use the Direct Post Method Pending on multiple objects is probably the most complex feature provided by uC OS III and requires interrupts to be disabled for fairly long periods of time when using the Direct Post Method If pending on multiple objects the Deferred Post Method is highly recommended If the application does not use this feature the user may select the Direct Post Method uC OS III disables interrupts while processing a post to multiple tasks in a broadcast If not using the broadcast option use the Direct Post Method Note that broadcasts only apply to semaphores and message queues Table C OS III features to avoid when using the Direct Post Method Copyright 2015 Micrium Inc 175 uC OS III User s Manual The Clock Tick Periodic Tick uC OS III based systems generally require the presence of a periodic time sou
373. uC OS III maximizes the use of the CPU by selecting the next most important task which executes until the ISR occurs In fact the ISR may not occur for many milliseconds and during that time the CPU will work on other tasks As far as the task that is waiting for the semaphore is concerned it does not consume CPU time while it is waiting Finally the task waiting for the semaphore will execute immediately after the event occurs assuming it is the most important task that needs to run Copyright 2015 Micrium Inc 252 uC OS III User s Manual Credit Tracking As previously mentioned a semaphore remembers how many times it was signaled or posted to In other words if the ISR occurs multiple times before the task waiting for the event becomes the highest priority task the semaphore will keep count of the number of times it was signaled When the task becomes the highest priority ready to run task it will execute without blocking as many times as there were ISRs signaled This is called Credit Tracking and is illustrated in the figure below and described below Sem Sem 3 9 ISR eis 4 10 Y HC OS III 2 8 T 15 The Real Time Kernel 4 12 14 M t High Priority W _ i Task OP 7 D 13 16 Low Priority a7 Taek OSSemPend Figure Semaphore Credit Tracking 1 A high priority task is executing 2 3 An event meant for a lower priority task occurs which preempts the
374. u_a asm Copyright 2015 Micrium Inc 149 uC OS III User s Manual OSCtxSw OSCtxSw see os_cpu_a asm is called when the task level scheduler OSSched determines that a new high priority task needs to execute The figure below shows the state of several uC OS III variables and data structures just prior to calling osctxSw 1 2 3 Copyright 2015 Micrium Inc OS_TCB OS_TCB RAM __ stkPtr OsTCBCurPtr OSTCBHighRdyPtr gt stkPtr J o 3 CPU Memory Oa Oe Oe Ou Oe Oe O e Ceo O Oo Oe _ a L Reo memory Figure Variables and data structures prior to calling OSCtxSw OSTCBCurPtr points to the oS_TcB of the task that is currently running and that called OSSched OSSched finds the new task to run by having OSTCBHighRdyPtr point to its OS_TCB OSTCBHighRdyPtr gt StkPtr points to the top of stack of the new task to run 150 uC OS III User s Manual 4 When uC OS II creates or suspends a task it always leaves the stack frame to look as if an interrupt just occurred and all the registers saved onto it This represents the expected state of the task so it can be resumed 5 The CPU s stack pointer points within the stack area i e RAM of the task that called OSSched Depending on how osctxSw is invoked the stack pointer may be pointing at the return address of OSCtxSw The figure below shows the steps involved in performing the context
375. ue is set in os_cfg h ROM Variable Data Type Value OSDbg_TmrEn CPU_INT 8U OS_CFG_TMR_EN When 1 this variable indicates that oSTmr services are available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TmrDelEn CPU_INT 8U OS_CFG_TMR_DEL_EN When 1 this variable indicates that the function OSTmrDe1 is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_TmrSize CPU_INT16U sizeof OS_TMR This variable indicates the RAM footprint in bytes of an OS_TMR data structure ROM Variable Data Type Value OS_VERSION OSDbg_VersionNbr CPU_INT16U This variable indicates the current version of uC OS II multiplied by 10000 For example version 3 02 00 will show as 30200 ROM Variable Data Type Value OSDbg DataSize CPU_INT32U Size of all RAM variables This variable indicates the RAM footprint in bytes of the internal wC OS II variables for the current configuration Copyright 2015 Micrium Inc 409 uC OS III User s Manual os_cfg_app c Static As with os_dbg c os_cfg_app c defines a number of ROM variables These variables however reflect the run time configuration of an application Specifically the user will be able to know the RAM footprint in bytes of uC OS III task stacks the message pool and more Below is a list of ROM variables provided in os_app_cfg c along with their descriptions These variables represent ap
376. uires that interrupt service routines be written in assembly language However if a C compiler supports in line assembly language the ISR code can be placed directly into a C source file The pseudo code for a typical ISR when using uC OS III is shown in Listing 9 1 MyISR 1 Disable all kernel aware interrupts 2 Save the CPU registers 3 OSIntNestingCtr 4 if OSIntNestingCtr 1 5 OSTCBCurPtr gt StkPtr Current task s CPU stack pointer register value Clear interrupting device 6 Re enable kernel aware interrupts optional 7 Call user ISR 8 OSIntExit 9 Restore the CPU registers 10 Return from interrupt 11 1 2 3 Copyright 2015 Micrium Inc Listing ISRs under pC OS III assembly language As mentioned above an ISR is typically written in assembly language MyISR corresponds to the name of the handler that will handle the interrupting device It is important that all kernel aware interrupts are disabled before going any further Some processors have interrupts disabled whenever an interrupt handler starts Others require the user to explicitly disable interrupts as shown here This step may be tricky if a processor supports different interrupt priority levels However there is always a way to solve the problem The first thing the interrupt handler must do is save the context of the CPU onto the interrupted task s stack On some processors this occurs automatic
377. um com for additional details and pricing Copyright 2015 Micrium Inc uC OS III User s Manual uC OS Ill uC OS III is a scalable ROMable preemptive real time kernel that manages an unlimited number of tasks uC OS III is a third generation kernel offering all of the services expected from a modern real time kernel including resource management synchronization inter task communication and more However uC OS III also offers many unique features not found in other real time kernels such as the ability to perform performance measurements at run time directly signal or send messages to tasks and pending i e waiting on such multiple kernel objects as semaphores and message queues Here is a list of features provided by wC OS III Source Code wC OS II is provided in ANSI C source form The source code for uC OS IH is arguably the cleanest and most consistent kernel code available Clean source is part of the corporate culture at Micrium Although many commercial kernel vendors provide source code for their products unless the code follows strict coding standards and is accompanied by complete documentation with examples to show how the code works these products may be cumbersome and difficult to harness With this book you will gain a deep understanding of the inner workings of uC OS III which will protect your investment Intuitive Application Programming Interface API uC OS III is highly intuitive Once familiar with the
378. upts are disabled This is called interrupt disable time All real time systems disable interrupts to manipulate critical sections of code and re enable interrupts when critical sections are completed The longer interrupts are disabled the higher the interrupt latency Interrupt response is defined as the time between the reception of the interrupt and the start of the user code that handles the interrupt Interrupt response time accounts for the entire overhead involved in handling an interrupt Typically the processor s context CPU registers is saved on the stack before the user code is executed Interrupt recovery is defined as the time required for the processor to return to the interrupted code or to a higher priority task if the ISR made such a task ready to run Task latency is defined as the time it takes from the time the interrupt occurs to the time task level code resumes Copyright 2015 Micrium Inc 155 uC OS III User s Manual Handling CPU Interrupts There are many popular CPU architectures on the market today and most processors typically handle interrupts from a multitude of sources For example a UART receives a character an Ethernet controller receives a packet a DMA controller completes a data transfer an Analog to Digital Converter ADC completes an analog conversion a timer expires etc In most cases an interrupt controller captures all of the different interrupts presented to the processor as sho
379. ust agree as to the meaning of the message The size of the message received is saved in msg size Note that p_msg could point to a buffer and msg_size would indicate the size of this buffer Also when the message is received ts will contain the timestamp of when the message was sent A timestamp is the value read from a fairly fast free running timer The timestamp is typically an unsigned 32 bit or more value 63 uC OS III User s Manual 2 3 Copyright 2015 Micrium Inc Knowing when the message was sent allows the user to determine how long it took this task to get the message This is done by reading the current timestamp and subtracting the timestamp of when the message was sent allows users to know how long it took for the message to be received Note that the receiving task may not get the message immediately since ISRs or other higher priority tasks might execute before the receiver gets to run Here you would add your own code to process the received message 64 uC OS III User s Manual Critical Sections A critical section of code also called a critical region is code that needs to be treated indivisibly There are many critical sections of code contained in wC OS IIL If a critical section is accessible by an Interrupt Service Routine ISR and a task then disabling interrupts is necessary to protect the critical region If the critical section is only accessible by task level cod
380. utton switches initializes peripheral clocks etc providing nearly any functionality to multiple products projects Names of typical BSP files include bsp c bsp h bsp_os c bsp_os h bsp_os_a a cpu_bsp c cpu_bsp h All files are generally placed in a directory as follows Micrium Software EvalBoards lt manufacturer gt lt board_name gt BSP Here lt manufacturer gt is the name of the evaluation board or target board manufacturer and lt board_name gt is the name of the evaluation or target board BSPs are typically written in C and are generally portable bsp c and bsp h These files normally contain functions and their definitions such as Copyright 2015 Micrium Inc 366 uC OS III User s Manual BSP_Init This function is called by application code to initialize the BSP functionality BSP_Init could initialize I O ports setup timers serial ports SPI ports and so on cpu_bsp c and cpu_bsp h These files normally contain functions and their definitions to initialize the time stamping feature needed by uC CPU CPU_TS_Tmrlnit CPU_TS_TmrInit is a function that uC CPU expects to have in order to initialize the timer that will be used for timestamps Note that a skeleton of CPU_TS_TmrInit is can be found in the template file Micrium Software uC CPU BSP Template cpu_bsp c CPU_TS TmrRd CPU_TS_TmrRd is responsible for reading the value of a 16 32 or 64 bit free running timer CPU_TS_TmrRd return
381. utual exclusion semaphores ISRs are not allowed uC OS III enables the user to nest ownership of mutexes If a task owns a mutex it can own the same mutex up to 250 times The owner must release the mutex an equivalent number of times In several cases an application may not be immediately aware that it called OSMutexPend multiple times especially if the mutex is acquired again by calling a function as shown in Listing 13 12 OS_MUTEX MyMutex SOME_STRUCT MySharedResource void MyTask void p_arg OS_ERR err CPU_TS ts while DEF_ON OSMutexPend OS_MUTEX amp MyMutex 1 OS TICK OS_OPT OS_OPT_PEND_BLOCKING CPULTS amp ts OS_ERR amp err Check err ff 2 Acquire shared resource if no error aff MyLibFunction 3 OSMutexPost OS_MUTEX amp MyMutex 7 OS_OPT OS_OPT_POST_NONE OS_ERR amp err Check err if void MyLibFunction void OS_ERR err CPU TS TS OSMutexPend OS_MUTEX amp MyMutex 4 OS TICK OS_OPT OS_OPT_PEND_BLOCKING CPULTS amp ts OS_ERR amp err Check err isi Access shared resource if no error 5 OSMutexPost OS_MUTEX amp MyMutex 6 OS_OPT OS_OPT_POST_NONE OS_ERR amp err Check err wy Listing Nesting calls to OSMutexPend 1 A task starts by pending on a mutex to access shared resources OSMutexPend sets a Copyright 2015 Micrium Inc 234 uC OS III User s Manua
382. variable indicates that wC OS III s service to pend on multiple objects semaphores or message queues is available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_ PendDataSize CPU_INT16U sizeof OS_PEND_DATA This variable indicates the RAM footprint in bytes of an OS_PEND_DATA data type ROM Variable Data Type Value OSDbg_PendListSize CPU_INT16U sizeof 0S_PEND_LIST Copyright 2015 Micrium Inc 403 uC OS III User s Manual This variable indicates the RAM footprint in bytes of an OS_PEND_LIST data type ROM Variable Data Type Value OSDbg_PendObjSize CPU_INT16U sizeof 0S_PEND_OBJ This variable indicates the RAM footprint in bytes of an OS_PEND_0BJ data type ROM Variable Data Type Value OSDbg_PrioMax CPU_INT16U OS_CFG_PRIO_MAX This variable indicates the maximum number of priorities that the application will support ROM Variable Data Type Value OSDbg PtrSize CPU_INT16U sizeof void This variable indicates the size in bytes of a pointer ROM Variable Data Type Value OSDbg_QEn CPU_INT 8U OS_CFG_Q_EN When 1 this variable indicates that wC OS III s message queue services are available to the application This value is set in os_cfg h ROM Variable Data Type Value OSDbg_QDelEn CPU_INT 8U OS_CFG_Q DEL_EN When 1 this variable indicates that the function 0SQDe1 is available to the application This value is set in os_cfg h ROM Variable Data Type V
383. wait forever for the mutex to be released by its current owner The forever wait is specified by passing 0 as the second argument of the call 4 When OSMutexPend returns the task owns the resource and can therefore access the Copyright 2015 Micrium Inc shared resource The shared resource may be a variable an array a data structure an I O 62 uC OS III User s Manual 5 device etc You should note that we didn t actually show the access to the shared resource This is not relevant at this point When the task is done with the shared resource it must call OSMutexPost to release the mutex static void AppTask2 void p_arg 1 Copyright 2015 Micrium Inc OS_ERR err void p_msg OS_MSG_SIZE msg_size CPU_TS ts CPU_TS ts_delta p_arg p_arg while 1 p_msg OSQPend OS_Q amp AppQ 1 OS_MSG_SIZE amp msg size OS_TICK eo OS_OPT OS_OPT_PEND_BLOCKING CPU_TS amp ats OS_ERR amp err ts_delta OS_TS_GET ts 2 Process message received 3 Listing app c 5th Part Task 2 starts by waiting for messages to be sent through the message queue AppQ The task waits forever for a message to be received because the third argument specifies an infinite timeout When the message is received p_msg will contain the message i e a pointer to something In our case AppTask2 will always receive a message value of 1 Both the sender and receiver m
384. was sent 6 When the task is finished processing the packet the buffer is returned to the memory partition it came from by calling oSMemPut void UART_ISR void OS ERR err RxData Read byte from UART if RxData Start of Packet ie RxDataPtr RxDataPtr RxDataCtr if RxData RxDataPtr RxDataCtr OSMemGet amp UART_MemPool if amp err End of Packet byte iF RxData OSQPost OS_Q amp UART_Q void RxDataPtr OS_MSG_SIZE RxDataCctr OS_OPT OS_OPT_POST_FIFO OS_ERR amp err NULL Don t point to sent buffer sy RxDataPtr RxDataCtr else RxDataPtr RxDataCtr Copyright 2015 Micrium Inc RxData z See if we need a new buffer Yes yf See if we got a full packet Yes post to task for processing Save the byte received ah Listing UART ISR Pseudo code 293 uC OS III User s Manual Using Message Queues The table below shows a summary of message queue services available from uC OS IIL Refer to pC OS III API Reference for a full description on their use Function Name Operation oOSQCreate Create a message queue OSQDel1 Delete a message queue OSQFlush Empty the message queue OSQPend Wait for a message OSQPendAbort Abort waiting for a message OSQPost Send a message through a message queue Table Message queue API summary The table below is a summary of task message queue services
385. wn in Figure 9 1 note that the CPU Interrupt Enable Disable is typically part of the CPU but is shown here separately for sake of the illustration Interrupting devices signal the interrupt controller which then prioritizes the interrupts and presents the highest priority interrupt to the CPU Device nterrupt Device nterrupt Disable Interrupt rectus Controller O Enable Device nterrupt Device nterrupt CPU Interrupt Enable Disable Figure Interrupt controllers Modern interrupt controllers have built in intelligence that enable the user to prioritize interrupts remember which interrupts are still pending and in many cases have the interrupt controller provide the address of the ISR also called the vector address directly to the CPU If global interrupts i e the switch in Figure 9 1 are disabled the CPU will ignore requests from the interrupt controller but they will be held pending by the interrupt controller until the CPU re enables interrupts CPUs deal with interrupts using one of two models e All interrupts vector to a single interrupt handler Each interrupt vectors directly to an interrupt handler Copyright 2015 Micrium Inc 156 uC OS III User s Manual Before discussing these two methods it is important to understand how uC OS II handles CPU interrupts Copyright 2015 Micrium Inc 157 uC OS III User s Manual Typical uC OS IIl Interrupt Service Routine uC OS III req
386. wo times is stored in this variable This field can be displayed by a debugger or uC Probe to indicate how much time it took for the task to be signaled This field is only available when setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h SemPendTimeMax This field contains the maximum amount of time it took for the task to be signaled It is a peak detector of the value of SemPendTime The peak can be reset by calling OSStatReset Copyright 2015 Micrium Inc 106 uC OS III User s Manual This field is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg h StkUsed and StkFree uC OS III is able to compute at run time the amount of stack space a task actually uses and how much stack space remains This is accomplished by a function called OSTaskStkChk Stack usage computation assumes that the task s stack is cleared when the task is created In other words when calling OSTaskCreate it is expected that the following options be specified OS_TASK_OPT_STK_CLR and OS_TASK_OPT_STK_CHK OSTaskCreate will then clear all the RAM used for the task s stack uC OS III provides an internal task called 0S_statTask that checks the stack of each of the tasks at run time 0S_StatTask typically runs at a low priority so that it does not interfere with the application code 0S_StatTask saves the value computed for each task in the TCB of each task in these fields which represents the maximum numbe
387. words if the CPU or MCU has a dedicated timer that can be assigned for the tick ISR so that it s the same irrespective of the target application then BSP_OS_TickInit can be placed in os_cpu_c c The pseudo code for this function is shown in the listing below void BSP_OS TickInit CPU_INT32U freq 1 Install the interrupt vector for the timer used to generate tick interrupts 2 Configure the timer to generate interrupts at freq Hz 3 Enable timer interrupts 4 Listing BSP_OS_TickInit Pseudo Code BSP_OS TickISR If ISRs are implemented in assembly language this function could be placed in a file called bsp_os_a asm or other filename extension as needed by your assembler Alternatively you can place BSP_OS_TickISR in os_cpu_a asm depending on whether or not the tick ISR is generic for the CPU and whether it needs to be implemented in assembly language In other words if the CPU or MCU has a dedicated timer that can be assigned for the tick ISR so that it s the same irrespective of the target application then BSP_OS_TickISR can be placed in os_cpu_a asm The pseudo code for this function is shown below the C like code needs to be implemented in assembly language You should note that all ISRs should be modeled after BSP_OS_TickISR Copyright 2015 Micrium Inc 343 uC OS III User s Manual BSP_OS_TickISR 1 OS_CTX_SAVE 2 Disable Interrupts 3 OSIntNestingCtr 4 if OSIntNestingCtr 1
388. xCur This variable indicates the maximum amount of time the scheduler was locked This value is expressed in CPU_TS units and is reset by the context switch code so that it can track the scheduler lock time on a per task basis This variable is declared only if OS_CFG_SCHED_LOCK_TIME_MEAS_EN is set to DEF_ENABLED in os _cfg h Copyright 2015 Micrium Inc 386 uC OS III User s Manual OSSchedLockNestingCtr This variable keeps track of the nesting level of the scheduler lock OSSchedRoundRobinEn When set to 1 this variable indicates that round robin scheduling is enabled Statistics Task OSStatTaskCPUUsage This variable indicates the CPU usage of the application expressed as a percentage multiplied by 100 A value of 1000 indicates that 10 00 of the CPU is used while 90 00 of the time the CPU is idling This variable is declared only if OS_CFG_STAT_TASK_EN is Set to DEF_ENABLED in os _cfg h oSStatTaskCPUUsageMax This variable indicates the maximum CPU usage of the application expressed as a percentage multiplied by 100 A value of 1000 indicates that 10 00 of the CPU is used while 90 00 of the time the CPU is idling This variable is declared only if OS_CFG_STAT_TASK_EN is set to DEF_ENABLED in os_cfg h and can be reset by calling oSStatReset oSStatTaskCtr This variable contains a counter that is incremented every time the idle task infinite loop runs This variable is declared only if 0S_CFG_STAT_TASK_EN is set to DEF_EN
389. xample because we are dealing with an ISR The RPM task starts by waiting for a message from the RPM ISR by pending on the message queue The third argument specifies the timeout In this case ten seconds worth of timeout is specified However the value chosen depends on the requirements of an application Also notice that the ts variable contains the timestamp of when the post was completed You can determine the time it took for the task to respond to the message received by calling 0S_TS_GET and subtract the value of ts response_time OS_TS GET ts If a timeout occurs you can assume the wheel is no longer spinning 298 Copyright 2015 Micrium Inc uC OS III User s Manual 7 The RPM is computed from the delta counts received and from the reference frequency of the free running counter 8 Additional computations are performed as needed In fact messages can be sent to different tasks in case error conditions are detected The messages would be processed by the other tasks For example if the wheel spins too fast another task can initiate a shutdown on the device that is controlling the wheel speed In the lising below OSQPost and OSQPend are replaced with OSTaskQPost and OSTaskQPend for the RPM measurement example Notice that the code is slightly simpler to use and does not require creating a separate message queue object However when creating the RPM task it is important to specify the size of the m
390. y debuggers or uC Probe to easily identify this event flag group wC OS III stores a pointer to the name so there is no practical limit to its size except that the ASCII string needs to be NUL terminated You initialize the flags inside the event flag group to zero 0 unless the task and ISRs signal events with bits cleared instead of bits set If using cleared bits you should initialize all the bits to ones 1 OSFlagCreate returns an error code based on the outcome of the call If all the arguments are valid err will contain 0S_ERR_NONE A task waits for one or more event flag bits either from an ISR or another task by calling OSFlagPend as shown in the listing below Copyright 2015 Micrium Inc 272 uC OS III User s Manual OS_FLAG_GRP MyEventFlagGrp void MyTask void p_arg 1 Copyright 2015 Micrium Inc OS_ERR err CPU_TS ts OS_FLAGS which_flags while DEF_ON which_flags OSFlagPend amp MyEventFlagGrp 1 Pointer to event flag group oi OS_FLAGS x F ie Which bits to wait on Of 10 JF Maximum time to wait i OS_OPT_PEND_BLOCKING OS_OPT_PEND_FLAG_SET_ANY Option s amp ts if Timestamp of when posted to amp err JF Pointer to Error returned sal Check err 2 7 Listing Pending or waiting on an Event Flag Group When called OSFlagPend starts by checking the arguments passed to this function to ensure they have valid values assuming 0S_CFG_ARG
391. y length as long as it is NUL terminated PendList NbrEntries Each event flag group contains a wait list of tasks waiting for event flags to be set or cleared This variable represents the number of entries in the wait list Copyright 2015 Micrium Inc 397 uC OS III User s Manual Flags This variable contains the current value of the event flags in an event flag group TS This variable contains the timestamp of when the event flag group was last posted Copyright 2015 Micrium Inc 398 uC OS III User s Manual os_dbg c Static os_dbg c is provided in wC OS III as some debuggers are not able to read the values of define constants Specifically os_dbg c contains ROM variables initialized to define constants so that users can read them with any debugger Below is a list of ROM variables provided in os_dbg c along with their descriptions These variables use approximately 100 bytes of code space The application code can examine these variables and you do not need to access them in a critical region as they reside in code space and are therefore not changeable ROM Variable Data Type Value OSDbg_DbgEn CPU_INT 8U OS_CFG_DBG_EN When 1 this variable indicates that ROM variables in os_dbg c will be compiled This value is set in os_cfg h ROM Variable Data Type Value OSDbg_ArgChkEn CPU_INT 8U OS_CFG_ARG_CHK_EN When 1 this variable indicates that run time argument checking is enabled This means that wC O
392. y time a task pends on a kernel object with a timeout and every time the Tick task is run This Tick Step is applied to the Dynamic tick timer by calling the BSP_OS_TickNextSet function This guarantees that the Tick ISR will be called when at least Tick Step ticks have elapsed The Tick ISR will then notify the Tick task using OSTimeDynTick that Tick Step ticks have indeed elapsed Now instead of increment OSTickCtr by one and updating the tick lists the Tick task will add the Tick Step to osTickctr and update the tick lists accordingly After updating these lists the Tick task will determine the new Tick Step based on the updated tick lists and apply this step to the Dynamic tick timer This ensures that by setting a variable delay in the Dynamic tick timer the Tick task will be awakened by the Tick ISR only when necessary Note that to use the Dynamic Tick feature the wC OS III port developer has Copyright 2015 Micrium Inc 117 uC OS III User s Manual to implement the Dynamic Tick API described in uC OS III Port and 0S_CFG_DYN_TICK_EN needs to be set to DEF_ENABLED in os_cfg h You should note that there are practical limitations in using the Dynamic Tick mode For one thing if you use a 16 bit timer that increments at a rate of 1 MHz then the maximum reload time for the timer would be 65 535 milliseconds and thus you could not rely on such a timer to provide a 1 second delay In this case you probably would want the maximum Tick S

Download Pdf Manuals

image

Related Search

Related Contents

DeLOCK 88428 network antenna    Manual del propietario Tomas de fuerza  浴 ー施工が完了しましたら、 以下の方奪去で試運転を行って    ASUS (TF300T) User's Manual  Hiver 2013 - Université d`Ottawa  

Copyright © All rights reserved.
Failed to retrieve file