Upload
suhas-shirol
View
212
Download
0
Embed Size (px)
DESCRIPTION
Porting to 8086 information
Citation preview
uC/OS-II HW/SW ArchitectureApplication Software
μC/OS-II(Processor-Independent Code)OS_CORE.C uCOS_II.COS_MBOX.C uCOS_II.HOS_MEM.C OS_Q.COS_SEM.C OS_TASK.COS_TIME.C
μC/OS-II Configuration(Application-Specific Code)
OS_CFG.HINCLUDES.H
μC/OS-II Port(Processor-Specific Code)
OS_CPU.HOS_CPU_A.ASM
OS_CPU_C.C
CPU Timer
SoftwareHardware
Addressing with a Segment and an offset
Memory addressing relies on using a segment and offset register
A 20-bit address that can access up to 1Mb
A 16-bit segment register can point to any of 65,536 different paragraphs of 16 bytes
Development ToolsDirectories & Files Development Tools : Borland C/C++ V3.1
compiler along with the Borland Turbo Assembler
The compiler provides in-line assembly language instructions to be inserted in C code
The source code for the port is found in OS_CPU.H, OS_CPU_C.C and OS_CPU_A.ASM
Intel/AMD 80186 \SOFTWARE\uCOS-II\Ix86s
Motorola 68HC11
\SOFTWARE\uCOS-II\68HC11
\OS_CPU.H
\OS_CPU_A.ASM
\OS_CPU_C.C
\OS_CPU.H\OS_CPU_A.ASM\OS_CPU_C.C
OS_CPU.H -- Data Types (compiler specific)
typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /* Unsigned 8 bit quantity */typedef signed char INT8S; /* Signed 8 bit quantity */typedef unsigned int INT16U; /* Unsigned 16 bit quantity */typedef signed int INT16S; /* Signed 16 bit quantity */typedef unsigned long INT32U; /* Unsigned 32 bit quantity */typedef signed long INT32S; /* Signed 32 bit quantity */typedef float FP32; /* Single precision floating point */typedef double FP64; /* Double precision floating point */
typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */
#define BYTE INT8S #define UBYTE INT8U #define UWORD INT16U#define LONG INT32S#define ULONG INT32U
OS_CPU.H -- Critical Section
#define OS_CRITICAL_METHOD 2
#if OS_CRITICAL_METHOD == 1#define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */#define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */#endif Both the CLI and STI instructions execute in less that two clock cycles eac
h on this processor (a total of 4 cycles)
#if OS_CRITICAL_METHOD == 2#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */#endif OS_ENTER_CRITICAL consumes 12 clock cycles. OS_EXIT_CRITICAL uses u
p another 8 clock cycles (a total of 20 cycles)
OS_CPU.H -- Miscellaneous#define OS_STK_GROWTH 1/* Stack grows from HIGH to LOW memory on 80x86 */
#define uCOS 0x80 /* Interrupt vector # used for context switch */
#define OS_TASK_SW() asm INT uCOS
OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */
OS_CPU_A.ASM
A μC/OS-II port requires 4 assembly language functions: OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTickISR()
(1) OSStartHighRdy() 功能 : 系統一開始的時候 , 執行此 function, 使最高 priority task
執行 順序 :
系統一開始時呼叫 OSInit() ( 在 OS_CORE.C 中 ) 至少建立一個 task (by calling OSTaskCreate() and OSTask
CreateExt()) Called by OSStart(), OSStart() 中呼叫 OSStartHighRdy()
Pseudo codeCall user definable OSTaskSwHook();Get the stack pointer of the task to resume:
Stack Pointer = OSTCBHighRdy OSTCBStkPtr;OSRunning = TRUE;Execute a return from interrupt instruction
OSStartHighRdy() (cont.)_OSStartHighRdy PROC FAR
MOV AX, SEG _OSTCBHighRdy ; Reload DS MOV DS, AX ; ; CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook; INC BYTE PTR DS:_OSRunning ; Indicate that multitasking has started; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr MOV SS, ES:[BX+2] ; MOV SP, ES:[BX+0] ; ; POP DS ; Load task's context POP ES ; POPA ; ; IRET ; Run task
_OSStartHighRdy ENDP
OSStartHighRdy() (cont.) OSRunning
declaration( in uCOS_II.H) OS_EXT BOOLEAN OSRunning;
initialization(in OS_CORE.C) OSRunning = FALSE; OSTaskSwHook() //in OS_CPU_C.C 內容 :void OSTaskSwHook (void) {} 功能 : 提供使用者操作 OSTCBCur 和 higest priority
task 之 TCB( 由 OSTCBHighRdy 指到 ), 為使用者自訂 .
OSStartHighRdy() (cont.) OSTaskSwHook() can examine OSRun
ning: OSRunning is FALSE – called from OSStar
tHighRdy() OSRunning is TRUE – called from regular
context switch
(2) OSCtxSw() 用途 :Task-level context switch Use software interrupt(int 0x80) 喚起 : 1. 每次作 context 喚起 OSSched() 其中呼叫 OS_TASK_SW(),OS_TASK_SW()
是一個 software interrupt, 此 interrupt 執行 OSCtxSw(),OSCtxSw() 使最高priority 的 task run
2. No context switch if current task is highest ready Pseudo code
Save processor registers;Save the current task’s stack pointer into the current task’s OS_TCB:
OSTCBCur->OSTCBStkPtr = Stack Pointer;Call user definable OSTaskSwHook();OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy;Get the stack pointer of the task to resume:
Stack Pointer = OSTCBHighRdy->OSTCBStkPtr;POP DS,POP ES,POPAExecute a return from interrupt instruction;
OSCtxSw() (cont.)
OSSched () (in OS_CORE.C) 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();}
(3) OSIntCtxSw() 功能 :context switch from ISR to highe
st priority task 呼叫過程 : ISR 結束前會呼叫 OSIntExit(), OSIntExit
() 中呼叫 OSIntCtxSw().
OSIntCtxSw() (cont.)
TASK TASK
TASK
Task ResponseInterrupt disabled
Interrupt Response
Vectoring
Saving Context,saving all
Processor regisisters.
Notify kernels by call OSIntEnter()
User ISR code Notify kernel
Restore Context
Return from interrupt
Interrupt RecoveryInterrupt Request
New HPT
Interrupt RecoveryTask Response
No New HPT Or OSLockNesting=0
Return from interrupt
Notify kernel
Restore ContextCall OSIntExit()
OSIntCtxSw() (cont.) OSIntExit in OS_CPU_C.C
void OSIntExit (void){ OS_ENTER_CRITICAL(); if ((--OSIntNesting | OSLockNesting) == 0) { /* Reschedule only if all ISRs completed & not l
ocked */ OSIntExitY = OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]); if (OSPrioHighRdy != OSPrioCur) { /* No context switch if current task is highest read
y */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; /* Keep track of the number of context switches */ OSIntCtxSw(); /* Perform interrupt level context switch */ } } OS_EXIT_CRITICAL();}
OSIntCtxSw() (cont.) called by OSIntExit(), 和 OSCtxSw() 相
似 , 不同之處為 : - 因為所有 processor reg 在 ISR 執行之
前已都被正確的放入 interrupt task stack,所以不必儲存 regisisters( 即 :no PUSHA,PUSH ES,PUSH DS)
執行此 function 時候 interrupt 為 disable
( 因為 OSIntExit() 設的 )
OSIntCtxSw() (cont.)_OSIntCtxSw PROC FAR; ; Ignore calls to OSIntExit and OSIntCtxSw; ADD SP,8 ; (Uncomment if OS_CRITICAL_METHOD is 1, see OS_CPU.H) ADD SP,10 ; (Uncomment if OS_CRITICAL_METHOD is 2, see OS_CPU.H); MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered MOV DS, AX ; ; LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP MOV ES:[BX+2], SS ; MOV ES:[BX+0], SP ; ; CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook; MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy MOV DX, WORD PTR DS:_OSTCBHighRdy ; MOV WORD PTR DS:_OSTCBCur+2, AX ; MOV WORD PTR DS:_OSTCBCur, DX ; ; MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy MOV BYTE PTR DS:_OSPrioCur, AL ; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr MOV SS, ES:[BX+2] ; MOV SP, ES:[BX] ; ; POP DS ; Load new task's context POP ES ; POPA ; ; IRET ; Return to new task;_OSIntCtxSw ENDP
(4) OSTickISR() On PC, the ticker occurs ev
ery54.93ms(18.20648Hz), what needs to be done while changing tick rate to 200Hz?
Relocate the original ticker ISR from 0x08 to 0x81
Install OSCtxSw() ISR at 0x80
Create first task which should help to install OSTickISR() at 0x08 and change the tick rate if needed
Call OSStart() to start multitasking
OSTickISR() (cont.) Pseudo code
Save processor registers;OSIntNesting++;OSTickDOSCtr--;if (OSTickDOSCtr == 0) {
Chain into DOS by executing an ‘INT 81H’ instruction;} else {
Send EOI (End of Interrupt) command to PIC (Priority Interrupt Controller);
}OSTimeTick();OSIntExit();Restore processor registers;Execute a return from interrupt instruction (IRET);
OSTickISR() (cont.) Incorrect place to start the tick interrupt
void main(void){
…OSInit();…Enable TICKER interrupts; /*DO NOT DO THIS HERE */…OSStart();
}
OS_CPU_C.C
A μC/OS-II port requires 6 C functions: OSTaskStkInit() //necessary OSTaskCreateHook() OSTaskDelHook() OSTaskSwHook() OSTaskStatHook() OSTimeTickHook()
(1) OSTaskStkInit() Called by OSTaskCreate() and OSTask
CreateExt() OSTaskStkInit() needs the following a
rguments : the start address of the task (task) a pointer (pdata) the task’s TOS (ptos)
OSTaskStkInit() (cont.)void *OSTaskStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U opt){ INT16U *stk; opt = opt; /* 'opt' is not used, prevent warning */ stk = (INT16U *)ptos; /* Load stack pointer */ *stk-- = (INT16U)FP_SEG(pdata); /* Simulate call to function with argument */ *stk-- = (INT16U)FP_OFF(pdata); *stk-- = (INT16U)FP_SEG(task); *stk-- = (INT16U)FP_OFF(task); *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ *stk-- = (INT16U)FP_OFF(task); *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ *stk = _DS; /* DS = Current value of DS */ return ((void *)stk);}