1 / 20

Chapter 9 80x86, Large Model Port

Chapter 9 80x86, Large Model Port. Porting to real mode and for the large model Real mode: 1Mb memory space (pointers in this model require 32 bits) In real mode, all registers are 16 bits wide, and they all need to be saved during a context switch. Figure 9.1 80x86 real-mode register map.

eyad
Download Presentation

Chapter 9 80x86, Large Model Port

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 980x86, Large Model Port • Porting to real mode and for the large model • Real mode: 1Mb memory space (pointers in this model require 32 bits) • In real mode, all registers are 16 bits wide, and they all need to be saved during a context switch

  2. Figure 9.1 80x86 real-mode register map

  3. How to use 16-bit registers to access up to 1Mb memory

  4. uC/OS-II Hardware/Software Architecture u u Setting the value of 1 #define constants (OS_CPU.H) Declaring 10 data types (OS_CPU.H) Declaring 3 #define macros (OS_CPU.H) Writing 6 simple functions in C (OS_CPU_C.C) Writing 4 assembly language functions (OS_CPU_A.ASM) u

  5. OS_CPU.H #ifdef OS_CPU_GLOBALS #define OS_CPU_EXT #else #define OS_CPU_EXT extern #endif /* *************************************************************************** * DATA TYPES * (Compiler Specific) *************************************************************************** */ typedef unsigned char BOOLEAN; typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ (1) 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 data types for backward compatibility ... */ #define UBYTE INT8U /* ... to uC/OS V1.xx. Not actually needed for ... */ #define WORD INT16S /* ... uC/OS-II. */ #define UWORD INT16U #define LONG INT32S #define ULONG INT32U

  6. #define OS_CRITICAL_METHOD 2 #if OS_CRITICAL_METHOD == 1 #define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */ (2) #define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */ #endif #if OS_CRITICAL_METHOD == 2 #define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ #define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ #endif /* ***************************************************** * Intel 80x86 (Real-Mode, Large Model) Miscellaneous ***************************************************** */ #define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ (3) #define uCOS 0x80 /* Interrupt vector # used for context switch */ (4) #define OS_TASK_SW()asm INT uCOS //vector to the assembly language function OSCtxSw() (5) /* *********************************************************** * GLOBAL VARIABLES ********************************************************** */ OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */ (6) // the defualt tick rate is 18.2Hz. if we set the clock tick to 200Hz, this allow you to chain into DOS once every 11 ticks.

  7. Context Switch • In uC/OS-II, the stack frame for a ready task always looks as if an interrupt has just occurred and all processor registers were saved onto to it • OS_TASk_SW() is always called from task-level code • OSIntExit() is used to perform a context switch when an ISR makes a higher priority task ready for execution • OS_CPU_A.ASM • OSStartHighRdy() • OSCtxSw() • OSIntCtxSw() • OSTickISR()

  8. OSStartHighRdy(): called by OSStart() Void OSStartHighRdy(void) { call user definable OSTaskSwHook() Get the stack pointer of the task to resume: stack pointer = OSTCBHighRdy->OSTCBStkPtr; OSRunning = True; Restore all processor registers from the new task’s stack; Execute a return from interrupt instruction: } _OSStartHighRdy PROC FAR MOV AX, SEG _OSTCBHighRdy ; Reload DS MOV DS, AX ; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr (1) MOV SS, ES:[BX+2] ; MOV SP, ES:[BX+0] ; ; POP DS ; Load task's context (2) POP ES ; (3) POPA ; (4) ; IRET ; Run task (5) _OSStartHighRdy ENDP

  9. Figure 9.3 80x86 stack frame when task is created

  10. OSCtxSw(): a task call an OS kernel call =>OSSched() => select a highest priority => INT 80H => OSCtxSw() void OSCtxSw(void) { 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; Restore all processor registers from the new task’s stack; Execute a return from interrupt instruction; }

  11. Figure 9.4 80x86 stack frames during a task-level context switch

  12. Listing 9.4 OSCtxSw() _OSCtxSw PROC FAR ; (1) ; PUSHA ; Save current task's context (2) PUSH ES ; (3) PUSH DS ; (4) ; MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered MOV DS, AX ; ; LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP (5) MOV ES:[BX+2], SS ; MOV ES:[BX+0], SP ; ; CALL FAR PTR _OSTaskSwHook (6) ; MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy (7) 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 (8) MOV BYTE PTR DS:_OSPrioCur, AL ; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr (9) MOV SS, ES:[BX+2] ; MOV SP, ES:[BX] ; ; POP DS ; Load new task's context (10) POP ES ; (11) POPA ; (12) ; IRET ; Return to new task (13) ; _OSCtxSw ENDP

  13. OSIntCtxSw(): called by OSIntExit() Figure 9.5 80x86 stack frames during an interrupt-level context switch

  14. Pseudocode for OSIntCtxSw() void OSIntCtxSw(void) { Adjust the stack pointer to remove calls to: OSIntExit(), OSIntCtxSw() and possibly the push of the processor status word; 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; Restore all processor registers from the new task’s stack; Execute a return from interrupt instruction; }

  15. Listing 9.5 OSIntCtxSw() _OSIntCtxSw PROC FAR ; ; Ignore calls to OSIntExit and OSIntCtxSw ; ADD SP,8 ; (Uncomment if OS_CRITICAL_METHOD is 1, see OS_CPU.H) (1) 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 (2) MOV ES:[BX+2], SS ; MOV ES:[BX+0], SP ; ; CALL FAR PTR _OSTaskSwHook (3) ; MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy (4) 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 (5) MOV BYTE PTR DS:_OSPrioCur, AL ; LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr (6) MOV SS, ES:[BX+2] ; MOV SP, ES:[BX] ; ; POP DS ; Load new task's context (7) POP ES ; (8) POPA ; (9) ; IRET ; Return to new task (10) ; _OSIntCtxSw ENDP

  16. OSTickISR() Figure 9.6 The PC interrupt vector table (IVT)

  17. Pseudocode for tick ISR void OSTickISR (void) { Save processor registers; (1) OSIntNesting++; (2) OSTickDOSCtr—-; (3) if (OSTickDOSCtr == 0) { Chain into DOS by executing an ‘INT 81H’ instruction; (4) } else { Send EOI command to PIC (Priority Interrupt Controller); (5) } OSTimeTick(); (6) OSIntExit(); (7) Restore processor registers; (8) Execute a return from interrupt instruction (IRET); (9) }

  18. Listing 9.7 OSTickISR() _OSTickISR PROC FAR ; PUSHA ; Save interrupted task's context PUSH ES PUSH DS ; MOV AX, SEG _OSTickDOSCtr ; Reload DS MOV DS, AX ; INC BYTE PTR _OSIntNesting ; Notify uC/OS-II of ISR ; DEC BYTE PTR DS:_OSTickDOSCtr CMP BYTE PTR DS:_OSTickDOSCtr, 0 JNE SHORT _OSTickISR1 ; Every 11 ticks (~199.99 Hz), chain into DOS ; MOV BYTE PTR DS:_OSTickDOSCtr, 11 INT 081H ; Chain into DOS's tick ISR JMP SHORT _OSTickISR2 _OSTickISR1: MOV AL, 20H ; Move EOI code into AL. MOV DX, 20H ; Address of 8259 PIC in DX. OUT DX, AL ; Send EOI to PIC if not processing DOS timer. ; _OSTickISR2: CALL FAR PTR _OSTimeTick ; Process system tick ; CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR ; POP DS ; Restore interrupted task's context POP ES POPA ; IRET ; Return to interrupted task ; _OSTickISR ENDP

  19. OSTaskStkInit() void MyTask (void *pdata) { /* Do something with argument ‘pdata’ */ for (;;) { /* Task code */ } } • Stack frame initialization with pdata passed on the stack

  20. Stack frame initialization with pdata passed in register

More Related