Kernel Structure - structural aspects of μC/OS-II

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 30

Kernel Structure –

structural aspects of μC/OS-II

906714 劉曙銘
906792 劉健民
904392 彭啟廷
Table of Contents

 Critical Section
 Task
 Scheduling
 ISR (Interrupt Service Routine)
 Clock Ticker
 Multitasking
 Appendix
Critical Section
 Shared resource is protected from being accessed
simultaneously by either tasks or ISRs.
 μC/OS-II needs to disable interrupts in order to
access critical section of code, and re-enable
interrupts when done.
 Kernel Service
 OS_ENTER_CRITICAL ()
 OS_EXIT_CRITICAL ()
 Reference
 OS_CPU.H
Task
 Internal
 A task is an infinite loop.
 void myTask (void *pdata)
{
for (;;) {
// USER CODE, Call one of kernel services
}
}
 A task that deletes itself when done.
 void myTask (void *pdata)
{
// USER CODE
OSTaskDel (OS_PRIO_SELF);
}
 64 tasks at most including two system tasks.
 Kernel Service
 OSTaskCreate()
 OSTaskCreateExt()
Task (Cont 1)
 Priority
 The lower the priority number, the higher the priority of task.
 Reserved Priority
 0,1,2,3, OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2
 OS_LOWEST_PRIO-1 and OS_LOWEST_PRIO
 56 application tasks in fact.
 Kernel Service
 OSTaskChangePrio()
 OSTaskDel()
 Refenence
 OS_CFG.H
Task (Cont 2)

 Task States

WAITING

OSMBoxPost() OSMBoxPend()
OSQPost() OSQPend()
OSQPostFront()
OSTaskDel() OSSemPost() OSSemPend()
OSTaskResume() OSTaskSuspend()
OSTimeDlyResume() OSTimeDly()
OSTimeTick() OSTimeDlyHMSM()

OSTaskCreate()
OSTaskCreateExt() OSStart()
OSIntExit() Interrupt
OS_TASK_SW()
DORMANT READY RUNNING ISR
OSIntExit()
OSTaskDel()
Task is Preempted

OSTaskDel()
Task (Cont 3)

 Task Control Block (TCB)


 When a task is created, it is assigned a TCB.
 Used by μC/OS-II for context switching.
 All TCBs are placed in OSTCBTbl[].
 List of free TCBs
OSTCBTbl[OS_MAX_TASKS+OS_N_SYS_TASKS-1]

OSTCBTbl[0] OSTCBTbl[1] OSTCBTbl[2]

OSTCBFreeList OSTCBNext OSTCBNext OSTCBNext OSTCBNext 0


Task (Cont 4)
 Task Control Block (TCB)
 Components
 OSTCBStkPtr : pointer to current top of stack
 OSTCBExtPtr : pointer to user definable data for TCB
extension
 OSTCBStkBottom : pointer to bottom of stack
 OSTCBStkSize : size of task stack
 OSTCBOpt : task options as passed by OSTaskCreateExt()
 OSTCBId : task ID (0..65535)
 OSTCBNext & OSTCBPrev : used to doubly link TCBs
 OSTCBEventPtr : pointer to event control block
 OSTCBMsg : message received from OSMboxPost() or
OSQPost()
Task (Cont 5)
 Task Control Block (TCB)
 Components
 OSTCBDly : n ticks to delay task or, timeout waiting for event
 OSTCBStat : task status
 OSTCBPrio : task priority
 OSTCBX : bit position in group corresponding to task priority
(0..7)
 OSTCBY : index into ready table corresponding to task priority
 OSTCBBitX : bit mask to access bit position in ready table
 OSTCBBitY : bit mask to access bit position in ready group
 OSTCBDelReq : indicates whether a task needs to delete
itself
Task (Cont 6)

 Task Control Block (TCB)


 Calculating TCB members
 OSTCBY = priority >> 3;
OSTCBBitY = OSMapTbl[priority >> 3];
OSTCBX = priority & 0x07;
OSTCBBitX = OSMapTbl[priority & 0x07];
 Reference
 OS_CFG.H
 uCOS-II.H
Task (Cont 7)
 Ready List
 A task owns a priority level between 0 and
OS_LOWEST_PRIO.
 Each task that is ready to run is placed in Ready List.
 Components
 OSRdyGrp : Ready Group
 Task priorities are grouped (8 tasks per group).
 Each bit indicates a task of any group is ready to run.
 OSRdyTbl[] : Ready Table
 Size of OSRdyTbl[] is OS_LOWEST_PRIO.
 Task’s priority determines the bit location in table.
Task (Cont 8)
OSRdyGrp
OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]
 Ready List 7 6 5 4 3 2 1 0
Highest Priority Task

X
 Figure [0] 7 6 5 4 3 2 1 0
[1] 15 14 13 12 11 10 9 8
[2] 23 22 21 20 19 18 17 16
[3] 31 30 29 28 27 26 25 24
Y
[4] 39 38 37 36 35 34 33 32
[5] 47 46 45 44 43 42 41 40
[6] 55 54 53 52 51 50 49 48
[7] 63 62 61 60 59 58 57 56

Task Priority #
Task's Priority
Lowest Priority Task
(Idle Task)
0 0 Y Y Y X X X

Bit position in OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]

Bit position in OSRdyGrp and


Index into OSRdyTbl[OS_LOWEST_PRIO / 8 + 1]
Task (Cont 9)
 Ready List
 Source Code
 OSMapTbl[] : bit mask table
 OSMapTbl[0] == 00000001b
OSMapTbl[1] == 00000010b
OSMapTbl[2] == 00000100b
OSMapTbl[3] == 00001000b
OSMapTbl[4] == 00010000b
OSMapTbl[5] == 00100000b
OSMapTbl[6] == 01000000b
OSMapTbl[7] == 10000000b
 Make a task ready-to-run
 OSRdyGrp |= OSMapTbl[prio >> 3];
OSRdyTbl[prio>>3] |= OSMapTbl[prio & 0x07];
 Remove a task from the ready list
 if((OSRdyTbl[prio>>3]&=~OSMapTbl[prio&0x07]) == 0)
OSRdyGrp &= ~OSMapTbl[prio >> 3];
Task (Cont 10)
 Ready List
 Source Code
 Find highest priority task ready-to-run
 y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;
 OSUnMapTbl[] : priority resolution table
 { 0, 0, 1, 0, 2,
0, 1, 0, 3, 0,
1, 0, 2, 0, 1,
0, 4, 0, 1, 0,
2, 0, 1, 0, 3,
0, 1, 0, 2, 0,
. . . }
Scheduling
 ISR level scheduling
 Explain later…
 Task level scheduling
 OSSched()
 Execute the highest priority task ready to run.
 It will exit if
 Called from an ISR.
 OSIntNesting > 0
 Scheduling has been disabled.
 OSSchedLock()
 To disable task scheduling
 OSSchedUnlock()
Scheduling (Cont 1)
 Source Code
 Task Scheduler
 void OSSched (void)
{
INT8U y;

OS_ENTER_CRITICAL();
if ((OSLockNesting | OSIntNesting) == 0) {
y = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur) {
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OS_TASK_SW();
}
}
OS_EXIT_CRITICAL();
}
Scheduling (Cont 2)
 Source Code
 Locking the Scheduler
 void OSSchedLock (void)
{
if (OSRunning == TRUE) {
OS_ENTER_CRITICAL();
OSLockNesting++;
OS_EXIT_CRITICAL();
}
}
 Unlocking the Scheduler
 void OSSchedUnlock (void)
{
if (OSRunning == TRUE) {
OS_ENTER_CRITICAL();
if (OSLockNesting > 0) {
OSLockNesting--;
if ((OSLockNesting | OSIntNesting) == 0) {
OS_EXIT_CRITICAL();
OSSched();
} else {
OS_EXIT_CRITICAL();
}
} else {
OS_EXIT_CRITICAL();
}
}
}
Scheduling (Cont 3)
 Caution
 OSSchedLock() and OSSchedUnlock() must be used in
pairs.
 The task that calls OSSchedUnlock() keeps control of
CPU forever!
 After calling OSSchedLock(), your task must not make
any kernel service that will suspend execution of the
current task.
 No other task will be allowed to run!
 Reference
 OS_CORE.C
ISR
 Internal
 A piece of code in assembly language.
 Pseudo Code
 myISR:
Save all CPU registers;
Call OSIntEnter();
Execute user assembly to service ISR;
Call OSIntExit();
Restore all CPU registers;
Execute a return from interrupt instruction;
 OSIntEnter()
 Notify μC/OS-II about beginning of ISR.
 OSIntExit()
 Notify μC/OS-II about leaving of ISR.
 Reference
 OS_CPU_A.ASM
ISR (Cont 1)
 Source Code
 void OSIntEnter (void)
{
OS_ENTER_CRITICAL();
OSIntNesting++;
OS_EXIT_CRITICAL();
}
 void OSIntExit (void)
{
OS_ENTER_CRITICAL();
if ((--OSIntNesting | OSLockNesting) == 0) {
OSIntExitY = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((OSIntExitY << 3) +
OSUnMapTbl[OSRdyTbl[OSIntExitY]]);
if (OSPrioHighRdy != OSPrioCur) {
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OSIntCtxSw();
}
}
OS_EXIT_CRITICAL();
}
ISR (Cont 2)
Time
Task Response
Interrupt Request (1)
µC/OS-IIor your application
has interrupts disabled.
(2) Interrupt Recovery
 Call Flow TASK TASK
No New HPT or,
Vectoring OSLockNesting > 0 Return from interrupt
(3) (9)
Saving Context Restore conte xt
(4) (8)
Notify kernel:
OSIntEnter() or, Notify kernel: OSIntExit()
OSIntNesting++ User ISR code (7)
(5)
(6)
Interrupt Response Notify kernel: OSIntExit()
(10)
Restore context
(11)
Return from interrupt
ISR signals a task
New HPT (12)
TASK
Interrupt Recovery
Task Response
ISR (Cont 3)

 Run-time Stack
LOW MEMORY

(4) Return address to caller of OSIntCtxSw() SP Points Here!

(3) Processor Status Word


(5)
(2) Return address to caller of OSIntExit()

SP must be adjusted
to point here.

Saved Processor Registers This new SP is saved into


the preempted task's OS_TCB.
(1) (6)

Interrupt Return Address Stack Growth


Processor Status Word

HIGH MEMORY
Clock Ticker
 Internal
 Periodic time source to keep track of time delay and timeouts.
 OSTCBDly in TCB
 The higher the tick rate, the higher the overhead.
 Must be enabled after multitasking has started.
 Enable ticker interrupts at first task!
 Source
 Hardware timer
 AC power line (50/60 Hz)
 Pseudo Code
 void OSTickISR(void)
{
Save processor registers;
Call OSIntEnter();
Call OSTimeTick();
Call OSIntExit();
Restore processor registers;
Execute a return from interrupt instruction;
}
Clock Ticker (Cont 1)
 Source Code
 void OSTimeTick (void)
{
OS_TCB *ptcb;

OSTimeTickHook();
ptcb = OSTCBList;
while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0) {
if (--ptcb->OSTCBDly == 0) {
if (!(ptcb->OSTCBStat & OS_STAT_SUSPEND)) {
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
} else {
ptcb->OSTCBDly = 1;
}
}
}
ptcb = ptcb->OSTCBNext;
OS_EXIT_CRITICAL();
}
OS_ENTER_CRITICAL();
OSTime++;
OS_EXIT_CRITICAL();
}
Multitasking
 Initializing and starting μC/OS-II
 void main (void)
{
OSInit(); // Initialize uC/OS-II
.
.
Create at least 1 task;
.
.
OSStart(); // Start multitasking!
}
 OSInit()
 Initialize all variables and data structures.
 Create the idle task (OSTaskIdle()) which is always ready-to-run.
 Create the statistic task (OSTaskStat()) optionally.
 OSStart()
 Find the highest priority task that have created.
 Never return to the caller!
Multitasking (Cont 1)
 Source Code
 Start Multitasking
 void OSStart (void)
{
INT8U y;
INT8U x;

if (OSRunning == FALSE) {
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy = (INT8U)((y << 3) + x);
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSTCBCur = OSTCBHighRdy;
OSStartHighRdy();
}
}
 Obtaining μC/OS-II’s version
 INT16U OSVersion (void)
{
return (OS_VERSION);
}
Appendix 1 1 0
OSRdyGrp
0 0 0 0 0 0
Ready List
OSTCBPrioTbl[]
OSRdyTbl[] 0 [0]
0 [1]
0 [2]
0 0 0 0 0 0 0 0 0 [3]
0 [4]
0 0 0 0 0 0 0 0 0 [5]
0 [6]
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 0
0
[OS_LOWEST_PRIO - 1]
[OS_LOWEST_PRIO]

OSTaskStat() OSTaskIdle()
OS_TCB OS_TCB
OSTCBStk Ptr OSTCBStk Ptr
OSTCBExtPtr = NULL OSTCBExtPtr = NULL
OSTCBStk Botto m OSTCBStk Botto m
OSTCBStk Size = stack size OSTCBStk Size = stack size
OSTCBId = OS_LOWEST_PRIO OSTCBId = OS_LOWEST_PRIO
OSTCBList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBEventPtr = NULL OSTCBEventPtr = NULL
OSPrioCur = 0 OSTCBMsg = NULL OSTCBMsg = NULL
OSPrioHighRdy = 0 0 OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
0
OSTCBCur = NULL OSTCBPrio = OS_LOWEST_PRIO-1
OSTCBX = 6
OSTCBPrio = OS_LOWEST_PRIO
OSTCBX = 7
OSTCBHighRdy = NULL OSTCBY = 7 OSTCBY = 7
OSTime = 0L OSTCBBitX = 0x40
OSTCBBitY = 0x80
OSTCBBitX = 0x80
OSTCBBitY = 0x80
OSIntNesting = 0 OSTCBDelReq = FALSE OSTCBDelReq = FALSE
OSLockNesting = 0
OSCtxSwCtr = 0
OSTaskCtr = 2
OSRunning = FALSE
OSCPUUsage = 0
OSIdleCtrMax = 0L
OSIdleCtrRun = 0L
OSIdleCtr = 0L Task Stack
OSStatRdy = FALSE Task Stack
Appendix 2
OS_MAX_TASKS
OS_TCB OS_TCB OS_TCB OS_TCB
OSTCBStkPtr OSTCBStkPtr OSTCBStkPtr OSTCBStkPtr
OSTCBExtPtr OSTCBExtPtr OSTCBExtPtr OSTCBExtPtr
OSTCBStkBottom OSTCBStkBottom OSTCBStkBottom OSTCBStkBottom
OSTCBStkSize OSTCBStkSize OSTCBStkSize OSTCBStkSize
OSTCBId OSTCBId OSTCBId OSTCBId
OSTCBFreeList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev 0
OSTCBEventPtr OSTCBEventPtr OSTCBEventPtr OSTCBEventPtr
OSTCBMsg OSTCBMsg OSTCBMsg OSTCBMsg
OSTCBDly OSTCBDly OSTCBDly OSTCBDly
OSTCBStat OSTCBStat OSTCBStat OSTCBStat
OSTCBPrio OSTCBPrio OSTCBPrio OSTCBPrio
OSTCBX OSTCBX OSTCBX OSTCBX
OSTCBY OSTCBY OSTCBY OSTCBY
OSTCBBitX OSTCBBitX OSTCBBitX OSTCBBitX
OSTCBBitY OSTCBBitY OSTCBBitY OSTCBBitY
OSTCBDelReq OSTCBDelReq OSTCBDelReq OSTCBDelReq

OS_MAX_EVENTS
OS_EVENT OS_EVENT OS_EVENT OS_EVENT

OSEventFreeList OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
OSEventPtr
OSEventTbl[]
0
OSEventCnt OSEventCnt OSEventCnt OSEventCnt
OSEventType OSEventType OSEventType OSEventType
OSEventGrp OSEventGrp OSEventGrp OSEventGrp

OS_MAX_QS
OS_Q OS_Q OS_Q OS_Q

OSQFreeList OSQPtr
OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
OSQPtr
OSQStart
0
OSQEnd OSQEnd OSQEnd OSQEnd
OSQIn OSQIn OSQIn OSQIn
OSQOut OSQOut OSQOut OSQOut
OSQSize OSQSize OSQSize OSQSize
OSQEntries OSQEntries OSQEntries OSQEntries

OS_MAX_MEM_PART
OS_MEM OS_MEM OS_MEM OS_MEM

OSMemAddr OSMemAddr OSMemAddr OSMemAddr


OSMemFreeList OSMemFreeList
OSMemBlkSize
OSMemFreeList
OSMemBlkSize
OSMemFreeList
OSMemBlkSize
OSMemFreeList
OSMemBlkSize 0
OSMemNBlks OSMemNBlks OSMemNBlks OSMemNBlks
OSNFree OSNFree OSNFree OSNFree
Appendix 3
OSTime
OSIntNesting
=
=
0L
0
1 0 0
OSRdyGrp
0 0 0 0 1
Ready List

OSRdyTbl[]
OSLockNesting = 0 0 1 0 0 0 0 0 0
OSCtxSwCtr = 0
OSTaskCtr = 3 0 0 0 0 0 0 0 0
OSRunning = TRUE 0 0 0 0 0 0 0 0
OSCPUUsage = 0 0 0 0 0 0 0 0 0
OSIdleCtrMax = 0L
OSIdleCtrRun = 0L 0 0 0 0 0 0 0 0
OSIdleCtr = 0L 0 0 0 0 0 0 0 0 OSTCBPrioTbl[]
OSStatRdy = FALSE 0 [0]
0 0 0 0 0 0 0 0 0 [1]
0 [2]
OSPrioCur =6 1 1 0 0 0 0 0 0 0 [3]
OSPrioHighRdy = 6 0 [4]
0 [5]
[6]

0
0
0
[OS_LOWEST_PRIO - 1]
[OS_LOWEST_PRIO]

YouAppTask() OSTaskStat() OSTaskIdle()


OS_TCB OS_TCB OS_TCB

OSTCBCur OSTCBStkPtr
OSTCBExtPtr = NULL
OSTCBStkPtr
OSTCBExtPtr = NULL
OSTCBStkPtr
OSTCBExtPtr = NULL
OSTCBHighRdy OSTCBStkBottom
OSTCBStkSize = stack size
OSTCBStkBottom
OSTCBStkSize = stack size
OSTCBStkBottom
OSTCBStkSize = stack size
OSTCBId = 6 OSTCBId = OS_LOWEST_PRIO OSTCBId = OS_LOWEST_PRIO
OSTCBList OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBNext
OSTCBPrev
OSTCBEventPtr = NULL OSTCBEventPtr = NULL OSTCBEventPtr = NULL
OSTCBMsg = NULL OSTCBMsg = NULL OSTCBMsg = NULL
0 OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY
OSTCBDly = 0
OSTCBStat = OS_STAT_RDY 0
OSTCBPrio = 6 OSTCBPrio = OS_LOWEST_PRIO-1 OSTCBPrio = OS_LOWEST_PRIO
OSTCBX = 6 OSTCBX = 6 OSTCBX = 7
OSTCBY = 0 OSTCBY = 7 OSTCBY = 7
OSTCBBitX = 0x40 OSTCBBitX = 0x40 OSTCBBitX = 0x80
OSTCBBitY = 0x01 OSTCBBitY = 0x80 OSTCBBitY = 0x80
OSTCBDelReq = FALSE OSTCBDelReq = FALSE OSTCBDelReq = FALSE

Task Stack
Task Stack
Task Stack
Appendix 4

Highest Priority OS_LOWEST_PRIO - 1 OS_LOWEST_PRIO


main() TaskStart() OSTaskStat() OSTaskIdle()
{ { { {
OSInit(); (1)
Install context switch vector; (2)
Create TaskStart(); (3)
OSStart();
Scheduler
} Init uC/OS-II's ticker; (5)
(4) OSStatInit(): (6)
OSTimeDly(2); (7)
Scheduler while (OSStatRdy == FALSE) { (8)
OSTimeDly(2 seconds); (9)
2 ticks } Scheduler for (;;) {
After 2 ticks OSIdleCtr++; (10)
(11) }
OSIdleCtr = 0; (12)
OSTimeDly(1 second); (13)
Scheduler for (;;) {
2 seconds OSIdleCtr++; (14)
1 second After 1 second }

OSIdleCtrMax = OSIdleCtr; (15)


OSStatRdy = TRUE; (16)
for (;;) {
Task code;
} for (;;) {
} Compute Statistics; (17)
}
}

You might also like