Chapter 1 Sample Code Real-Time Programming Two Types of ...
Chapter 1 Sample Code Real-Time Programming Two Types of ...
Chapter 1 Sample Code Real-Time Programming Two Types of ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Two</strong> <strong>Types</strong> <strong>of</strong> <strong>Real</strong>-time System<br />
<strong>Chapter</strong> 1 <strong>Sample</strong> <strong>Code</strong><br />
1<br />
• Must finish operations by deadlines.<br />
– Hard real time: missing deadline causes failure.<br />
• Tasks have to be performed not only correctly but<br />
on time<br />
– S<strong>of</strong>t real time: missing deadline results in degraded<br />
performance.<br />
• Tasks are performed by the system as fast as<br />
possible<br />
• Most real-time systems have a combination <strong>of</strong><br />
SOFT and HARD requirements.<br />
• Most real-time systems are embedded<br />
3<br />
<strong>Real</strong>-<strong>Time</strong> <strong>Programming</strong><br />
Multi-task <strong>Programming</strong><br />
Single Task:<br />
Multi Task:<br />
Subroutine 1<br />
Task A<br />
Task C<br />
Main routine<br />
•••<br />
Task B<br />
Task D<br />
Subroutine n<br />
Subroutine<br />
No<br />
1<br />
2<br />
3<br />
Task<br />
No<br />
1<br />
2<br />
3<br />
(a) Sequential subroutine calls (cyclic executive)<br />
(b) Multi-tasking<br />
subroutine 3 finished<br />
calling subroutine 2<br />
task 1 suspended<br />
resume task 3<br />
time<br />
time<br />
2<br />
4
• A typical real-time multi-tasking program<br />
main( )<br />
{<br />
...<br />
subroutine1( ... );<br />
...<br />
subroutine2( ... );<br />
...<br />
subroutine3( ... );<br />
...<br />
}<br />
Cyclic Executive<br />
execute<br />
every<br />
10 ms<br />
execute<br />
whenever<br />
the CPU<br />
is available<br />
give up<br />
CPU time<br />
main( )<br />
{<br />
...<br />
create( task1, 10, ... );<br />
create( task2, 20, ... );<br />
create( task3, -1, ... );<br />
...<br />
} ....<br />
task2()<br />
{ ....<br />
if( ...) suspend( );<br />
...<br />
}<br />
Multi-tasking<br />
1.04 OS_Enter_Critical() and<br />
OS_Exit_Critical()<br />
#define OS_CRITICAL_METHOD 2<br />
#if OS_CRITICAL_METHOD == 1<br />
#define OS_ENTER_CRITICAL() asm CLI<br />
#define OS_EXIT_CRITICAL() asm STI<br />
#endif<br />
#if OS_CRITICAL_METHOD == 2<br />
#define OS_ENTER_CRITICAL() asm {PUSHF; CLI}<br />
#define OS_EXIT_CRITICAL() asm POPF<br />
#endif<br />
• Disabling interrupts affects interrupt latency, so be<br />
carefully<br />
5<br />
7<br />
Task Scheduling (which one can be serviced<br />
by CPU)<br />
• Round-robin and time-slicing<br />
– What is the difference?<br />
Task No<br />
1<br />
2<br />
3<br />
Task No<br />
1<br />
2<br />
3<br />
(a)<br />
(b)<br />
<strong>Time</strong><br />
<strong>Time</strong><br />
Round-robin<br />
<strong>Time</strong>-sliced<br />
(More fairness)<br />
a quantum<br />
6<br />
1.07 Example 1<br />
• Consist 13 tasks<br />
– <strong>Two</strong> internal tasks: the idle task and a task that determines CPU<br />
usage<br />
– Create 11 tasks: the TaskStart() task is created by main()<br />
– Other 10 tasks is create by TaskStart() task. This 10 tasks are based<br />
on the same code<br />
void main (void)<br />
{<br />
PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); (1)<br />
OSInit(); (2)<br />
PC_DOSSaveReturn(); (3)<br />
PC_VectSet(uCOS, OSCtxSw); // INT 80H 200HZ (4)<br />
RandomSem = OSSemCreate(1); (5)<br />
OSTaskCreate(TaskStart, (6)<br />
(void *)0,<br />
(void *)&TaskStartStk[TASK_STK_SIZE-1],<br />
0);<br />
OSStart(); (7)<br />
}<br />
– OSInit () creates two tasks : an idle task, which executes when no<br />
other task is ready to run and a statistic task, which computes CPU<br />
usage<br />
8
Listing 1.3 Example #1, TaskStart()<br />
void TaskStart (void *data)<br />
{<br />
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */<br />
OS_CPU_SR cpu_sr;<br />
#endif<br />
char s[100];<br />
INT16S key;<br />
pdata = pdata; (1) /* Prevent compiler warning */<br />
TaskStartDispInit(); (2) /* Initialize the display */<br />
OS_ENTER_CRITICAL(); (3)<br />
PC_VectSet(0x08, OSTickISR); (4)<br />
PC_SetTickRate(200); (5)<br />
OS_EXIT_CRITICAL(); (6)<br />
OSStatInit(); (7)<br />
TaskStartCreateTasks()<br />
(8) Create 10 identical tasks;<br />
for (;;) {<br />
TaskStartDisp();<br />
// Display the number <strong>of</strong> tasks created;<br />
if (key was pressed) {<br />
if (key pressed was the ESCAPE key) {<br />
PC_DOSReturn();<br />
}<br />
}<br />
Delay for 1 Second;<br />
}<br />
}<br />
Listing 1.4 Example #1 TaskStartCreateTasks()<br />
static void TaskStartCreateTasks (void)<br />
{<br />
INT8U i;<br />
for (i = 0; i < N_TASKS; i++) { /* Create N_TASKS identical tasks */<br />
TaskData[i] = '0' + i; /* Each task will display its own letter */<br />
OSTaskCreate(Task,<br />
(void *)&TaskData[i],<br />
&TaskStk[i][TASK_STK_SIZE - 1],<br />
i + 1);<br />
}<br />
}<br />
If you run code in an embedded application, you should always enable the ticker within the first task<br />
9<br />
11<br />
Example #1 Determining the PC’s speed<br />
void OSStatInit (void)<br />
{<br />
OS<strong>Time</strong>Dly(2); (1)<br />
OS_ENTER_CRITICAL();<br />
OSIdleCtr = 0L; (2)<br />
OS_EXIT_CRITICAL();<br />
OS<strong>Time</strong>Dly(OS_TICKS_PER_SEC); (3)<br />
OS_ENTER_CRITICAL();<br />
OSIdleCtrMax = OSIdleCtr; (4)<br />
OSStatRdy = TRUE; (5)<br />
OS_EXIT_CRITICAL();<br />
}<br />
• OSIdleCtrMax contains the largest value <strong>of</strong> the OSIdleCtl<br />
• Use OSStatTask() to compute the CPU utilization, which<br />
executes every second<br />
Listing 1.5 Example #1 Task that displays a number<br />
at random locations on the screen<br />
void Task (void *data)<br />
{<br />
UBYTE x;<br />
UBYTE y;<br />
UBYTE err;<br />
for (;;) {<br />
OSSemPend(RandomSem, 0, &err); (1)<br />
x = random(80); (2)<br />
y = random(16);<br />
OSSemPost(RandomSem); (3)<br />
PC_DispChar(x, y + 5, *(char *)data, DISP_FGND_LIGHT_GRAY); (4)<br />
OS<strong>Time</strong>Dly(1); (5)<br />
}<br />
}<br />
• TaskStart () creates all the 10 identical tasks, and no<br />
context switch occurs because TaskStart() has a priority <strong>of</strong><br />
0 (the highest priority)<br />
10<br />
12