Micro-Controller Operating Systems
Micro C/OS-II The Real Time Kernel
Agenda
Task Control Blocks Ready Lists Task Scheduling An Example - CPU Usage
Critical Sections
Disables the interrupts to access critical sections of code and reenables interrupts when finished with
Interrupt disable time depends on the processor architecture and the quality of the code generated by the compiler
MicroC/OS-II provides two macros: OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL()
Tasks
Typically an infinite loop
void YourTask (void *pdata) { for (;;) { /*USER CODE*/ Call one of mC/OS-II’s services:
OSMboxPend(); OSQPend();
OSSemPend(); OSTaskDel(OS_PRIO_SELF); OSTaskSuspend (OS_PRIO_SELF); OSTimeDlyHMSM(); /*USER CODE*/ } }
Void YourTask (void *pdata) { /*USER CODE*/ OSTaskDel (OS_PRIO_SELF); } Task States Task Control Blocks When a task is created, a Task Control Block, a data structure OS_TCB,is assigned All OS_TCBs reside in RAM OS_TCBs contain the information on the current top of the task bottom of the stack size of the stack in bytes an identifier for the task task priority state of the task
Task Control Blocks The max number of tasks that an application can have is in OS_CFG.H and it can be changed
All OS_TCBs are placed in OSTCBTbl[]
When OS is initialized,all OS_TCBs in the table are linked in a singly linked list of free OS_TCBs
The creation of a task assigns OS_TCB pointed to by OSTCBFreeList to itself and OSTCBFreeList now points to the next OS_TCB in the chain Ready List Each task is assigned a unique priority level between 0 and OS_LOWEST_PRIO which is assigned to an idle task
Each task that is ready to run is placed in a ready list consisting of two variables, OSRdyGrp and OSRdyTbl[]
The scheduler determines the lowest priority number that has its bit set in OSRdyTbl[] to run the next task
mC/OS-II Ready list Contents of OSMapTbl[] Making a task ready OSRdyGrp |= OSMaptbl [prio>>3]; OSRdyTbl [prio>>3] |= OSMapTbl [prio & 0x07]; e.g: Say priority of a task is 12 and the initial contents of OSRdyGrp is 01000010 and
OSRdyTbl [1] is = 10100000
Then, tbl OSMap [12>>3 =00000001]=00000010
OSRdyGrp = 01000010 OR 00000010 =01000010;
OSMapTbl [prio & 07=00000100]=00010000 OSRdyTbl [prio>>3=00000001]=10100000 OR 00010000 = 10110000 indicating that task priority 12 has been set to 1. More on ready list Removing a task from the ready list
if ((OSRdyTbl [prio>>3]&=~OSMaptbl [prio & 0x07]) ==0) OSRdyGrp &= ~OSMapTbl[prio>>3];
E.g: say initial conditions are OSRdyGrp =00000010
and OSRdyTbl[1] =00010000 and we want to remove the task whose priority is 12 from the ready list,then
~OSMapTbl [12 & 07 =04]=111011111 OSRdyTbl [12>>3=01] =00010000 & 11101111=00000000; Therefore, OSRdyGrp = 00000010 & 11111101 =00000000
More on ready list Finding the highest priority task ready to run
y =OSUnMaptbl [OSRdyGrp]; x =OSUnMapTbl [OSRdyTbl[y]]; prio = (y<<3) +x;
E.g: say initial conditions are OSRdyGrp =01101000
and OSRdyTbl[3] =11100100,then
y = returns the least significant bit that is set ;that is 3 x = OSunMapTbl [ 11100100]= returns the least significant bit that is set ;that is 2
prio = 00000110<<3 +x =00011000 + 00000010=00011010 =26;
OSUnMapTbl[] Task Scheduling OSSched() performs task level scheduling ISR level scheduling is handled by OSIntExit() OSSched() exits if called from an ISR or if scheduling has been disabled Or else, OSSched() determines the priority of the highest priority task that is ready to run If the highest priority task is not the current one,then context switch occurs
Locking the Scheduler The OSSchedLock and OSSchedUnlock functions are used to disable and reenable task scheduling void OSSchedLock (void) {
if (OSRunning ==TRUE ) { OS_ENTER_CRITICAL(); OSLockNesting++; OS_EXIT_CRITICAL(); } }
Idle Task
OSTaskIdle() increments a 32 bit counter called OSIdleCtr to determine the percent CPU time actually being consumed by the application software Statistics Task
Called the OSTaskStat() provides run time statistics - executes every second and computes the percent CPU usage
It is created when the configuration constant OS_TASK_STAT_EN in OS_CFG.H is set to 1 If the application is to use the statistic task, then OSStatInit() should be called from the first task created in the application during initialization
Statistics Task Void main (void) {
OSInit();
/*install uc/OS-II’s context switch vector ,create your startup task,say TaskStart*/
OSStart();
}
void TaskStart (void *pdata) { /* install and initialze uCOS-II ‘s ticker*/
OSStatInit();
/*create your application task(s)*/
for (;;) {
/* Code for TaskStart() goes here*/
}
}
Statistic Task Initialization