Title: ECE 695 Embedded Systems Winter 2006
1ECE 695 Embedded SystemsWinter 2006
2Review of Concepts
- Foreground/Background Approach
- Designed for periodic systems
- Manage hard deadlines
- Must be creative to handle events
- Real-Time OS
- Driven by events
- Must be creative to handle periodic processes and
hard deadlines
3Consider the Periodic Process
4Near-Periodic Tasking
- Use OSTimeDlyHMSM(h,m,s,ms) operating system call
from within each task. - Task runs forever
- Call time delay at completion of run.
5Example Schedule
- One Background Task and 11 Foreground Tasks
- Background task should complete once a minute
(can be segmented) - Foreground tasks are periodic with hard deadlines
- Tasks 2, 3, and 4 must run every 10 ms
- Tasks 5 and 6 must run every 25 ms
- Task 7 must run every 45 ms
- Tasks 8, 9, and 10 must run every 55 ms
- Tasks 11 and 12 must run every 75 ms
- Our foreground/background approach generates the
following schedule table
6Sample Schedule Table
7Implementing with RTOS
- Let Task 1 be the background
- Tasks 2 through 12 are then the foreground
- Can schedule foreground tasks to be periodic at
the exact required rate - In our example table, tasks 11 and 12 are
scheduled in the 40 ms group when they only need
to execute at 75 ms - Each task can be a separate file
8Example 1Main Routine
/
file uCEX1.c Author John G. Weber
Date 4/7/2003 This file provides a
periodic timing example for ECE 532 using uCOS-II
and Nios.
/ include "librtos32\includes.h" includ
e "uCEX1_Tasks.h" int main(void)
OSNiosInitContextSwitch(ND_OSCTXSW_ITNUMBER,
ND_OSTICKISR_ITNUMBER) OSInit()
OSTaskCreate(Task1, (void)0, Task1StkTASK_STACK
SIZE-1, 15) OSStart()
9Example 1--Tasks
file uCEX1_Tasks.c Author John G.
Weber Date 4/7/2003
/ include
"librtos32\includes.h" include
"uCEX1_Tasks.h" /
void Task1() Initializes the
timer, starts statistic task and creates other
tasks This Task prints message once a
minute
/ void Task1 (void pdata) INT32U cpt 0
OSNiosStartTicks((void)ND_TIMER)
/ starts the user timer /
OSStatInit()
/ OSCPUUsage of cpu usage / /
Creates other Tasks / OSTaskCreate(Task2,
(void)0, Task2StkTASK_STACKSIZE-1, 2)
OSTaskCreate(Task3, (void)0, Task3StkTASK_STAC
KSIZE-1, 3) OSTaskCreate(Task4, (void)0,
Task4StkTASK_STACKSIZE-1, 4) OSTaskCreate(Tas
k5, (void)0, Task5StkTASK_STACKSIZE-1,
5) OSTaskCreate(Task6, (void)0,
Task6StkTASK_STACKSIZE-1, 6) OSTaskCreate(Tas
k7, (void)0, Task7StkTASK_STACKSIZE-1,
7) OSTaskCreate(Task8, (void)0,
Task8StkTASK_STACKSIZE-1, 8) OSTaskCreate(Tas
k9, (void)0, Task9StkTASK_STACKSIZE-1,
9) OSTaskCreate(Task10, (void)0,
Task10StkTASK_STACKSIZE-1, 10) OSTaskCreate(T
ask11, (void)0, Task11StkTASK_STACKSIZE-1,
11) OSTaskCreate(Task12, (void)0,
Task12StkTASK_STACKSIZE-1, 12) while(1)
// This while loop
becomes the background task in our example
printf("TASK 1 cpt d\n", cpt)
OSTimeDlyHMSM(0,1,0,0) //
Waits 1 minute Alternatively could just free run
if Task 1 priority is //lower
than that of the other tasks
10Example 1 TasksTypical Task
- timer_milliseconds.s modified to use the user
timer - the call to nr_timer_milliseconds now references
the user timer and can be used to time the tasks
/
void Task2() This Task prints message every
seconds and never stops.
/ void Task2 (void pdata)
INT32U cpt 0 int last_time 0 int now
0 int delta 0 while(1)
last_time now cpt now
nr_timer_milliseconds() delta now -
last_time printf("TASK 2 cpt d and delta
time d\n", cpt,delta)
OSTimeDlyHMSM(0,0,0,10) //tell OS to schedule
again in 10 ms
11(No Transcript)
12(No Transcript)
13RTOS Events
- Can implement with Event Flags, Semaphores, or
Messages - Mechanized with OS calls
- Relieves user of writing code to support event
14Program Structure
15Using uCOS-II
- Periodic Tasking
- priority based to approximate hard deadlines
- Example 1
- Semaphore use
- Event management
- Task synchronization
- Example 2
16Example 2
- Extends Example 1 to allow events
- Three modifications to the code of example 1
- First semaphore must be created before it is
used - create in main program
- Second task 1 creates all other tasks and then
suspends waiting for the semaphore. - Third task 12 posts a semaphore every third
time it runs - Task 1 is the lowest priority task
- Other tasks are pseudo-periodic
17Example 2 --Main
/
file uCEX2.c Author John G. Weber
Date April 2003 This file provides a
semaphore example for ECE 532 using uCOS-II and
Nios.
/ include "librtos32\includes.h" include
"uCEX2_Tasks.h" INT16U SyncSem //declare the
semaphore int main(void)
OSNiosInitContextSwitch(ND_OSCTXSW_ITNUMBER,
ND_OSTICKISR_ITNUMBER) OSInit()
//create a task synchronization semaphore
SyncSem OSSemCreate(0)
OSTaskCreate(Task1, (void)0, Task1StkTASK_STACK
SIZE-1, 15) OSStart()
18Example 2 Tasks Task 1 While Loop
while(1) printf("TASK 1 cpt
d\n", cpt) //OSTimeDlyHMSM(0,1,0,0)
/ time delay
commented out / //Task 1 suspends and
waits for the SyncSem Semaphore to be set by task
12 OSSemPend(SyncSem,0,err)
19Example 2 Task12 Post the Semaphore
void Task12() This Task prints message every
10 seconds and never stops. Every third time
this task executes the semaphore is set to allow
task 1 to execute.
/ void Task12 (void pdata)
INT32U cpt 0 int last_time 0 int now
0 int delta 0 int icnt0 while(1)
last_time now cpt now
nr_timer_milliseconds() delta now -
last_time printf("TASK 12 cpt d and delta
time d\n", cpt,delta) if (icnt
3) OSSemPost(SyncSem) icnt
0 else icnt
OSTimeDlyHMSM(0,0,10,0)
20Inter-Task Communication with RTOS
- Easiest method is through shared data structures
- low latency
- higher risk
- When task is accessing shared data structure, it
must have exclusive access to avoid contention
and corruption - Exclusive Access obtained in several ways
- disable interrupts,
- disable scheduling
- semaphores
21Disabling Interrupts
- Fastest way to gain exclusive access to shared
resource - uC/OS-II uses this technique in the kernel for
access to internal variables and data structures - uC/OS-II provides two functions
- OS_ENTER_CRITICAL() //disables interrupts
- OS_EXIT_CRITICAL()//enables interrupts
- bracket access to shared data with these two
functions - Hazards
- dont disable interrupts for too long (affects
response time of system) - may need to do this to share data with an ISR
22Disabling and Enabling the Scheduler
- Allows two or more tasks to share data without
contention - Interrupts are enabled
- If Interrupt occurs while scheduler is disabled,
ISR is executed and control returns to the task
that was executing (looks like a non-preemptive
kernel) - uC/OS-II functions
- OSSchedLock() //disables the scheduler
- OSSchedUnlock() //enables the scheduler
- bracket shared data access with above functions
- Hazard
- works well but defeats the purpose of having the
scheduler and preemptive kernel
23Semaphores
- Invented the Edgser Dijkstra in the 1960s
- Use to
- control access to a shared resource (mutual
exclusion) - signal the occurrence of an event
- allow two tasks to synchronize their activities
- highest priority task waiting for semaphore gets
it
OSSemPost(SharedDataSem)
OSSemPend(SharedDataSem)
24Semaphores in uC/OS-II
- Two types
- binary
- counting (0 65,535)
- Creating a semaphore
- declare its name (global)
- OS_EVENT SampleSem
- create it prior to use (main or in task but not
inside loop) - SampleSem OSSemCreate(INT16U value)
- if a counting semaphore, init value to zero (it
will track the number of times it is called) - if value 1, binary semaphore
- Using a semaphore
- task that is waiting for signal calls
OSSemPend(OS_EVENT event, INT16U timeout, INT8U
err) - OSSemPend(SampleSem, 0, err)
- task that is sending the signal calls
OSSemPost(OS_EVENT event) - OSSemPost(SampleSem)
- Semaphores must be enabled before use
- In file OS_CFG.H set OS_SEM_EN to 1
25Accessing Peripherals with Semaphores
26Buffer Management Using Semaphores
- Counting Semaphore
- Use when resource can be used by more than one
task at same time - Example10 buffers
- Buffer manager satisfies first 10 buffer requests
directly - When all semaphores used, task requesting buffer
is suspended until semaphore available
27Deadlocks and Semaphores
- Situation where two tasks are waiting for
resource held by the other - E.g. Task 1 has exclusive use of resource R1 and
Task 2 has exclusive use of resource R2. - T1 requires exclusive use of R2 and T2 requires
exclusive use of R1 - Neither task can complete
- Avoid by
- Acquire all resources before beginning
- Acquire resources in same order
- Release resource in reverse order
- If kernel allows a timeout to be specified with
semaphore (uC/OS-II does), this allows deadlock
to be broken - Deadlocks generally occur in large, multi-tasking
systems
28Task Synchronization
29Synchronization
- Synchronize tasks with a semaphore
- Will work with ISR or another task
30Event Flags
- Used to synchronize task with multiple event
occurrence - Synchronize when any of the events have occurred
- disjunctive synchronization
- effectively the logical OR of event occurrence
31Event Flags (Cont)
- Synchronize when all of the events have occurred
- conjunctive synchronization
- effectively the logical AND of event occurrence
32Multiple Task Signaling
- Common events may signal multiple tasks
33Services
- OS_FLAG_EN must be set to 1 in OS_CFG.H
- Create a flag group before using it
- OSFlagCreate()
- OS_FLAG_GRP EngineStatusFlags
- OSFlagCreate(OS_FLAGS flags, INT8U err)
- flags contains the initial values to store in the
flag group - example
- OS_FLAG_GRP EngineStatus
- void main (void)
- INT8U err
- .
- .
- OS_INIT() //Initialize OS
- .
- . //create flag group containing engine status
- EngineStatusFlags OSFlagCreate(0x00,err)
- .
- .
- OSStart() //start multitasking
34Services (Cont)
- Set an Event Flag use OSFlagPost()
- OSFlagPost(pgrp, flags, opt, err)
- pgrp is a pointer to event flag group
- flags sets corresponding bit in the flag group
- opt determines whether set to one or zero
- OS_FLAG_SET or OS_FLAG_CLR
- err is pointer to error code
- OS_NO_ERR call successful
- OS_FLAG_INVALID_PGRP passed a null pointer
- OS_ERR_EVENT_TYPE not pointing to event flag
group - OS_FLAG_INVALID_OPT invalid option
- Example
- define ENGINE_OIL_PRESSURE_OK 0x01
- define ENGINE_OIL_TEMP_OK 0x02
- define ENGINE_START 0x04
- .
- .
- err OSFlagPost(EngineStatusFlags, EngineStart,
OS_FLAG_SET, err)
35Services (Cont)
- To wait for a condition, use OSFlagPend()
- OSFlagPend(pgrp, flags, wait_type, timeout,err)
- pgrp is pointer to flag group
- flags is bit pattern indicating which bit(s) to
check1 implies check - wait_type specifies all or any bits
- OS_FLAG_WAIT_CLR_ALL check all bits in flags to
be zero - OS_FLAG_WAIT_CLR_ANY check any of bits in flags
to be zero - OS_FLAG_WAIT_SET_ALL check all bits in flags to
be one - OS_FLAG_WAIT_SET_ANY check any of bits in flags
to be one - consume flag by adding OS_FLAG_CONSUME (checks
flag and clears it) - timeout is number of ticks to wait
- err is pointer to error code
- OS_NO_ERR no error
- OS_ERR_PEND_ISR tried to pend from an ISR which
is nono - OS_FLAG_INVALID_PGRP passed null pointer
- OS_ERR_EVENT_TYPE not pointing to event flag
group - OS_TIMEOUT flags not available within specified
amount of time - OS_FLAG_WAIT_TYPE improper wait_type argument
- example
36Additional Intertask Communication Methods
- Message Mailboxes
- task can place a pointer in a mailbox for another
task to access - kernel provides services
- Message Queues
- array of mailboxes
- messages may be accessed FIFO or LIFO