Professional Documents
Culture Documents
INTRODUCTION TO RTOS
Tasks
Issue – Scheduler/Task signal exchange for block-unblock of tasks via function
calls
Issue – All tasks are blocked and scheduler idles forever (not desirable!)
Issue – Two or more tasks with same priority levels in Ready state
(time-slice, FIFO)
Example: scheduler switches from processor-hog vLevelsTask to
vButtonTask (on user interruption by pressing a push-button),
controlled by the main() which initializes the RTOS, sets priority
levels, and starts the RTOS
(See Fig 6.2, Fig 6.3, Fig 6.4)
I* "Button Task" */
void vButtonTask (void) /* High priority */
{
while(TRUE)
{
!! Block until user pushes a button
!! Quick: respond to the user
}
}
I* "Levels Task" */
void vLevelsTask (void) /* Low priori y */
{
while(TRUE)
{
!! Read levels of floats in tank
!!Calculate average float level (continued )
!!Do some intermi nablecalculation
!!Do more intermi nablecal culation
!! Do yet more interminable calculation
!! Figure out which tank to do next
)
}
Figure 6.3 Microprocessor Re ponds to a Button under an RTOS
v lev e1 sTaskis busy User presses button; vButtonTask vButtonTask finishes its
calculating RTOS switches does everything it work and blocks
microprocessor to needs to do to again; RTOS
while vButtonTask
vButtonTask; respond to the switches
is blocked.
vlevelsTask button. nucroprocessor
is ready. back to
/ vLevelsTask.
\ I
vButtonTask
Time------------------------
Each tasks has its won context - not shared, private registers, stack, etc.
In addition, several tasks share common data (via global data declaration; use of ‘extern’ in one
task to point to another ta sk that declares the shared data
Shared data caused the ‘shared-data problem’ without solutions discussed in Chp4 or use of
‘Reentrancy’ characterization of functions
(See Fig 6.5, Fig 6.6, Fig 6.7, and Fig 6.8)
Figure 6.6 Sharing Data among RTOS Tasks
struct
{
long lTankLevel:
long lTimeUpdated;
}tankdata[MAX_TANKS];
/* "Button Task" */
void vRespondToButton (void) /* High priority */
{
inti;
while(TRUE)
{
!! Block until user pushes abutton
i - !! ID of button pressed;
printf("\nTIME: %08ld LEVEL: %08ld". tankdata[i].lTimeUpdated,
tankdata[i].lTankLevel);
}
}
I* "Levels Task" */
void vCalculateTankLevels(void)
{
I* Low priority */
int i - 0; while
(TRUE) (
!1 Read levels of floats in tank i
!! Do more interminable calculation
!! Do yet more interminable calculation
struct
(
long lTankLevel;
long lTimeUpdated:
}tankdata[MAX_TANKS]:
/* "Button Task" */
void vRespondToButton(void)/* High priority */
(
inti:
while(TRUE)
(
Embedded System Design 06EC82
II Block until user pushes a button
1 - II Get 10 of button pressed
TakeSemaphore():
printf("\nTIME:%08ld LEVEL:%081d", I* Low priority */
tankdata[i].lTimeUpdated,
tankdata[i].lTankLevel):
ReleaseSemaphore();
}
}
/* "Levels Task" */
void vCalculateTanklevels (void)
{
int i - 0:
while(TRUE)
{
TakeSemaphore();
!!Set tankdata[i].1TimeUpdated
!! Set tankdata[i].1TankLeve7
ReleaseSemaphore();
)
}
6.3 Semaphores and Shared Data – 1
void ma i n <void)
{
I* Initialize(but do not start> the RTOS*I
OSinit():
vCountErrors(11);
)
while <TRUE)
{
I* Wait for a message telling what report to format.*I
wMsg-(int)OSQPend (QPrinterTask, WAIT_FOREVER, &byError);
else
I* Print the next line. *I
vHardwarePrinterOutputline(a chPrint[iLinesPrinted++]);
}
Task A gets a
message in its
queue and
unblocks; RTOS
switches to Task A.
Task C
Ti me ---------------------------------------------------- .
Basic techniques for inter-task communication and data sharing are: interrupt
enable/disable and using semaphores. E.g., the tank monitoring tasks and
serial port and printer handling tasks
Others supported by RTOS: Message Queues, Mailboxes and Pipes
Example of Message Queue: (See Fig 7.1)
Task1 and Task2 (guaranteed to be reentrant) compute
separate functions
Use services of vLogError and ErrorsTask (vLogError enqueues
errors for ErrorsTask to process)
vLogError is supported by AddToQueue function, which keeps
a queue of integers for the RTOS to interpret or map to error- type.
Using the ReadFromQueue function, the RTOS then activates
ErrorTask to handle the error if the queue is not empty – freeing
Task1 and Task2 to continue their tasks.
Functions AddToQueue and ReadFromQueue are non-
reentrant, and the RTOS switches between Task1 and Task2 in the
middle of their tasks execution are guaranteed to be ok
void Task2(void)
(
if (JJproblem arises>
vLogError(ERROR_TYPE_Y);
}
7.1 Message Queues, Mailboxes, and Pipes – 1
Difficulties in using Queues:
Queue initialization (like semaphore initialization) must be dedicated
to a separate task to a) guarantee correct start-up values and b)
avoid uncertainty about task priorities and order of execution which
might affect the queue’s content
Queues must be tagged (identify which queue is referenced)
Need code to manage the queue (when full and empty) if RTOS
doesn’t – block reading/writing task on empty/full, plus returning an
error code
RTOS may limit the amount of info to write/read to queue in any
single call
I* The data space for our queue. The RTOS will manage this.*/
#define SIZEOF_QUEUE 25
void *apvQueue[SIZEOF_OUEUE];
if {!!problem arises)
vlogError (ERROR_TYPE_Y);
while(TRUE)
{
!!Wait until it's time to read the next temperature
wh1le(TRUE)
{
pTemperatures
(int *)OSQPend (pOseQueueTemp, WAIT_FOREVER. &byErr);
if(pTemperatures[OJ 1- pTemperatures[l])
11 Set off howling alarm:
free(pTemperatures);
02 }
}
7.1 Message Queues, Mailboxes, and Pipes
Using Mailboxes:
Purpose is similar to queues (both supporting asynchronous task
communication)
Typical RTOS function for managing mailboxes – create, write, read,
check-mail, destroy
Variations in RTOS implementations of mailboxes
Either a single-message mailbox or multi-message mailbox (set #
entries at start)
# of messages per mailbox could be unlimited, but total # in the
system could be (with possibility of shuffling/distributing messages
among mailboxes)
Mailboxes could be prioritized
Examples: (from the RTOS – MultiTask! )
int sndmsg (unsigned int uMbid, void *p_vMsg, unsigned int uPriority);
void *rcvmsg(unsigned int uMbid, unsigned int uTimeout);
void *chkmsg(unsigned int uMbid);
Using Pipes:
Pipes are implemented as (special) files, using normal file-descriptors
RTOS can create, read from, write to, destroy pipes (typically: each
pipe has 2 ends)
Details of implementation depends on RTOS
Pipes can have varying length messages (unlike fixed length for
queues / mailboxes)
Pipes could be byte-oriented – and read/write by tasks depends on #
bytes specified
In standard C, read/write of pipes use fread/fwrite functions,
respectively
Programming queues, mailboxes, and pipes – caution!
Coding tasks to read from or write to intended ‘structure’
(RTOS can’t help on mismatch)
Interpretation and processing of message types (see code
segments on p. 182)
• Overflow of 'structure' size - could cripple the software, so need
to set size as large as possible
• Passing pointers in 'structures' provides 'unwanted'
opportunity to create shared data problem
• (See Fig 7.4)
while(TRUE)
{
I! Wait until it's time to read the next temperature
Timer Functions
Issues:
Embedded systems track time passage, hence, need to keep time
(e.g., to save battery life, power need to be shut off automatically
after, say, X seconds; a message send-task expects an ACK after Y
seconds, it is delayed Y seconds and may retransmit; task is allowed a slice of time
after which it is blocked)
RTOS provides these timing services or functions
(See Fig 7.5 – VsWorks RTOS support for taskDelay(nticks) function in
telephone call code)
RADIO_STARTING.
RADIO_TX_ON,
RAOIO_RX_ON,
} eRadioState: I* State of the radio*I
eRadioState - RADIO_OFF;
while(TRUE)
{
I* Find out what to do next*I
msgQReceive(queueRadio.a_chMsg, MAX_MSG. WAIT_FOREVER):
I* The first character of the message tells this task what the message is.*I
switch(a _chMsg[OJ)
{
case 'T':
case 'R':
I* Someone wants to turn on the transmitter *I
if(eRadioState -- RADIO_OFF)
{
!! Turn on power to the radio hardware.
eRadioState - RADIO_STARTING:
/* Get the frequency from the message */
iFrequency-*(int *) a_chMsg[l];
else
J J Handle error. Can't turn radio on if not off
break;
case 'K':
/* The radio is ready. */
eRadioState- RADIO_TX_ON;
J! Do whatever we want to do with the radio
break;
case 'L':
I* The radio is ready. */
eRadioState - RAOIO_RX_ON;
!I Do whatever we want to do with the radio
break;
case 'X':
/* Someone wants to turn off the radio. */
if (eRadioState -- RADIO_TX_ON I I
eRadioState -- RADIO_RX_ON)
(
!1 Turn oFf power to the radio hardware.
eRad1oState - RADIO_OFF;
}
else
11 Handle error. Can't turn radio off if not on
break:
default:
11 Deal with the error of a bad message
break:
}
)
7.3 Events
In standard OS, an event is typically an indication which is related to time
In RTOS, an event is a boolean flag, which is set and reset by tasks/routines
for other tasks to wait on
RTOS is supposed to manage several events for the ‘waiting’ tasks. Blocked
or waiting tasks are unblocked after the event occurrence, and the event is
reset
E.g., pulling the trigger of a cordless bar-code scanner sets the flag for a
waiting task, which turns of the laser beam for scanning, to start running
(See Fig 7.8 and Fig 7.9)
Figure 7.8 Using Events
!! Figure out which key the user pressed and store that value
!! When the scan has been found. turn off the scanner.
}
}
void vRadioTask (void)
(
while (TRUE)
(
I* Wait for the user to pull the trigger or press a key. *I
ajevwat (amxidTrigger. TRIGGER_MASK I KEY_MASK.
TRIGGER_SET I KEY_SET, WAIT_FOR_ANY ,
WAIT_FOREVER):
I* Reset the key event. (The trigger event will be reset by the ScanTask.)*I
ajevsig (amxidTrigger, KEY_MASK. KEY_RESET);
7.3 Events – 1
Features of events (and comparison with semaphores, queues, mbox,
pipes):
More than one task can wait on the same event (tasks are activated
by priority)
Events can be grouped, and tasks may wait on a subset of events in a
group
Resetting events is either done by the RTOS automatically or your
embedded software
Tasks can wait on only one semaphore, queue, mbox or pipe, but on
many events simultaneously.
Semaphores are faster, but unlike queues, mboxes, and pipes, they
carry 1-bit info
Queues, mboxes, and pipes are error prone and message
posting/retrieval is compute-intensive
7.4 Memory Management
In general RTOS offer C lang equivalent of malloc and free for MM, which
are slow and unpredictable
Real time system engineers prefer the faster and more predictable
alloc/free functions for fixed size buffers. E.g., MultiTask! RTOS allocates
pools of fixed size buffers, using
getbuf() [with timed task blocking on no buffers] and reqbuf() [with
no blocking and return of NULL pointer on no buffers]
relbuf() to free buffers in a given pool (buffer pointer must be valid)
Note that most embedded sw is integrated with the RTOS (same
address space) and the ES starts the microprocessor; hence your ES
must tell the memory-pool
(See Fig 7.10 and Fig 7.11 – high priority FormatTask and low priority
OutputTask)
Figure 7.10 The i ni t _mem_pool Function in MultiTask!
p_ vMemory-
uBufCount
. _1_
uBuf S1zeT
Figure 7.11 Using Memory Management Functions
MAX_LINES.MAX_LINE_LENGTH.TASK_POOL);
}
void vPrintFormatTask (void)
{
char *p_chline; I* Pointer to current line */
I* Get a new set of temperatures.*/ aTemperatures[O)- 1! read in value from hardware: aTemperatures[l]-
11 read in value from hardware:
while(TRUE)
(
lTemps -(long) sc_qpend (iQueueTemp, WAIT_FOREVER. sizeof(int). &1Error);
aTemperatures[O]- Cint)ClTemps >> 16); aTemperatures[l]-(int)(lTemps &OxOOOOffff): if
(aTemperatures[O] !-aTemperatures[l])
11 Set off howling alarm:
)
)
1. What are the three states in a task. explain it with neat block diagram
2. Describe the use of take semaphore( ) and release semaphore( ) with an
example .
3. Explain any 6 problems with semaphores.
4. Describe the use of message queues, mailbox and pipes.
5. Explain memory management in multitasking.
6. How does interrupt routines work in RTOS environment.
7. What are nested interrupts ? and how do they work?