• 沒有找到結果。

Started with uC uC /OS /OS - - II II

N/A
N/A
Protected

Academic year: 2022

Share "Started with uC uC /OS /OS - - II II"

Copied!
50
0
0

加載中.... (立即查看全文)

全文

(1)

Chapter 1: Getting

Started with uC/OS-II Chapter 1: Getting Chapter 1: Getting Started with

Started with uC uC /OS /OS - - II II

Dr. Li

Dr. Li -Pin Chang - Pin Chang

Real Real - - Time and Embedded System Lab. Time and Embedded System Lab.

National Taiwan University

National Taiwan University

(2)

Text Book

• Jean J. Labresse, MicroC/OS-II:

The Real-Time Kernel.

ISBN: 1-57820-103-9

(3)

uC/OS-2

• A very small real-time kernel.

– Memory footprint is about 20k for a fully functional kernel.

– It’s source is open.

– Preemptible priority-driven real-time scheduling.

– Support many platforms: x86, 68x, MIPS…

– Very easy to develop: Borland C++ compiler and DOS (optional).

• However, it lacks of…

– Resource synchronization protocols.

– Sporadic task support.

– Soft-real-time support.

(4)

Getting started with uC/OS-2!

• See what a uC/OS-2 program looks like.

• Learn how to write a skeleton program for uC/OS-2.

– How to initialize uC/OS-2?

– How to create real-time tasks?

– How to use inter-task communication mechanism?

– How to catch system event?

(5)

Example 1

(6)

Example 1

• uC/OS-2 can run with or without DOS.

– DOS box under Windows

– Boot directly from image on HDD/FDD.

– Convenient to test and debug.

(7)

Example 1

• Files needed:

– The main program (test.c)

– The configuration for uC/OS-2(os_cfg.h) – The big include file (includes.h)

• Tools needed:

– Borland C++ compiler (V3.1+)

– A PC!!

(8)

Example 1

• 13 tasks run concurrently.

– 2 internal tasks:

• The idle task and the statistic task.

– 11 user tasks:

• Randomly print numbers onto the screen.

• Focus: System initialization and task

creation.

(9)

Example 1

#include "includes.h"

/*

*********************************************************************************************************

* CONSTANTS

*********************************************************************************************************

*/

#define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */

#define N_TASKS 10 /* Number of identical tasks */

/*

*********************************************************************************************************

* VARIABLES

*********************************************************************************************************

*/

OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /* Tasks stacks */

OS_STK TaskStartStk[TASK_STK_SIZE];

char TaskData[N_TASKS]; /* Parameters to pass to each task */

OS_EVENT *RandomSem;

A semaphore

(explain later)

(10)

Main()

void main (void)

{

PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); (1)

OSInit(); (2)

PC_DOSSaveReturn(); (3)

PC_VectSet(uCOS, OSCtxSw); (4)

RandomSem = OSSemCreate(1); (5)

OSTaskCreate(TaskStart, (6)

(void *)0, (void *)&TaskStartStk[TASK_STK_SIZE-1], 0);OSStart(); (7)

}

(11)

Main()

• OSinit():

– Init internal structures of uC/OS-2.

• Task ready list.

• Priority table.

• Task control blocks (TCB).

• Free pool.

– Create housekeeping tasks.

• The idle task.

• The statistics task.

(12)

OSinit()

OSTCBStkPtr OSTCBExtPtr = NULL OSTCBStkBottom OSTCBStkSize = stack size OSTCBId = OS_LOWEST_PRIO OSTCBNext

OSTCBPrev OSTCBEventPtr = NULL OSTCBMsg = NULL OSTCBDly = 0 OSTCBStat = OS_STAT_RDY OSTCBPrio = OS_LOWEST_PRIO-1 OSTCBX = 6

OSTCBY = 7 OSTCBBitX = 0x40 OSTCBBitY = 0x80 OSTCBDelReq = FALSE

OSTCBStkPtr OSTCBExtPtr = NULL OSTCBStkBottom OSTCBStkSize = stack size OSTCBId = OS_LOWEST_PRIO OSTCBNext

OSTCBPrev OSTCBEventPtr = NULL OSTCBMsg = NULL OSTCBDly = 0 OSTCBStat = OS_STAT_RDY OSTCBPrio = OS_LOWEST_PRIO OSTCBX = 7

OSTCBY = 7 OSTCBBitX = 0x80 OSTCBBitY = 0x80 OSTCBDelReq = FALSE

0 0

0 0 0 0 0 0 0 0 0 0

[OS_LOWEST_PRIO]

[OS_LOWEST_PRIO - 1]

[0]

[1]

[2]

[3]

[4]

[5]

[6]

OS_TCB OS_TCB

OSTaskStat() OSTaskIdle() OSTCBPrioTbl[]

OSTCBList

OSPrioCur = 0 OSPrioHighRdy = 0 OSTCBCur = NULL OSTCBHighRdy = NULL OSTime = 0L OSIntNesting = 0 OSLockNesting = 0 OSCtxSwCtr = 0 OSTaskCtr = 2 OSRunning = FALSE OSCPUUsage = 0 OSIdleCtrMax = 0L OSIdleCtrRun = 0L OSIdleCtr = 0L

OSStatRdy = FALSE Task Stack Task Stack

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0

OSRdyGrp

OSRdyTbl[]

Ready List

*

(13)

OSinit()

OSTCBStkPtr OSTCBExtPtr OSTCBStkBottom OSTCBStkSize OSTCBId OSTCBNext OSTCBPrev OSTCBEventPtr OSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq OS_TCB

0 OSTCBFreeList

OS_MAX_TASKS

0 OSEventFreeList

OS_MAX_EVENTS

OS_EVENT OS_EVENT OS_EVENT OS_EVENT

OSQPtr OSQStart OSQEnd OSQIn OSQOut OSQSize OSQEntries OSEventPtr OSEventTbl[]

OSEventCnt OSEventType OSEventGrp

OSTCBStkPtr OSTCBExtPtr OSTCBStkBottom OSTCBStkSize OSTCBId OSTCBNext OSTCBPrev OSTCBEventPtr OSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq OS_TCB

OSTCBStkPtr OSTCBExtPtr OSTCBStkBottom OSTCBStkSize OSTCBId OSTCBNext OSTCBPrev OSTCBEventPtr OSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq OS_TCB

OSEventPtr OSEventTbl[]

OSEventCnt OSEventType OSEventGrp

OSEventPtr OSEventTbl[]

OSEventCnt OSEventType OSEventGrp

OSEventPtr OSEventTbl[]

OSEventCnt OSEventType OSEventGrp OSTCBStkPtr OSTCBExtPtr OSTCBStkBottom OSTCBStkSize OSTCBId OSTCBNext OSTCBPrev OSTCBEventPtr OSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq OS_TCB

0 OSQFreeList

OS_MAX_QS

OS_Q OS_Q OS_Q

OSQPtr OSQStart OSQEnd OSQIn OSQOut OSQSize OSQEntries

OSQPtr OSQStart OSQEnd OSQIn OSQOut OSQSize OSQEntries

OSQPtr OSQStart OSQEnd OSQIn OSQOut OSQSize OSQEntries

OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSNFree

0 OSMemFreeList

OS_MAX_MEM_PART

OS_MEM

OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSNFree

OS_MEM OS_MEM OS_MEM

OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSNFree

OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSNFree

OS_Q

*

(14)

Main()

• PC_DOSSaveReturn()

– Save the current status of DOS for the future restoration.

• Interrupt vectors and the RTC tick rate.

– Set a global returning point by calling setjump().

• uC/OS-2 can come back here when terminating.

• PC_DOSReturn()

(15)

PC_DOSSaveReturn()

void PC_DOSSaveReturn (void)

{

PC_ExitFlag = FALSE; (1)

OSTickDOSCtr = 8; (2)

PC_TickISR = PC_VectGet(VECT_TICK); (3)

OS_ENTER_CRITICAL();

PC_VectSet(VECT_DOS_CHAIN, PC_TickISR); (4)

OS_EXIT_CRITICAL();

setjmp(PC_JumpBuf); (5)

if (PC_ExitFlag == TRUE) {

OS_ENTER_CRITICAL();

PC_SetTickRate(18); (6)

PC_VectSet(VECT_TICK, PC_TickISR); (7)

OS_EXIT_CRITICAL();

PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); (8)

exit(0); (9)

}

}

*

(16)

Main()

• PC_VectSet(uCOS,OSCtxSw)

– Install the context switch handler.

– Interrupt 0x08 under 80x86 family.

• Invoked by int instruction.

*

(17)

Main()

• OSSemCreate()

– Create a semaphore for resource synchronization.

• To protect non-reentrant codes.

– The created semaphore becomes a mutual exclusive mechanism if “1” is given as the initial value.

– In this example, a semaphore is created to protect the standard C library “random()”.

*

(18)

Main()

• OSTaskCreate()

– Create tasks by the given arguments.

– Tasks become “ready” after they are created.

• Task

– An active entity which could do some computations.

Priority, CPU registers, stack, text, housekeeping status.

– uC/OS-2 allows maximum 63 tasks created.

• The uC/OS-2 picks up the highest priority task to run on context-switch.

– Tightly coupled with RTC ISR.

(19)

OSTaskCreate()

• OSTaskCreate(

TaskStart,

(void *)0,

&TaskStartStk[TASK_STK_SIZE - 1], 0

); Priority

(0=hightest) Top of Stack

Entry point of the task (a pointer to function)

User-

specified data

(20)

TaskStart()

void TaskStart (void *pdata)

{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */

OS_CPU_SR cpu_sr;

#endif

char s[100];

INT16S key;

pdata = pdata; /* Prevent compiler warning */

TaskStartDispInit(); /* Initialize the display */

OS_ENTER_CRITICAL();

PC_VectSet(0x08, OSTickISR); /* Install uC/OS-II's clock tick ISR */

PC_SetTickRate(OS_TICKS_PER_SEC); /* Reprogram tick rate */

OS_EXIT_CRITICAL();

OSStatInit(); /* Initialize uC/OS-II's statistics */

TaskStartCreateTasks(); /* Create all the application tasks */

for (;;) {

TaskStartDisp(); /* Update the display */

if (PC_GetKey(&key) == TRUE) { /* See if key has been pressed */

if (key == 0x1B) { /* Yes, see if it's the ESCAPE key */

PC_DOSReturn(); /* Return to DOS */

}

}

OSCtxSwCtr = 0; /* Clear context switch counter */

OSTimeDlyHMSM(0, 0, 1, 0); /* Wait one second */

}

}

Change the

ticking rate

(21)

TaskStart()

• OS_ENTER(EXIT)_CRITICAL

– Enable/disable most interrupts.

– An alternative way to accomplish mutual exclusion.

• No rescheduling is possible during the disabling of interrupts.

• Different from semaphores.

– Processor specific.

• CLI/STI (x86 real mode)

• Interrupt descriptors (x86 protected mode)

(22)

TaskStartCreateTasks()

static void TaskStartCreateTasks (void)

{

INT8U i;

for (i = 0; i < N_TASKS; i++) {

TaskData[i] = '0' + i;

OSTaskCreate(

Task,

(void *)&TaskData[i],

&TaskStk[i][TASK_STK_SIZE - 1],

i + 1);

}

} Priority Stack

Argument: character to print

Entry point of the

created task

(23)

Task()

void Task (void *pdata)

{

INT8U x;

INT8U y;

INT8U err;

for (;;) {

OSSemPend(RandomSem, 0, &err);/* Acquire semaphore to perform random numbers */

x = random(80); /* Find X position where task number will appear */

y = random(16); /* Find Y position where task number will appear */

OSSemPost(RandomSem); /* Release semaphore */

/* Display the task number on the screen */

PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);

OSTimeDly(1); /* Delay 1 clock tick */

}

}

Semaphore

operations.

(24)

Semaphores

• OSSemPend() / OSSemPost()

– A semaphore consists of a wait list and an integer counter.

– OSSemPend:

• Counter--;

• If the value of the semaphore <0, the task is blocked and moved to the wait list immediately.

• A time-out value can be specified . – OSSemPost:

• Counter++;

• If the value of the semaphore >= 0, a task in the wait list is removed from the wait list.

– Reschedule if needed.

(25)

Main()

• OSStart()

– Start multitasking of uC/OS-2.

– It never returns to main().

– uC/OS-2 is terminated if PC_DOSReturn() is

called.

(26)

Summary: Example 1

• uC/OS-2 is initialized and started by calling OSInit() and OSStart(), respectively.

• Before uC/OS-2 is started,

– DOS status is saved by calling PC_DOSSaveReturn().

– Context switch handler is installed by calling PC_VectSet().

– User tasks must be created by OSTaskCreate().

• Shared resources can be protected by semaphores.

– OSSemPend(),OSSemPost().

(27)

Example 2

• Example 2 focuses on:

– More task creation options.

Stack usage of each task.

Floating point operations.

– Communication through mailbox.

(28)

Stack Usage of a Task

.OSTCBStkBottom

.OSTCBStkSize 0

0 0 0

Free Stack Space

Used Stack Space

Initial TOS Deepest Stack Growth

Stack Growth

LOW MEMORY

HIGH MEMORY

Current Location of Stack Pointer

(1) (2)

(3)

(5) (4) (6)

(7)

(8)

(29)

Example 2

(30)

#define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */

#define TASK_START_ID 0 /* Application tasks IDs */

#define TASK_CLK_ID 1

#define TASK_1_ID 2

#define TASK_2_ID 3

#define TASK_3_ID 4

#define TASK_4_ID 5

#define TASK_5_ID 6

#define TASK_START_PRIO 10 /* Application tasks priorities */

#define TASK_CLK_PRIO 11

#define TASK_1_PRIO 12

#define TASK_2_PRIO 13

#define TASK_3_PRIO 14

#define TASK_4_PRIO 15

#define TASK_5_PRIO 16

OS_STK TaskStartStk[TASK_STK_SIZE]; /* Startup task stack */

OS_STK TaskClkStk[TASK_STK_SIZE]; /* Clock task stack */

OS_STK Task1Stk[TASK_STK_SIZE]; /* Task #1 task stack */

OS_STK Task2Stk[TASK_STK_SIZE]; /* Task #2 task stack */

OS_STK Task3Stk[TASK_STK_SIZE]; /* Task #3 task stack */

OS_STK Task4Stk[TASK_STK_SIZE]; /* Task #4 task stack */

OS_STK Task5Stk[TASK_STK_SIZE]; /* Task #5 task stack */

OS_EVENT *AckMbox; /* Message mailboxes for Tasks #4 and #5 */

OS_EVENT *TxMbox;

2 Mailboxes

(31)

void main (void)

{

OS_STK *ptos;

OS_STK *pbos;

INT32U size;

PC_DispClrScr(DISP_FGND_WHITE); /* Clear the screen */

OSInit(); /* Initialize uC/OS-II */

PC_DOSSaveReturn(); /* Save environment to return to DOS */

PC_VectSet(uCOS, OSCtxSw); /* Install uC/OS-II's context switch vector */

PC_ElapsedInit(); /* Initialized elapsed time measurement */

ptos = &TaskStartStk[TASK_STK_SIZE - 1]; /* TaskStart() will use Floating-Point */

pbos = &TaskStartStk[0];

size = TASK_STK_SIZE;

OSTaskStkInit_FPE_x86(&ptos, &pbos, &size);

OSTaskCreateExt(TaskStart,

(void *)0,

ptos,

TASK_START_PRIO,

TASK_START_ID,

pbos,

size,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSStart(); /* Start multitasking */

}

Main()

(32)

void TaskStart (void *pdata)

{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */

OS_CPU_SR cpu_sr;

#endif

INT16S key;

pdata = pdata; /* Prevent compiler warning */

TaskStartDispInit(); /* Setup the display */

OS_ENTER_CRITICAL(); /* Install uC/OS-II's clock tick ISR */

PC_VectSet(0x08, OSTickISR);

PC_SetTickRate(OS_TICKS_PER_SEC); /* Reprogram tick rate */

OS_EXIT_CRITICAL();

OSStatInit(); /* Initialize uC/OS-II's statistics */

AckMbox = OSMboxCreate((void *)0); /* Create 2 message mailboxes */

TxMbox = OSMboxCreate((void *)0);

TaskStartCreateTasks(); /* Create all other tasks */

for (;;) {

TaskStartDisp(); /* Update the display */

if (PC_GetKey(&key)) { /* See if key has been pressed */

if (key == 0x1B) { /* Yes, see if it's the ESCAPE key */

PC_DOSReturn(); /* Yes, return to DOS */

}

}

OSCtxSwCtr = 0; /* Clear context switch counter */

OSTimeDly(OS_TICKS_PER_SEC); /* Wait one second */

}

}

TaskStart()

Create 2 mailboxes

The dummy loop

wait for ‘ESC’

(33)

void Task1 (void *pdata)

{

INT8U err;

OS_STK_DATA data; /* Storage for task stack data */

INT16U time; /* Execution time (in uS) */

INT8U i;

char s[80];

pdata = pdata;

for (;;) {

for (i = 0; i < 7; i++) {

PC_ElapsedStart();

err = OSTaskStkChk(TASK_START_PRIO + i, &data);

time = PC_ElapsedStop();

if (err == OS_NO_ERR) {

sprintf(s, "%4ld %4ld %4ld %6d",

data.OSFree + data.OSUsed,

data.OSFree,

data.OSUsed,

time);

PC_DispStr(19, 12 + i, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);

}

}

OSTimeDlyHMSM(0, 0, 0, 100); /* Delay for 100 mS */

}

}

Task1()

Task1: total 1024 Free 654 Used 370

The local variables

errata

(34)

void Task2 (void *data)

{

data = data;

for (;;) {

PC_DispChar(70, 15, '|', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(10);

PC_DispChar(70, 15, '/', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(10);

PC_DispChar(70, 15, '-', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(10);

PC_DispChar(70, 15, '\\', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(10);

}

}

void Task3 (void *data)

{

char dummy[500];

INT16U i;

data = data;

for (i = 0; i < 499; i++) { /* Use up the stack with 'junk' */

dummy[i] = '?';

}

for (;;) {

PC_DispChar(70, 16, '|', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(20);

PC_DispChar(70, 16, '\\', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(20);

PC_DispChar(70, 16, '-', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(20);

PC_DispChar(70, 16, '/', DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDly(20);

}

}

(35)

void Task4 (void *data)

{

char txmsg;

INT8U err;

data = data;

txmsg = 'A';

for (;;) {

OSMboxPost(TxMbox, (void *)&txmsg); /* Send message to Task #5 */

OSMboxPend(AckMbox, 0, &err); /* Wait for acknowledgement from Task #5 */

txmsg++; /* Next message to send */

if (txmsg == 'Z') {

txmsg = 'A'; /* Start new series of messages */

}

}

}

void Task5 (void *data)

{

char *rxmsg;

INT8U err;

data = data;

for (;;) {

rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); /* Wait for message from Task #4 */

PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW + DISP_BGND_BLUE);

OSTimeDlyHMSM(0, 0, 1, 0); /* Wait 1 second */

OSMboxPost(AckMbox, (void *)1); /* Acknowledge reception of msg */

}

}

Task4 and Task5

(36)

MailBox

• A mailbox is a data exchange between tasks.

– A mailbox consists of a data pointer and a wait-list.

• OSMboxPend():

– The message in the mailbox is retrieved.

– If the mailbox is empty, the task is immediately blocked and moved to the wait-list.

– A time-out value can be specified.

• OSMboxPost():

– A message is posted in the mailbox.

– If there is already a message in the mailbox, an error is returned (not overwritten).

– If tasks waiting for a message from the mailbox, the task with the highest priority is removed from the wait-list and

scheduled to run.

(37)

OSTaskStkInit_FPE_x86()

• OSTaskStkInit_FPE_x86(&ptos, &pbos,

&size)

• Passing the original top address, bottom address, and size of the stack.

• On return, the arguments are modified and some stack space are reserved for floating point library.

– For context switches.

(38)

OSCreateTaskExt()

OSTaskCreateExt(

TaskStart, (void *)0, ptos,

TASK_START_PRIO, TASK_START_ID, pbos,

size,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR

);

(39)

OSTaskStkCheck()

• Check for stack overflow.

– bos < (tos – stack length)

– Local variables, arguments for procedure calls, temporary storage for ISR’s.

– uC/OS-2 can check for stack overflow on the creation of tasks and when OSTaskStkCheck() is called.

– uC/OS-2 does not automatically check stacks.

(40)

Summary: Example2

• Local variable, function calls, and ISR’s will utilize the stack space of user tasks.

– ISR will use the stack of the interrupted task.

• If floating-point operations are needed, some stack space should be reserved.

• Mailbox can be used to synchronize among

tasks.

(41)

Example 3

• Passing user-specified data structures on task creations.

• Using message queues.

• Demonstrating how to use OS hooks to

receive desired event from the uC/OS-2.

(42)

Example 3

(43)

• #define TASK_STK_SIZE 512 /* Size of each task's stacks (# of WORDs) */

• #define TASK_START_ID 0 /* Application tasks */

• #define TASK_CLK_ID 1

• #define TASK_1_ID 2

• #define TASK_2_ID 3

• #define TASK_3_ID 4

• #define TASK_4_ID 5

• #define TASK_5_ID 6

• #define TASK_START_PRIO 10 /* Application tasks priorities */ • #define TASK_CLK_PRIO 11

• #define TASK_1_PRIO 12

• #define TASK_2_PRIO 13

• #define TASK_3_PRIO 14

• #define TASK_4_PRIO 15

• #define TASK_5_PRIO 16

• #define MSG_QUEUE_SIZE 20 /* Size of message queue used in example */

• typedef struct {

• char TaskName[30];

• INT16U TaskCtr;

• INT16U TaskExecTime;

• INT32U TaskTotExecTime;

• } TASK_USER_DATA;

• OS_STK TaskStartStk[TASK_STK_SIZE]; /* Startup task stack */

• OS_STK TaskClkStk[TASK_STK_SIZE]; /* Clock task stack */

• OS_STK Task1Stk[TASK_STK_SIZE]; /* Task #1 task stack */

• OS_STK Task2Stk[TASK_STK_SIZE]; /* Task #2 task stack */

• OS_STK Task3Stk[TASK_STK_SIZE]; /* Task #3 task stack */

• OS_STK Task4Stk[TASK_STK_SIZE]; /* Task #4 task stack */

• OS_STK Task5Stk[TASK_STK_SIZE]; /* Task #5 task stack */

• TASK_USER_DATA TaskUserData[7];

• OS_EVENT *MsgQueue; /* Message queue pointer */

• void *MsgQueueTbl[20]; /* Storage for messages */

Message queue and an array of event

User-defined data

structure to pass to tasks

(44)

• void Task1 (void *pdata)

• {

• char *msg;

• INT8U err;

• pdata = pdata;

• for (;;) {

• msg = (char *)OSQPend(MsgQueue, 0, &err);

• PC_DispStr(70, 13, msg, DISP_FGND_YELLOW + DISP_BGND_BLUE);

• OSTimeDlyHMSM(0, 0, 0, 100);

• }

• }

• void Task2 (void *pdata)

• {

• char msg[20];

• pdata = pdata;

• strcpy(&msg[0], "Task 2");

• for (;;) {

• OSQPost(MsgQueue, (void *)&msg[0]);

• OSTimeDlyHMSM(0, 0, 0, 500);

• }

• }

Task 2, 3, 4 are functionally

identical.

(45)

Message Queues

• A message queue consists an array of elements and a wait- list.

• Different from a mailbox, a message queue can hold many data elements (in a FIFO basis).

• As same as mailboxes, there can be multiple tasks pend/post to a message queue.

OSQPost(): a message is appended to the queue. The

highest-priority pending task (in the wait-list) receives the message and is scheduled to run, if any.

OSQPend(): a message is removed from the array of

elements. If no message can be retrieved, the task is moved

to the wait-list and becomes blocked.

(46)

• A hook function will be called by uC/OS-2 when the corresponding event occurs.

– Event handlers in user programs.

– For example, OSTaskSwHook () is called every time when context switch occurs.

• The hooks are specified in compile time in uC/OS-2.

– Since it is an embedded OS.

– Most OS’s can register and un-register hooks.

Hooks

(47)

• void OSInitHookBegin (void)

• void OSInitHookEnd (void)

• void OSTaskCreateHook (OS_TCB *ptcb)

• void OSTaskDelHook (OS_TCB *ptcb)

• void OSTaskIdleHook (void)

• void OSTaskStatHook (void)

• void OSTaskSwHook (void)

• void OSTCBInitHook (OS_TCB *ptcb)

• void OSTimeTickHook (void)

User Customizable Hooks

(48)

• void OSTaskStatHook (void)

• {

• char s[80];

• INT8U i;

• INT32U total;

• INT8U pct;

• total = 0L; /* Totalize TOT. EXEC. TIME for each task */

• for (i = 0; i < 7; i++) {

• total += TaskUserData[i].TaskTotExecTime;

• DispTaskStat(i); /* Display task data */

• }

• if (total > 0) {

• for (i = 0; i < 7; i++) { /* Derive percentage of each task */

• pct = 100 * TaskUserData[i].TaskTotExecTime / total;

• sprintf(s, "%3d %%", pct);

• PC_DispStr(62, i + 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);

• }

• }

• if (total > 1000000000L) { /* Reset total time counters at 1 billion */

• for (i = 0; i < 7; i++) {

• TaskUserData[i].TaskTotExecTime = 0L;

• }

• }

• }

• void OSTaskSwHook (void)

• {

• INT16U time;

• TASK_USER_DATA *puser;

• time = PC_ElapsedStop(); /* This task is done */

• PC_ElapsedStart(); /* Start for next task */

• puser = OSTCBCur->OSTCBExtPtr; /* Point to used data */

• if (puser != (TASK_USER_DATA *)0) {

• puser->TaskCtr++; /* Increment task counter */

• puser->TaskExecTime = time; /* Update the task's execution time */

• puser->TaskTotExecTime += time; /* Update the task's total execution time */

• }

• }

(49)

Summary: Example 3

• Message queues can be used to synchronize among tasks.

– Multiple message can be held in the queue.

– Multiple tasks can pend/post to message queues simultaneously.

• Hooks can be used to do some user- specific computations on certain OS events occurs.

– They are specified in compile time.

(50)

Summary: Getting

Started with uC/OS-2

• Have you understood:

– how to write a dummy uC/OS-2 program?

– how the control flows among procedures?

– how tasks are created?

– how tasks are synchronized by

semaphore, mailbox, and message queues?

– how the space of stacks are utilized?

– how to capture system events?

參考文獻

相關文件

Department of Mathematics National Cheng Kung

On the other hand, by (22), the triangle inequality, and the definition of the operator norm... On the other hand, by (22), the triangle inequality, and the definition of the

Department of Mathematics National Cheng Kung

Department of Mathematics National Cheng Kung

• The cost per megabyte of hard disk storage is competitive with magnetic tape if only one tape is used per drive. • The cheapest tape drives and the cheapest disk drives have

Outros artefactos têxteis confeccionados; sortidos; artefactos de matérias têxteis, calçado, chapéus e artefactos de uso semelhante, usados;

* All rights reserved, Tei-Wei Kuo, National Taiwan University,

– Each time a file is opened, the content of the directory entry of the file is moved into the table.. • File Handle (file descriptor, file control block): an index into the table