uCOS ppt
-
Upload
kishan1234 -
Category
Documents
-
view
717 -
download
1
Transcript of uCOS ppt
uCOS II
RTOS
Reference Book
Bu ild G C C f o r th e 1 s t t im e( w ith o u t G lib c )
Bu ild Bin ar y to o ls
Bu ild G lib c( N eed k er n e l h ead f ile )
Bu ild G C C f o r th e 2 n dtim e
( W ith G lib c )
Bu ild u G lib c f o r em b ed d edd ev e lo p m en t
Bu ild G D B
Build Toolchain
Binutils
cd binutils-2.13.90.0.16./configure --target=powerpc-linux --prefix=/opt/linuxppcmakemake install
生成的可执行文件将被安装到 /opt/linuxppc/bin 目录下。也可以通过改变 --prefix 的值来指定其他任意路径。但最好不要将其指定为 /usr/local 或 /usr 以免毁坏操错系统现有的文件
GCC (1st Compile)
cd gcc-2.95.3./configure --target=powerpc-linux –prefix=/opt/linuxppc \--enable-shared --enable-languages=c --with-newlibmakemake install
Extract Kernel
tar xvfz …
GLIBCUn-compress GLIBC & glibc-linuxthreads
ln –s include/asm-ppc /opt/powerpc-linux/include/asmln –s include/linux /opt/powerpc-linux/include/linux
CC = powerpc-linux-gccAR=powerpc-linux-arRANLIB=powerpc-linux-ranlib./configure --host=powerpc-linux –enable-add-ons \ --with-headers=/opt/powerpc-linux/include\
--prefix=/opt/linuxppcmakemake install_root=/opt/powerpc-linux install
GCC (2nd Compile)
make distclean./configure --prefix=/opt/linuxppc –target=powerpc-linux \ --enable-shared –enable-threadsmake && make install
Why RTOS? Learn RTOS:
– Fill the gap between Computer Science Experts and Application Engineers
– Understanding Computer more theoretically
Using RTOS:– Simplify the Application Programming
Higher the System Performance and Reliability
Feature of Morden RTOS
CPU的管理 (硬件初始化、MMU 、定时器、中断 )
提供任务内存管理设备管理文件和网络的支持提供 C/C++ JAVA 图形模块等编程接口
Real Time Kernel
Advantage/Disadvantage of Using RTOS Advantage
– Split application to multi tasks, simplify the design, easy to be understand, expend and maintenance
– Time latency is guaranteed– Higher system reliability
Disadvantage– More RAM/ROM usage– 2~5% CPU overhead– Adding additional cost, if commercial TROS is
usedAbout 80 RTOS vendors, cost from $70 to $30,000 some are royalty free, some need $5 to $250 /MCU, MCU dependent
What is uCOS II?
Micro-Controller Operating Systems, Version 2
A very small real-time kernel. Memory footprint is about 20KB for a
fully functional kernel. Source code is about 5,500 lines,
mostly in ANSI C. It’s source is open but not free for
commercial usages.
Feature of uC/OSII
Preemptible priority-driven real-time scheduling.
64 priority levels (max 64 tasks), 8 reserved for uC/OS-II
Each task is an infinite loop. Deterministic execution times for most
uC/OS-II functions and services. Nested interrupts could go up to 256 levels.
Real Time Kernel on uCOS
µC/OS is Widely Used in Many Fields
cameras medical instruments Engine control musical instruments network adapter highway telephone call
box ATM machine industrial robots ……
Ports On Different CPUsManufacture MCU
AMD 80x86 Analog Device SHARC (AD21065L) ARM ARM7 Atmel AVR, AT103 Fujitsu SPARC Hitachi 64180, H8-300H, H8S,SH2,SH3 Infineon Tri.Core, 80C166/167 Intel Strong ARM110,80C251,XC52, 80x86,
196K Motorola M68HC08, M68HC11, M68HC12,
M68HC16, M68000, CPU32, DSP568xx, Cold.Fire,M.Core, PowerPC8xx,MPC555
Philips XA ST 80C166/167 TI TMS320-C40, TMS320-C6201 Automation V8 Zilog Z-80, Z-180
Roadmap of Learning Read the book and the µC/OS-II source code
– Understanding RTOS concepts Compiler the µC/OS-II with examples and run
on a PC– Add some codes to the examples
Porting the µC/OS-II to a MCU, which you are familiar with– Write the CPU.c and the CPU.a files
Do a project with a MCU board– Learn how to divide an application to several tasks– Communication and synchronization within tasks
uCOS II ArchitectureApplications (Tasks)
CPU Independent CodeuCOS-II.h (Global Var)uCOS_II.c Groups:
OS_Core.c OS_Task.c OS_Time.c OS_Sem.c OS_Mbox.c OS_Q.c OS_Mem.c
ApplicationConfiguration Code
OS_CFG.hIncludes.h
CPU Dependent CodeOS_CPU.H OS_CPU_A.ASM OS_CPU_C.C
CPU Startup Code ISR (Timer and Other INT)
Feature of uCOSII Portable : portable C, minimum uC dependent ASM
ROMable & Scalable
Preemptive : uC/OS-II is a fully preemptive real-time kernel
Multitasking : uC/OS-II can manage up to 64 tasks
Deterministic : Execution time of all uC/OS-II functions and service are deterministic
Deterministic : Each task requires its own different stack size
Services : Mailboxes, Queues, Semaphores, fixed-sized memory partitions, time-related functions
Interrupt Management
Int. can be nested up to 255 levels deep
Robust and Reliable
OS Functions Provided by uCOSII
Feature Not Supported by uCOS• Not support priority inheritance.
• With uC/OS-II, all tasks must have a unique priority, (Cannot Change While Running)
Term (1) Multitasking
– The process of scheduling and switching the CPU between several tasks
Task– A simple program which thinks it has the CPU all to
itself. Kernel
– The part of the multitasking system responsible for the management of tasks and communication between tasks
Task Switch– Kernel saves the current task's context (CPU
registers) onto the current task's stack.– Kernel load new task's context from the task’s stack
of new task
Term (2)
TCB– Task Control Block
Scheduler– Also called the dispatcher, is the part of the kernel
which is responsible for determining which task will run next
Non-preemptive scheduling– Each task is required to explicitly give up control of
the CPU. (ex. System API Call)– cooperative multitasking; tasks cooperate with each
other to gain control of the CPU.
Term (3)
Preemptive Kernel– In it, when an event makes a higher priority
task ready to run, the current task is immediately suspended and the higher priority task is given control of the CPU
Reentrancy– A reentrant function is a function which can
be used by more than one task without fear of data corruption.
uC/OS II Overview
TaskA() TaskB() TaskC()
IRQ1 IRQ2 IRQ3
Task Scheduler
{ { {
} } }
External IRQ
Timer
Multi-Tasking Overview
Sample Code (0)
Task0 Task1
MBox0 MBox1
Sample Code (1)
Global Variables
main(){ init OS; init Global Variables; init Task0 and Task1}
Task0(){ … }
Task1(){ … }
Sample Code (2)
#include "includes.h"
// Registers and data definition for our MX1 CPU#include "type.h" #include "mx1.h"
// Basic IO operation functionextern void EUARTinit(void);extern U8 EUARTgetData(void);extern void EUARTputString(U8 *line);
// Define stacks for eack task (32-bit)#define TASK_STK_SIZE 512OS_STK TaskStk[2][TASK_STK_SIZE];
// Function prototypes of tasksvoid Task0(void *data); void Task1(void *data);
// Mail boxes (Just two points)OS_EVENT* MBox0;OS_EVENT* MBox1;
Sample Code (3)
int main (void){ P_U32 temp; // Init UART controller EUARTinit(); EUARTputString("\nEntering main() now!\n");
// Init uCOS kernel OSInit(); // Create Mailbox MBox0 = OSMboxCreate((void*)0); MBox1 = OSMboxCreate((void*)0);
// Create two task OSTaskCreate(Task0, // Task function (void *)0, // point to data struct for this task &(TaskStk[0][TASK_STK_SIZE - 1]), // stacks for the task 1); // priority OSTaskCreate(Task1, // Task function (void *)0, // no data transfered &(TaskStk[1][TASK_STK_SIZE - 1]), // point to data struct for this task 2); // priority OSStart(); // Start multi-tasking now return 0; // Never comes here}
Sample Code (4)void Task0 (void *data){ int n = 0; int i; void* msg; INT8U err; while (1) { // Do something for (i = 0; i < 10000; i++) n++; // Tell people task0 is running EUARTputString("Enter task0\n"); // Send mail to mailbox 1 (to task 1) err = OSMboxPost(MBox1, (void*)&n);
// Waiting for mail from mailbox 0 (reply from task1)
msg = OSMboxPend(MBox0, 100, &err); // Get data attached in the mail n = *((int*)msg); } }
void Task1 (void *data){ int m = 0; int i; void* msg; INT8U err; while (1) { // Do something for (i = 0; i < 1234; i++) m++; // Tell people task1 is running EUARTputString("Enter task1\n"); // Waiting for mail from mailbox 1 (mail
from task 0) msg = OSMboxPend(MBox1, 100, &err);
// Get data attached in the mail m = *((int*)msg); // Reply the mail to mailbox 0 (to task 0) err = OSMboxPost(MBox0, (void*)&m); }}
Sample Code (5)
Calculate n
Send mail to 1
Waiting reply from 1
Retrieve data from mail
Calculate n
Send mail to 1
Waiting reply from 1
Retrieve data from mail
Calculate m
Reply 0
Wait mail from 0
Retrieve data from mail
Calculate m
Reply 0
Wait mail from 0
Retrieve data from mail
Task0 Task1
OSInit (1)
int main (void){ … OSInit(); … OSTaskCreate(…); … OSTaskCreate(…); … OSStart(); return 0; // Never return}
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.
OSInit (2)
OSTCBStkPtrOSTCBExtPtr = NULLOSTCBStkBottomOSTCBStkSize = stack sizeOSTCBId = OS_LOWEST_PRIOOSTCBNextOSTCBPrevOSTCBEventPtr = NULLOSTCBMsg = NULLOSTCBDly = 0OSTCBStat = OS_STAT_RDYOSTCBPrio = OS_LOWEST_PRIO-1OSTCBX = 6OSTCBY = 7OSTCBBitX = 0x40OSTCBBitY = 0x80OSTCBDelReq = FALSE
OSTCBStkPtrOSTCBExtPtr = NULLOSTCBStkBottomOSTCBStkSize = stack sizeOSTCBId = OS_LOWEST_PRIOOSTCBNextOSTCBPrevOSTCBEventPtr = NULLOSTCBMsg = NULLOSTCBDly = 0OSTCBStat = OS_STAT_RDYOSTCBPrio = OS_LOWEST_PRIOOSTCBX = 7OSTCBY = 7OSTCBBitX = 0x80OSTCBBitY = 0x80OSTCBDelReq = FALSE
0 0
000
00
00000
[OS_LOWEST_PRIO][OS_LOWEST_PRIO - 1]
[0][1][2][3][4][5][6]
OS_TCB OS_TCBOSTaskStat() OSTaskIdle()
OSTCBPrioTbl[]
OSTCBList
OSPrioCur = 0OSPrioHighRdy = 0OSTCBCur = NULLOSTCBHighRdy = NULLOSTime = 0LOSIntNesting = 0OSLockNesting = 0OSCtxSwCtr = 0OSTaskCtr = 2OSRunning = FALSEOSCPUUsage = 0OSIdleCtrMax = 0LOSIdleCtrRun = 0LOSIdleCtr = 0LOSStatRdy = FALSE Task Stack
Task Stack
0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 01 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
OSRdyGrp
OSRdyTbl[]
Ready List
OSInit (4)
OSTCBStkPtrOSTCBExtPtrOSTCBStkBottomOSTCBStkSizeOSTCBId OSTCBNextOSTCBPrevOSTCBEventPtrOSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq
OS_TCB
0OSTCBFreeList
OS_MAX_TASKS
0OSEventFreeList
OS_MAX_EVENTSOS_EVENT OS_EVENT OS_EVENT OS_EVENT
OSQPtrOSQStartOSQEndOSQInOSQOutOSQSizeOSQEntries
OSEventPtrOSEventTbl[]OSEventCntOSEventTypeOSEventGrp
OSTCBStkPtrOSTCBExtPtrOSTCBStkBottomOSTCBStkSizeOSTCBId OSTCBNextOSTCBPrevOSTCBEventPtrOSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq
OS_TCB
OSTCBStkPtrOSTCBExtPtrOSTCBStkBottomOSTCBStkSizeOSTCBId OSTCBNextOSTCBPrevOSTCBEventPtrOSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq
OS_TCB
OSEventPtrOSEventTbl[]OSEventCntOSEventTypeOSEventGrp
OSEventPtrOSEventTbl[]OSEventCntOSEventTypeOSEventGrp
OSEventPtrOSEventTbl[]OSEventCntOSEventTypeOSEventGrp
OSTCBStkPtrOSTCBExtPtrOSTCBStkBottomOSTCBStkSizeOSTCBId OSTCBNextOSTCBPrevOSTCBEventPtrOSTCBMsg OSTCBDly OSTCBStat OSTCBPrio OSTCBX OSTCBY OSTCBBitX OSTCBBitY OSTCBDelReq
OS_TCB
0OSQFreeList
OS_MAX_QSOS_Q OS_Q OS_Q
OSQPtrOSQStartOSQEndOSQInOSQOutOSQSizeOSQEntries
OSQPtrOSQStartOSQEndOSQInOSQOutOSQSizeOSQEntries
OSQPtrOSQStartOSQEndOSQInOSQOutOSQSizeOSQEntries
OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSNFree
0OSMemFreeList
OS_MAX_MEM_PARTOS_MEM
OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSNFree
OS_MEM OS_MEM OS_MEM
OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSNFree
OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSNFree
OS_Q
OSInit (3)
01234567
89101112131415
1617181920212223
2425262728293031
3233343536373839
4041424344454647
4849505152535455
5657585960616263
Task Priority #
Lowest Priority Task(Idle Task)
Highest Priority Task
X
Y
OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]01234567
OSRdyGrp
[7]
[6]
[5]
[4]
[3]
[2]
[1]
[0]
0 0 Y Y Y X X X
Bit position in OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]
Bit position in OSRdyGrp andIndex into OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]
Task's Priority
OSTaskCreate (1)
Create tasks with 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.
– Task never return;
int main (void){ … OSInit(); … OSTaskCreate(…); … OSTaskCreate(…); … OSStart(); return 0; // Never return}
OSTaskCreate (2)
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata,
OS_STK *ptos, INT8U prio)
Task Function
Private Data For Task
Stack For TaskPriority of
created task
Note that OSTaskCreate can be called by main when OSStart is not invoked, but it can also be called in tasks when more task should be created at the run time
Creating Task, OSTaskCreate()INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio){ void *psp; INT8U err;
if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ return (OS_PRIO_INVALID); } OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... */ /* ... the same thing until task is created. */ OS_EXIT_CRITICAL(); psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task's stack */ err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); if (err == OS_NO_ERR) { OS_ENTER_CRITICAL(); OSTaskCtr++; /* Increment the #tasks counter */ OSTaskCreateHook(OSTCBPrioTbl[prio]); /* Call user defined hook */ OS_EXIT_CRITICAL(); if (OSRunning) { /* Find highest priority task if multitasking has started */ OSSched(); } } else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority available to others */ OS_EXIT_CRITICAL(); } return (err); } else { OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); }}
OSStart Start multitasking of uC/OS-2. It never returns to main() The uC/OS-II picks up the highest-
priority task to run on context-switching.– Tightly coupled with RTC ISR.
int main (void){ … OSInit(); … OSTaskCreate(…); … OSTaskCreate(…); … OSStart(); return 0; // Never return}
Task Management
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
• Task is created by calling OSTaskCreate()
• Task is deleted by calling OSTaskDel() (After calling the function OS will never touch the task)
• Task is in waiting when request a system resource or singal (OSSemPend(),OSMboxPend(),OSQPend(), OSTimeDly() or OSTimeDlyHMSM() )
Task Management (contd.)
uC/OS-II can manage up to 64 tasks- two task are used for system use.- Reserve prorities 0, 1, 2, 3, OS_LOWEST_PRIO-3, 2, 1, 0
Use 56 application taskUse 56 application task
Task Control Block (TCB)
• When a task is created, it is assigned a Task Control Block, OS_TCB
• OS_TCB is a data structure that is used by uC/OS-II to maintain the state of a task when it is preempted.
• All OS_TCB reside in RAM
• An OS_TCB is initialized when a task is created.
typedef struct os_tcb { OS_STK *OSTCBStkPtr; // Can be accessed by ASM #if OS_TASK_CREATE_EXT_EN // Data for advanced task void *OSTCBExtPtr; // (record more info.) OS_STK *OSTCBStkBottom; INT32U OSTCBStkSize; INT16U OSTCBOpt; INT16U OSTCBId;#endif struct os_tcb *OSTCBNext; // 2 dir link struct os_tcb *OSTCBPrev; #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_SEM_EN OS_EVENT *OSTCBEventPtr; // Point to event list for#endif #if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN void *OSTCBMsg; // Point to message list #endif INT16U OSTCBDly; // Task call delay() INT8U OSTCBStat; INT8U OSTCBPrio; // Lower value higher prio. INT8U OSTCBX; // For fast task schedule INT8U OSTCBY; INT8U OSTCBBitX; INT8U OSTCBBitY; #if OS_TASK_DEL_EN BOOLEAN OSTCBDelReq;#endif} OS_TCB;
TCB Structure
OSTCBY = priority >> 3; OSTCBBitY = OSMapTbl[priority >> 3]; OSTCBX = priority & 0x07; OSTCBBitX = OSMapTbl[priority & 0x07];
TCB Structure (contd.)
0OSTCBFreeList OSTCBNext OSTCBNext OSTCBNext OSTCBNext
OSTCBTbl[0] OSTCBTbl[1] OSTCBTbl[2]
OSTCBTbl[OS_MAX_TASKS+OS_N_SYS_TASKS-1]
OS_MAX_TASKS is specified in OS_CFG.H
Task SchedulingTask-level scheduling is performed by OSSched().
ISR-level scheduling is handled by OSIntExit().void OSSched (void){ INT8U y;
OS_ENTER_CRITICAL(); if ((OSLockNesting | OSIntNesting) == 0) {/* Task scheduling must be enabled and not ISR level */ y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to highest priority task ready to run */ OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); if (OSPrioHighRdy != OSPrioCur) { /* No context switch if current task is highest ready */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; /* Increment context switch counter */ OS_TASK_SW(); /* Perform a context switch */ } } OS_EXIT_CRITICAL();}
Memory Management in uCOS malloc() and free() is dangerous in Embedded
real-time system – Unable to obtain a single contiguous memory area
due to fragmentation Execution time of malloc() and free() are also
nondeterministic– Algorithms used to locate a contiguous block of free
memory– Time for de-fragmentation
Fixed-sized memory blocks from a partition made of a contiguous memory area.– All memory blocks are the same size and the
partition contains an integral number of blocks– Allocation and deallocation of these memory blocks
is done in constant time and is deterministic
Memory Management in uCOS (contd.) Partition #1 Partition #2 Partition #3 Partition #4
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSMemNFree
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSMemNFree
OSMemAddr
OSMemFreeList
OSMemBlkSize
OSMemNBlks
OSMemNFree
0OSMemFreeList
OS_MAX_MEM_PART
Only empty data structs
after init
0
OSMemAddr = addr
OSMemFreeList= addr
OSMemBlkSize = blksize
OSMemNBlks = nblks
OSMemNFree = nblks
Contiguous memory
pmem
OSMemCreate() arguments
Get one node from OSMemFreeList, & fill
with real memory partition info.
Memory Management in uCOS (contd.)
typedef struct { void *OSMemAddr; void *OSMemFreeList; INT32U OSMemBlkSize; INT32U OSMemNBlks; INT32U OSMemBNFree;} OS_MEM;
OS_MEM *CommTxBuf;INT8U CommTxPart[100][32];void main(void){ INT8U err; . . . OSInit(); . . . CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err); . . . OSStart();}
Memory Management Functions OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err) – Format a memory partition
OSMemGet (OS_MEM *pmem, INT8U *err) – Get a memory block from one of the created memory partitions
OSMemPut (OS_MEM *pmem, void *pblk) – Returning a Memory Block to the appropriate partition
OSMemQuery() – Obtaining status of a Memory partition
Memory Management Example
ErrMsgPart
ErrMsgQ
ErrorHandler
AITask
0
OSMemGet() OSMemPut()
OSQPost() OSQPend()
OSTime
OSTimeGet()
(1)
AnalogInputs
(2)
(3)
(4)
(5) (6)
(7)
(8)
Time Management
5ms
10ms
Tick Interrupt
OSTic kISR ()
All HP T
Low- P rio rity Task
Task c alls OSTimeDly(1) here!
(1)(2)
(3)
(4)
(5)
(6)
Time Management Function OSTimeDly()–Delay for a user-specified number of clock ticks
OSTimeDlyHMSM()hours(H), minutes(M), seconds(S),
milliseconds(m), Maximum Delay 256hours (11days)OSTimeDlyHMSM( 0, 0, 1, 500);
OSTimeDlyResume()–Resuming a Delayed Task
OSTimeGet() & OSTimeSet()–32-bit counter
Time Management Function (contd.)
Task A
OSTimeDly(100)
Task A
Task BTask A sleep now
Task A call
Find the highest priority ready task B, and activate it
1
23
OSTickISR
This ISR is called every time tick to advance the clock
Hooks
A hook function will be called by uC/OS- when the corresponding event occurs.– Event handlers could be in user programs.– For example, OSTaskSwHook () is called every
time when context switch occurs. The hooks are specified in the compiling time
in uC/OS-II:– uC/OS-II is an embedded OS.
• OS_CFG.H (OS_CPU_HOOKS_EN = 0)
– Many OS’s can register and un-register hooks.
Hook Functions
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)
Empty function, can be overridden by user
Mail Box A mailbox is for data exchanging 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, then
an error is returned (not overwritten).– If tasks are waiting for a message from the mailbox,
then the task with the highest priority is removed from the wait-list and scheduled to run.
Mail Box OperationOS_EVENT* MBox0;
OS_EVENT* MBox1;
…
MBox0 = OSMboxCreate((void*)0);
MBox1 = OSMboxCreate((void*)0);
…
err = OSMboxPost(MBox1, (void*)&n);
…
msg = OSMboxPend(MBox0, 100, &err);
OSMboxCreate Step 1
– Get a OS_EVENTOS_EVENT node from OSEventFreeListOSEventFreeList
Step 2– Assign type OS_EVENT_TYPE_MBOXOS_EVENT_TYPE_MBOX to the OS_EVENT
node
Step 3– Attach the messageAttach the message (given from caller) to the OS_EVENT
node
Step 4– Return the point point of the OS_EVENT node to the caller
NoteNote– Mail box is an event in the view of uCOS– Mail box is not attach to specific task when created– The mail box has a table to record the tasks that are waiting
on the mail box.
OSMboxPost
Step 1– If there has some Task waitingTask waiting on the mail box,
wake up it and give the message to it directly
Step 2 (Step 1 is not run)– If the mail box is fullfull returnreturn error
OS_MBOX_FULLOS_MBOX_FULL
Step 3 (Step 2 is not run)– AttachAttach mailmail messagemessage to the mail box (mail box is
a special event)
OSMboxPend Step 1
– If mail box is emptyempty, pendingpending the task by calling OSEventTaskWait() OSEventTaskWait() (This function will register the task on the event table of the mail box, so that when mail box receive a message, it can check its table to wake up those tasks)
Step 2 (Step 1 is not run)– This step is run either because mail box get new
email or timeout event occur– The mail will be sent to task directly– Note:
• The message can be found by task’s message pointer. If there are already tasking waiting for mail in the mailbox, the arriving mail is given to task directly instead of storing to mailbox and then inform the task
• The message can be found in mail box’s pointer if the mail is sent when no tasking is pending for mail of the mail box.
Message Qeue A message queue consists of 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.
Intertask Comm. & Synch.
ISR TaskE C B
TaskE C BTask
E C B
Task
Task
ISR
Task
E C B
Task
Task
S ign al
S ign al
S ign al
S ign al
W ait/S ign al
W ait/S ign al
W ait
W ait
W ait
W ait
T im eou t
T im eou t
T im eou t
T im eou t
Event Control Blocks
typedef struct {
void *OSEventPtr;INT8U OSEventTbl[OS_EVENT_TBL_SIZE];INT16U OSEventCnt;INT8U OSEventType;INT8U OSEventGrp;
} OS_EVENT;
•OSEventPtr
ECB is assigned to a mailbox or a queue
•OSEventTbl[] & .OSEventGrp
Contains a list of tasks waiting on the event
•OSEventCnt
Hold the semaphore count
•OSEventType
The type associated with the ECB
OS_EVENT_SEM, OS_EVENT_TYPE_MBOX, OS_EVENT_TYPE_Q
Event Control Blocks
7 6 5 4 3 2 1 0
15 14 13 12 11 10 9 8
23 22 21 20 19 18 17 16
31 30 29 28 27 26 25 24
39 38 37 36 35 34 33 32
47 46 45 44 43 42 41 40
55 54 53 52 51 50 49 48
63 62 61 60 59 58 57 56
y
x
Highest Priority Task Waiting
Priority of task waitingfor the event to occur
Lowest Priority Task
7 6 5 4 3 2 1 0
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
0 0 Y Y Y X X X
Bit position in .OSEventTbl[]Bit posion in .OSEventGrpand Index into .OSEventTbl[]
Task’s Priority
.OSEventGrp.OSEventTbl[OS_LOWEST_PRIO/8+1]
Making a task wait for an event
pevent->OSEvebtGrp |= OSMapTbl[prio >> 3]; pevent->OSEventTbl[prio>>3] |= OSMapTbl[prio & 0x07];
Content of OSMapTbl[]
Removing a task from a wait list
if ((pevent->OSEventTbl[prio>>3] &= ~OSMapTbl[prio & 0x07]) == 0) { pevent->OSEventGrp &= ~OSMapTbl[prio >> 3]; }
Finding the highest priority task waiting for the event
y = OSUnMapTbl[pevent->OSEventGrp]; x = OSUnMapTbl[pevent->OSEvenTbl[y]]; prio = (y<<3) + x;
Index Bit Mask(Binary)0 0000 00011 0000 00102 0000 01003 0000 10004 0001 00005 0010 00006 0100 00007 1000 0000
OSEventWaitListInit()
: a function called when a semaphore, message mailbox, message queue is created
initializing an ECB
OSEventTaskRdy()
: Removes the highest priority task(HPT) from the wait list of the ECB and make this task ready to run
called by OSSemPost(), OSMboxPosr(), OSQPost(), OSQPostFront()
OSEventTaskWait()
: called by OSSemPend(), OSMboxPend(), OSQPend() when a task must wait on an ECB
Removes the current task from the ready list and places it in the wait list of the ECB
Semaphores16-bit unsigned integer used to hod the semaphore count (0 to 65535)
a list of tasks waiting for the semaphore count to be greater than 0
uC/OS-II provides five services to semaphores
- OSSemCreate()
- OSSemPend()
- OSSemPost()
- OSSemAccept()
- OSSemQuery()Task
Task
ISR
OR
OSSemP ost()OSSemAccept()
OSSemP ost()OSSemP end()OSSemAccept()OSSemQuery()
OSSemC reate()
N
N
OSSemCreate()
: Creates and initializes a semaphore
OS_EVENT *DispSem;
void main(void) {
. . . OSInit(); . . . DispSem = OSSemCreate(1); . . . OSStart();
}
OSSemPend()
: When a task wants exclusive access to a resource, needs to synchronize its activities with an ISR or a task, or is waiting until an event occurs
void DispTask(void *pdata)
{
INT8U err; pdata = pdata; for (;;) { . . . OSSemPend(DispSem, 0, &err);
. . . }
}
OSSemPost()
: A semaphore is signaled by calling OSSemPost().
void TaskX(void *pdata){
INT8U err; pdata = pdata;
for (;;) { . . . err = OSSemPost(DispSem); if (err == OS_NO_ERR) {
/* Semaphore signaled */
} else {
/* Semaphore has overflowed */
….
OSSemQuery()
: Obtain information about a semaphore
void Task (void *pdata)
{
OS_SEM_DAT sem_data: INT8U err, highest, x, y; pdata = pdata;
for (;;) {
. . . err = OSSemQuery(DispSem,&sem_data);
if (err==OS_NO_ERR) {
y=OSUnMapTbl[sem_data.OSEventGrp]; x=OSunMapTbl[sem_data.OSEventTbl[y]];
highest = (y<<3)+x;
. . .
Message MailboxesA message mailbox is a uC/OS-II object that allows a task or an ISR to send a pointer sized variable to another task
uC/OS-II provides five services to mailboxes
- OSMboxCreate()
- OSMboxPend()
- OSMboxPost()
- OSMboxAccept()
- OSMboxQuery() Task
Task
ISR
OSMboxP ost()OSMboxAccept()
OSMboxP ost()OSMboxP end()OSMboxAccept()OSMboxQuery()
OSMboxC reate()
M ailbox
Message
OSMboxCreate()
: Creates and initializes a mailbox
OS_EVENT *CommMbox;
void main(void) {
. . . OSInit(); . . . CommMbox = OSMboxCreate((void *)0); . . . OSStart();
}
OSMboxPend()
: When a task task expects to receive a message.
void CommTask(void *pdata)
{
INT8U err; void *msg;
pdata = pdata; for (;;) { . . .
msg=OSMboxPend(CommMbox, 10, &err);
if (err==OS_NO_ERR) {
/* Code for received message */
} else {
/* Code for message not received within time out */
. . .
OSMboxPost()
: Send a message to a task through a mailbox
OS_EVENT *CommMBox
INT8U CommRxBuf[100];
void CommTaskRx(void *pdata)
{
INT8U err; . . .
pdata = pdata; for (;;) {
. . . err = OSMboxPost(CommMbox, (void *)
&CommRxbuf[0]);
. . .
OSMboxQuery()
: Obtain information about a message mailbox
void Task (void *pdata)
{
OS_MBOXDATA mbox_data: INT8U err;
pdata=pdata; for (;;) {
. . . err = OSMboxQuery(CommMbox, &mbox_data);
if (err==OS_NO_ERR) { /* Mailbox contains a message if mbox_data.OSMsg is not NULL */ }
. . .
Message QueuesA message queue is a uC/OS-II object that allows a task or an ISR to send pointer sized variables to another task.
uC/OS-II provides seven services to Queues
- OSQCreate()
- OSQPend()
- OSQPost()
- OSQPostFront()
- OSQAccept()
- OSQFlush()
- OSQQuery()
Task
Task
ISR
OSQP ost()OSQP ostF ront()OSQF lush()OSQAccept()
OSQP ost()OSQP ostF ront()OSQF lush() OSQP end()
OSQAccept()OSQQuery()
OSQC reate()
Queue
Message
N
OSQCreate()
: Creates a message queue
OS_EVENT *CommQ;
void *CommMsg[10];
void main(void) {
. . . OSInit(); . . . CommQ=OSQCreate(&CommMsg[0],10); . . . OSStart();
}
OSQPend()
: When a task task expects to receive a message from a queue
void CommTask(void *pdata)
{
INT8U err; void *msg;
pdata = pdata; for (;;) { . . .
msg=OSQPend(CommQ, 100, &err); if (err==OS_NO_ERR) {
/* Message received wihin 100 ticks! */ } else {
/* Message not received, must have timed out */
. . .
OSQPost()
: Send a message to a task through a queue
OS_EVENT *CommQ;
INT8U CommRxBuf[100];
void CommTaskRx(void *pdata)
{
INT8U err; . . .
pdata = pdata; for (;;) {
. . . err = OSQPost(CommQ, (void *)
&CommRxBuf[0]);
. . .
OSQPostFront()
: Send a message to a task through a queue
OS_EVENT *CommQ;
INT8U CommRxBuf[100];
void CommTaskRx(void *pdata)
{
INT8U err; . . .
pdata = pdata; for (;;) {
. . . err = OSQPostFront(CommQ, (void *)
&CommRxBuf[0]);
. . .
Semaphore
How to Transplant to ARM? MMU?
Not implemented
Startup.sBasic init before main is run
OS_CPU_a.sSystem code for task swapping & IRQ (FIQ)
OS_CPU.c, OS_CPU.hHooks and the C extention of IRQ (FIQ) handler
OS_CFG.hWhich modules are compiled into code?
How Many Codes on uCOS Box
Startup.s
uCOS core
OS_CPU_a.s
Reset
TaskA(){…}TaskB(){…}TaskC(){…}TaskD(){…}
InterruptHow many codes on a uCOS box?
All of them are
compiled into a large binary file
Interrupts under uC/OS-IIuC/OS-II requires that an Interrupt Service Routine(ISR) be written in assembly language.
Pseudocode for an ISR
YourISR:
Save all CPU registers;
Call OSIntEnter() or, increment OSIntNesting directly;
Execute user code to service ISR;
Call OSIntExit();
Restore all CPU registers;
Execute a return from interrupt instruction;