Upload
vudan
View
239
Download
3
Embed Size (px)
Citation preview
McMaster University
Embedded Systems
Computer Engineering 4DS4
Lecture 8 – Real Time OS
Amin Vali – Feb. 2016
Characteristics of an Embedded Systems
• Inherently Parallel
• Difficult to implement as a single
sequential program
• How to implement parallelism ?
• Hardware: HDLs
• Software: Operating Systems
Solution for Small Systems
• BG/FG
• Super-loops
• ISR:
• Asynchronous
Multiple Processes
• Functionality is divided to many processes
• Each process may have its own rate
• Asynchronous inputs
• Different activities
• Processes communicate
• Share CPU: Cooperate
Process
• Is a program in execution
• Has its own address space
Thread
• Thread
• A process may have multiple threads of
control, sharing the same address space
• Many embedded operating systems
only support threads:
• Low overhead
• Low hardware requirements
Multi-tasking : An overview
Multi-tasking : An overview
• Shared CPU
• Scheduling
• Priority
• Shared Resources
• Exclusive access to a resource
• Critical section
• Context Switch
Cooperative Technique
Preemptive Technique
What is an operating system (OS)?
• A computer program that runs from
power-up
• Manages access to resources, e.g.,
inputs/outputs (I/Os) memory,
applications,
• Interacts with users (through user-
interfaces or OS services)
• Recovers from failures
What is an operating system (OS)?
• For a multi-tasking OS, the key
responsibility is to schedule the many
applications (tasks) that can run
independent of each other;
• To manage arbitration to resources,
decide when to release resources
• For multi-processor OS, the added
responsibility is to decide on which
processor to schedule each task
Real-Time Operating Systems
• An OS which guarantees that tasks
which are scheduled will be performed
within the required time
• Hard RT-OS, the task must complete
within the pre-defined constraint
(otherwise the RT-OS terminates with a
failure) – the real-time constraints are hard
Real-Time Operating Systems
• Soft RT-OS, if the task does not complete
within the pre-defined constraint, the
system operation will continue at degraded
performance – the real-time constraints
are soft
Real-Time Operating Systems
• Advantages
• Divide applications to multiple tasks
• Reduce the complexity of both system design and application development
• Easy to expand, understand and maintain
• Timing can be guaranteed (if the run completes without system failures)
• Disadvantages
• Extra memory usage
• Processor overhead (2-5%)
• Extra cost for commercial RT-OS
µC/OS-II
• Micro-Controller OS, Version 2
• A small and compact real-time kernel
• Memory ~ 20KB for a working kernel
• Source code ~ 5,500 lines (ANSI C)
• Open source; not free for commercial use
• Preemptive and priority-driven
• Tasks of higher priority (when ready to execute) will preempt the tasks of lower priority (force the “involuntary” release of the processor)
µC/OS-II
• Each task is an infinite loop
• It must suspend by waiting for an event to occur (the event can happen either in interrupts or another tasks)
• Or it must “voluntarily” release the processor time to permit tasks of lower priority to use the processor
• Deterministic execution times for most uC/OS-II functions and services
• OS services are given to disable interrupts in the critical code sections
µC/OS-II
• Tasks must suspend or delay
Preemptive
priority-driven
real-time
task scheduler
Task A { Task Z {
Initialize A; Initialize M;
While (1) While (1)
{ {
Function A1; Function Z1;
Function Ak; Function Zn;
Suspend or Delay; Suspend or Delay;
} }
} }
Timer
External interrups
Internal exceptions
Task Task
Period between two consecutive arrivals of the task
Execution time
Time when the processor is
assigned to other tasks
µC/OS-II
Task States
RUNNINGREADY
OSTaskCreate()OSTaskCreateExt()
Task is Preempted
OSMBoxPend()OSQPend()
OSSemPend()OSTaskSuspend()OSTimeDly()OSTimeDlyHMSM()
OSMBoxPost()OSQPost()OSQPostFront()OSSemPost()OSTaskResume()OSTimeDlyResume()OSTimeTick()
OSTaskDel()
DORMANT
WAITING
OSStart()OSIntExit()
OS_TASK_SW()
OSTaskDel()
OSTaskDel()
Interrupt
OSIntExit()
ISR
µC/OS-II
• Dormant – residing in memory - becomes a task when you call OSTaskCreate()
• Ready – neither delayed nor waiting for any event to occur (task is ready when created)
• Running – task scheduled to run on the CPU
• One running task per CPU
• Might be preempted and become ready
• Waiting – wait for certain events to occur
• Timer expiration, signaling of semaphores, messages in mailboxes, …
• ISR – a task is preempted by an interrupt
Preemptive vs. Non-preemptive
Task A (priority low)
Task B (priority high)
Arrival time of Task A
Arrival time of Task B
Task A Task B
Preemptive schedule
Task A (continued)
Context switching
Task A Task B
Non-preemptive schedule
Task Management
• Can be created either prior to the start of multitasking or by a running task
• void (*task)() – function pointer
• void *pdata – pointer to context
• OS_STK *ptos – top of stack
• INT8U prio – priority level
• A task cannot be created by an ISR
• Must be written with initialization code and an infinite loop (and it must not return)
• Must call one of the “release” services:
• OSMboxPend(), OSFlagPend(), OSMutexPend(), OSQPend(), OSSemPend()
• OSTimeDly(), OSTimeDlyHMSM()
• OSTaskSuspend(), OSTaskDel()
INT8U OSTaskCreate(void (*task)(void *pd), void *pdata,
OS_STK *ptos, INT8U prio);
Task Management
OS_STK custom_task_stk[NUM_TASK][TASK_STACKSIZE];
OS_TCB custom_task_tcb[NUM_TASK];
INT8U return_code = OS_NO_ERR;
return_code = OSTaskCreateExt(custom_task_0,
NULL,
(void *)&custom_task_stk[0][TASK_STACKSIZE-1],
CUSTOM_TASK_0_PRIORITY,
CUSTOM_TASK_0_PRIORITY,
&custom_task_stk[0][0],
TASK_STACKSIZE,
&custom_task_tcb[0],
0);
INT8U OSTaskCreateExt(void (*task)(void *pd),
void *pdata, OS_STK *ptos,
INT8U prio, INT16U id,
OS_STK *pbos, INT32U stk_size,
void *pext, INT16U opt);
Task Control Block (TCB)
• A task control block (TCB) is a data structure used to keep the state of a task while it is preempted or suspended
• Each task has a TCB
• TCB is created when the task is created
• TCBs for all the tasks are stored into a linked-list-type data structure that is managed by the OS kernel
• TCB for a task can be read by the user
• The contents of a TCB is saved/restored when a context-switch occurs
• Task priority, delay counter, event to wait, the location of the stack
• CPU registers are stored in the stack rather than in the TCB – the TCB saves only the stack pointer
Context Switching
OSTCBCur
OS_TCB
Low priority task
OSTCBHighRdy
OS_TCB
High priority task
Low memory
High memory
Stack growth
Low memory
R4
R3
R2
R1
PC
PSW
High memory
SP
CPU
R4
R3
R2
R1
PC
PSW
OSTCBCur
OS_TCB
Low priority task
OSTCBHighRdy
OS_TCB
High priority task
Low memory
R4
R3
R2
R1
PC
PSW
High memory
Stack growth
Low memory
R4
R3
R2
R1
PC
PSW
High memory
SP
CPU
R4
R3
R2
R1
PC
PSW
Context Switching
OSTCBCur
OS_TCB
Low priority task
OSTCBHighRdy
OS_TCB
High priority task
Low memory
R4
R3
R2
R1
PC
PSW
High memory
Stack growth
Low memory
R4
R3
R2
R1
PC
PSW
High memory
SP
CPU
R4
R3
R2
R1
PC
PSW
Context Switching
Shared Resources
• How to control a shared resource ?
• Disable Interrupts
• Test and Set
• Disable Scheduler
• Semaphores (and Mutex)
Mutual Exclusion
• How to control a shared resource ?
• Disable Interrupts
• Test and Set
• Disable Scheduler
• Semaphores (and Mutex)
Mutual Exclusion
• Disable Interrupts
Disable interrupts;
Access the resource (read/write from/to variables);
Reenable interrupts;
void Function (void)
{
OS_ENTER_CRITICAL();
.
. /* You can access shared data in here */
.
OS_EXIT_CRITICAL();
}
Mutual Exclusion
• Test and Set (without a kernel)
Disable interrupts;
if (‘Access Variable’ is 0) {
Set variable to 1;
Reenable interrupts;
Access the resource;
Disable interrupts;
Set the ‘Access Variable’ back to 0;
Reenable interrupts;
} else {
Reenable interrupts;
/* You don’t have access to the resource, try back later; */
}
Mutual Exclusion
• Disable Scheduler
void Function (void)
{
OSSchedLock();
.
. /* You can access shared data in here (interrupts are recognized) */
.
OSSchedUnlock();
}
Mutual Exclusion
• Semaphores (and Mutex)
• control access to a shared resource
(mutual exclusion)
• signal the occurrence of an event
• allow two tasks to synchronize their
activities.
Semaphores
• Operations:
• Initialize / Create
• Signal / Post
• Wait / Pend
• Accept
• Receiving task:
• the highest priority task waiting for the semaphore (uC/OS-II)
• the first task that requested the semaphore (First In First Out, or FIFO).
Semaphores
OS_EVENT *SharedDataSem;
void Function (void)
{
INT8U err;
OSSemPend(SharedDataSem, 0, &err);
.
. /* Access shared data in here (interrupts recognized) */
.
OSSemPost(SharedDataSem);
}
Mutex is a binary
semaphore
Synchronization
ISRs
// Semaphore from uCOSextern OS_EVENT *PBSemaphore[];
// Function for post semaphore when PB0 is pressedvoid KEY0_Pressed() {
INT8U return_code = OS_NO_ERR;
return_code = OSSemPost(PBSemaphore[0]);alt_ucosii_check_return_code(return_code);
}//…// ISR when any PB is pressedvoid handle_button_interrupts(){
OSIntEnter();switch(get_pio_edge_cap(PB_BUTTON_I_BASE)) {case 1: KEY0_Pressed(); break;case 2: KEY1_Pressed(); break;case 4: KEY2_Pressed(); break;case 8: KEY3_Pressed(); break;}set_pio_edge_cap(PB_BUTTON_I_BASE,0x0);OSIntExit();
}
ISRs
• Semaphores synchronize ISRs and tasks
• The ISR posts a value in the semaphore
• The tasks will wait for the event using:
• INT16U OSSemAccept(OS_EVENT *pevent);
• does not suspend the task (returns 0 if no event)
• void OSSemPend(OS_EVENT *pevent, INT16U
timeout, INT8U *err);
• suspends the task
Priority Inversion
Mutex
Binary Semaphore With Priority
Mutual exclusion semaphore (Mutex)
• A mutex is a special binary semaphore
that supports ownership
• Only the task that has locked a mutex
can release it
• Mutex is created in unlocked state
Code Development
int init_OS_data_structs(void) {int i;INT8U return_code = OS_NO_ERR;
printf("Init data structs...\n");
for (i = 0; i < NUM_PB_BUTTON; i++)PBSemaphore[i] = OSSemCreate(0);
LCDMutex = OSMutexCreate(LCD_MUTEX_PRIORITY,&return_code);
alt_ucosii_check_return_code(return_code);
return 0;}
µC/OS-II
void main(void)
{
/* Private initializations */
OSInit();
/* Create Startup task */
OSStart();
}
µC/OS-II
OSInit ()
• Initializes all MicroC/OS-II variables and data structures
• OSInit() creates the idle task, which is always ready to run and executes on priority OS_LOWEST_PRIO
• OSInit() also creates the statistic task OS_Task_Stat() and makes it ready to run, if OS_TASK_STAT_EN and OS_TASK_CREATE_EXT_EN are set to 1 in OS_CFG.H
µC/OS-II
OSStart()
• OSStart() starts multitasking
• Before you execute OSStart() at least
one task shall be created
Statistics in µC/OS-II
• In order to get statistics about CPU Utilization, the statistics task must be initialized
void TaskStart (void *pdata)
{
/* Install and initialize ucosII ticker */
OSStatInit(); /* Initialize statistics task */
/* Create your application task(s) */
while (1) {
/* Code for TaskStart()*/
}
}
µC/OS-II : Idle task
void OS_TaskIdle (void *pdata)
{
for (;;) {
OS_ENTER_CRITICAL();
OSIdleCtr++;
OS_EXIT_CRITICAL();
OSTaskIdleHook();
}
}
Statistics in µC/OS-II
.
void OSStatInit (void)
{
OSTimeDly(2);
OS_ENTER_CRITICAL();
OSIdleCtr = 0L;
OS_EXIT_CRITICAL();
OSTimeDly(OS_TICKS_PER_SEC);
OS_ENTER_CRITICAL();
OSIdleCtrMax = OSIdleCtr;
OSStatRdy = OS_TRUE;
OS_EXIT_CRITICAL();
}
Statistics in µC/OS-II
• OSStatInit() determines how high the idle counter (OSIdleCtr) can count, if no other task in the application is executing
• OSStatInit() delays itself (TaskStart()) for one full second
• During that time OSIdleCtr is continuously incremented
• After one second TaskStart() (still in OSStatInit() is resumed) and the value that OSIdleCtr has reached is stored in OSIdleCtrMax
Statistics in µC/OS-II
• Further on, every second, the new value of the
idle counter is copied into the global variable
OSIdleCtrMax
Reentrancy
• What if two tasks call a single function ?
int triple(int x)
{
return 3 * x;
}
int Temp; // Global
void swap(int *x, int *y)
{
Temp = *x;
*x = *y;
*y = Temp;
}
Reentrancy
• A reentrant function can be used by more
than one task without fear of data
corruption
• can be interrupted at any time and resumed
at a later time without loss of data
• use local variables
• protect data when global variables are used
Reentrancy
Reentrancy
• Difficult to catch and debug
• Do not use non-reentrant functions
• Declare Temp local to swap()
• Disable interrupts before the operation and
enable them afterwards.
• Use a semaphore
Periodic, Aperiodic and Sporadic Tasks
• A periodic task executes periodically
• Usually a hard deadline is assumed
• An aperiodic task executes on demand,
but has a soft deadline
• A sporadic task executes on demand,
but has a hard deadline
Periodic, Aperiodic and Sporadic Tasks
• Tasks are periodic and are characterized by P(c,p,d) where
• c = compute time
• p = period
• d = deadline
• We assume that period and deadline are equal (p = d)!
• Tasks may be preempted
• No dependency between tasks
• Scheduler can run at any time instance
• Context-switch time is zero
• Tasks are scheduled on a uniprocessor
Example
• T1 = (1,2,2); T2 = (2,5,5)
• Policy: T1 has higher priority than T2
Deadlines are met
Example
• T1 = (1,2,2); T2 = (2,5,5)
• Policy: T2 has higher priority than T1
P1 cannot meet its first deadline
Rate Monotonic Scheduling
• RMS assigns fixed priorities in reverse-
order of period length
• The shorter the period, the higher the
priority
• Intuition: Processes that require frequent
action should receive higher priority
• RMS uses preemption
• RMS uses static priorities
Rate Monotonic Analysis (RMA)
model
• Assumptions
• All process run on single CPU
• Zero context switch time
• No data dependencies between processes
• Process execution time is constant
• Deadline is at end of period
• Highest-priority ready process runs
Example
• T1 = (3,4,4); T2 = (2,8,8)
• T1 has shorter period and is thus assigned
higher priority!
Example
• T1 = (3,9,9); T2 = (5,18,18); T3 = (4,12,12)
• Priority : T1 > T3 > T2
µC/OS-II
Rerefences
• MicroC/OS II User’s Manual
• Micrium.com
• Embedded Systems Course
• Dr. Ingo Sanders, with permission