|
|
Microc/os-iiMicro C/OS-II is a pre-emptive real time kernel. Agenda Introduction- uC/OS II Tasks Kernel Reentrant Functions Scheduler mC/OS-II High performance Deterministic Robust and reliable ROMable Scalable Portable to different processors Royalty free Low cost mC/OS-II Preemptive real time kernel Can manage up to 64 tasks application can have up to 56 tasks other tasks are reserved each task has a unique priority round robin scheduling is not supported Each task requires its own stack can have different stack sizes mC/OS-II System services mail boxes queues semaphores fixed size memory partitions timer functions Interrupts can be nested up to 255 levels deep Where is it Used ? Used in applications such as cameras medical instruments engine controls on board computers satellites network adapters highway telephone call boxes ATM machines industrial robots Terminology A critical section/critical region of code - to be treated indivisibly A task/thread - a small program that thinks it has the CPU all to itself A resource - an entity used by a task A shared resource - a resource used by more than one task Multitasking - process of scheduling and switching the CPU between several tasks Possible states of Tasks Each task is an infinite loop and can be in any one of the following 5 states Dormant Ready Running Waiting ISR Possible states of Tasks Context Switch Task’s context is contents of CPU registers During switching the current task’s context is pushed to its stack area and the new task’s context is popped from its stack Also known as task switch Kernel Services of a real time kernel are context switching management of tasks communication between tasks semaphore management mailboxes queues time delays Kernel Pros simplifies the system design modularizes the design better use of the CPU Cons additional ROM for the code space additional RAM for kernel data Kernel will consume CPU’s time Non-Preemptive Kernel Preemptive Kernel The running task can be preempted if a higher priority task has been made ready Used when deterministic system response is important MicroC/OS-II is a preemptive kernel Preemptive Kernel Reentrant functions Can be entered at any time, preempted and resumed at a later time without loss of data Normally use local variables Global variables used will have the protection mechanism Non-reentrant function Low priority task while(1){ x=1; y=2; swap (&x,&y); { Temp=*x } . . . OSTimeDly(1); } High priority task while(1){ z=3; t=4; swap(&z,&t); { Temp= *z; } . . OSTimeDly(); . . } Another Example Non-reentrant function Int BufSize; char *pbuf; void ExtendBuffer(int NewSize) { if (NewSize <= BufSize) return; BufSize = NewSize; pBuf = realloc (pBuf,NewSize); return; } Scheduler MicroC/OS-II does not support round robin scheduling Each task has a unique priority Latest version supports priority inheritance Task priorities are assigned through a technique called Rate Monotonic Scheduling tasks with the highest rate of execution are given the highest priority Mutual Exclusion Can be achieved by disabling interrupts performing test and set operations disabling scheduling using semaphores Disabling Interrupts Steps Disable interrupts; Access the resource; reenable interrupts; MicroC/OS-II example void Function (void) { OS_ENTER_CRITICAL() . . /*access shared data*/ . OS_EXIT_CRITICAL() } Test and Set Disable interrupts; if (‘Access Variable’ is 0) { Set variable to 1; Enable interrupts; Access the resource; Disable interrupts; Set variable to 0; Enable interrupts; } else { Reenable interrupts; You don’t have access to resource*/ } Disabling the Scheduler Used when a task is not sharing variables or data structures with an ISR void Function (void) { OSSchedLock(); . . OSSchedUnlock(); } Using Semaphores Operations performed on a semaphore are INITIALIZE (also called CREATE) WAIT (also called PEND) SIGNAL (also called POST) Semaphore is said to be available when the value is greater than 0 Using Semaphore OS_EVENT *SharedDatasem; void Function (void) { INT8U err; OSSemPend(SharedDataSem,0,&err); . . OSSemPost(sharedDataSem); } Micro C/OS-II The Real Time Kernel Agenda Semaphores Message Queues Interrupts Clock Tick Real Time Characteristics Semaphore -printer example Hidden Semaphore Counting Semaphore Deadlock Among two tasks - each task waiting for resources held by the other task To avoid deadlock Task can proceed only after acquiring all resources Tasks to acquire resources in the same order & tasks to release the resources in the reverse order Synchronization Unilateral rendezvous A task initiates an I/O operation and waits for the semaphore More than one task waiting for an event to occur Bilateral rendezvous Two tasks can synchronize by using two semaphores Event flags Used when a task needs to synchronize with multiple events Message Mailboxes Mailbox Services Micro C/OS-II offer are create and initialize the mailbox deposit a message into a mailbox(POST) wait for a message to be deposited into the mailbox (PEND) get a message from a mailbox if one is present,but do not suspend the caller if the mailbox is empty (ACCEPT) Message Queues An array of mailboxes used to send one or more messages to a task Messages can be extracted in a FIFO or LIFO fashion Common message queue services are same as that of a mail box A task requesting a message from an empty queue is suspended and placed on the waiting list until the message is received Interrupts Hardware mechanism to inform the CPU that an asynchronous event has occurred The ISR processes the event and returns to the background in a foreground/ background system the interrupted task for a non preemptive kernel the highest priority task ready to run for a preemptive kernel Interrupt Latency Interrupt latency is the sum of the maximum amount of time interrupts are disabled and the time to start executing the first instruction in the ISR The longer the interrupts are disabled,the higher the interrupt latency Interrupt Nesting Interrupt Response Time between the reception of the interrupt and the start of the user code that handles the interrupt For a foreground background system and non preemptive kernel = interrupt latency + time to save the CPU’s context For a preemptive kernel = interrupt latency + the time to save the CPU’s context + execution time of the kernel ISR entry function Interrupt Recovery Time required for the processor to return to the interrupted code For a foreground/background system and non preemptive kernel = time to restore the CPU’s context + time to execute the return from interrupt instruction For a preemptive kernel = time to determine if a higher priority task is ready + time to restore the CPU’s context of the highest priority task + time to execute the return from interrupt instruction Interrupt Timings Interrupt Timings More on Interrupts YourISR: Save all CPU registers; Call OSIntEnter () or, increment OSIntNesting() directly; Execute user code to service ISR; Call OSIntExit(); Restore all CPU registers; Execute a return from interrupt instruction; Servicing an interrupt More on ISRs void OSIntEnter (void) { OS_ENTER_CRITICAL(); OSIntNesting++; OS_EXIT_CRITICAL(): } Tips on Interrupts ISRs are normally kept as small as possible Use NMI for low latency interrupt service NMI can be disabled through external circuitry NMI ISRs can be used to signal a task Clock Tick interrupt Occurs periodically, between 10 and 200ms - also called as System’s heartbeat Allows a kernel to delay tasks for an integer number of clock ticks provide timeouts when tasks are waiting for events to occur Non Deterministic Delay Possible solutions Increase the clock rate of processor Increase the time between clock tick interrupts Rearrange task priorities Avoid using floating point operations Use a compiler that performs better code optimization Write time critical code in assembly language Upgrade to a faster microprocessor Real Time Characteristics Worst case performance - Max. time between an event and an interrupt signal arriving at the processor Worst case interrupt latency - Max. time between the interrupt arrival and the start of the ISR Worst case response time for the software to respond. Real Time Characteristics Worst case execution time of each system call should be deterministic Worst case interrupt latency and context switch times should be guaranteed Data sheet provides the details of the minimum, average and maximum number of clock cycles for each system call Real Time Characteristics Interrupt - Response time of a real time project may vary from 1ms to 100ms Time required to perform a context switch is critical Real Time Characteristics 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 & 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 =00000001=00000010 OSRdyGrp = 01000010 OR 00000010 =01000010; OSMapTbl & 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 & 0x07) ==0) OSRdyGrp &= ~OSMapTblprio>>3; E.g: say initial conditions are OSRdyGrp =00000010 and OSRdyTbl1 =00010000 and we want to remove the task whose priority is 12 from the ready list,then ~OSMapTbl & 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 OSRdyTbl3 =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
|
 |