📄 os_cpu_c.c
字号:
// os_cpu_c.c
//
// Port of uC/OS-II (C) to the Intel 80x86 (32-bit flat protected mode)
// By Jean L. Gareau (jean.gareau@exposecorp.com)
//
// Copyright (C) 1997-1999, Jean L. Gareau. All rights reserved.
// This file or its content can not be used for commercial applications
// without the prior written permission of the author.
//
// Description:
// This file contains the C routines of the port (see Ix86pm_a.asm for the
// assembly language routines). A full description of the port can be found
// in Port86pm.doc.
//
// Development Environment:
// This file has been developed within a Visual C++ 5.0 project. Otherwise,
// it can be compiled using the following command:
//
// CL /ML /W3 /GX /O2 /FD /c [/D_DEBUG] Ix86p.c
//
// The macro _DEBUG can be enabled to dump the stack of unexpected interrupts,
// as in: #define _DEBUG. Note that Ix86p_a.asm must also be assembled with
// _DEBUG defined as well.
//
// Versions:
// 1.00 14-Dec-97 Initial release.
// 2.00 28-Feb-99 Upgrade from uC/OS to uC/OS-II
#include "os_cpu.h"
#include "os_cfg.h"
#include "ucos_ii.h"
#ifdef _DEBUG
#include <stdlib.h> // for itoa()
#endif
// Intel 8259 ports
#define I8259_A0 0x020 // 8259 #1, port #1
#define I8259_A1 0x021 // 8259 #1, port #2
#define I8259_B0 0x0a0 // 8259 #2, port #1
#define I8259_B1 0x0a1 // 8259 #2, port #2
// Prototypes
static void InitA20();
static void InitPIC();
static void SetIntVector(int IntNo, PTR Handler);
static void SetIDTGate(int IntNo, INT16U Type, INT16U Selector, INT32U Offset);
static void TaskBucket();
#ifdef _DEBUG
extern void OnScreen(int x, int y, char * pszText, int nColor);
#endif
///////////////////////////////////////////////////////////////////////////////
// uCOS-II Functions
// OSCpuInit()
// Performs CPU-dependent intiailization.
void OSCpuInit()
{
int IntNo;
InitA20(); // Enable address line 20
InitPIC(); // Relocate IRQs to 0x20-0x2F
// Install a default handler for all supported interrupts:
// a) 0x00-0x1F: Intel-reserved
// b) 0x20-0x2F: IRQ (relocated)
// c) 0x30-0x3F: Available for uCOS and application.
for (IntNo = 0; IntNo < 0x40; IntNo++)
SetIntVector(IntNo, DefIntHandler);
#ifdef _DEBUG
// Install a dump stack handler for int 13 (General Protection Fault).
SetIntVector(13, DumpStackHandler);
#endif
SetIntVector(0x20, OSTickISR); // Install the tick handler
SetIntVector(uCOS, OSCtxSw); // Install uCOS-II's context switch handler
}
// OSTaskStkInit()
// This is a uCOS-II function. Only the stack setup part needs some modifications.
void * OSTaskStkInit(void (*task)(void *pd), void *pdata, void *ptos, INT16U opt)
{
OS_STK* stk;
stk = (OS_STK *) ptos; // Load stack pointer
*--stk = (INT32U) pdata; // Simulate a function call (to pass the parameter)
*--stk = (INT32U) TaskBucket; // Return address in case the task exits.
*--stk = 0x00000202; // Eflags (interrupt flag enabled)
*--stk = CS_SELECTOR; // CS
*--stk = (INT32U) task; // Entry point
*--stk = 0; // EAX
*--stk = 0; // ECX
*--stk = 0; // EDX
*--stk = 0; // EBX
*--stk = 0; // ESP (unused)
*--stk = 0; // EBP
*--stk = 0; // ESI
*--stk = 0; // EDI
return stk;
}
// OSTaskCreateHook
// This hook is invoked during task creation.
void OSTaskCreateHook(OS_TCB * pTcb)
{
}
// OSTaskDelHook
// This hook is invoked during task deletion.
void OSTaskDelHook(OS_TCB * pTcb)
{
}
// OSTaskSwHook
// This hook is invoked during a task switch.
// OSTCBCur points to the current task (being switched out).
// OSTCBHighRdy points on the new task (being switched in).
void OSTaskSwHook()
{
}
// OSTaskStatHook
// This hook is invoked by the statistical task every second.
void OSTaskStatHook()
{
}
// OSTimeTickHook
// This hook is invoked during a time tick.
void OSTimeTickHook()
{
}
///////////////////////////////////////////////////////////////////////////////
// Helper Functions
// InitA20.
// Enable the address line 20.
//
// The address line 20 must be under the control of the CPU (not always 0 as it is
// in real-mode). This is done by sending commands to the keyboard controller (i8042).
// Before sending commands, the i8042 must be polled to ensure that it can receive data.
void InitA20()
{
INT8U status;
// Wait until i8042 can receive the command.
do
{
status = inportb(0x64);
} while (status & 2);
// Send the 'write' command to the i8042.
outportb(0x64, 0xd1);
// Wait until i8042 can receive the command.
do
{
status = inportb(0x64);
} while (status & 2);
// Send the new set-up.
outportb(0x60, 0xdf);
// Wait until i8042 has received the command.
do
{
status = inportb(0x64);
} while (status & 2);
}
// InitPIC()
// Relocate the IRQ lanes from 0x00 to 0x20 to prevent conflicts
// between IRQ and CPU's exceptions.
//
// This is achieved by sending a series of command to the Intel 8259
// Programmable Interrupt Controllers (PIC).
void InitPIC()
{
// Reprogram the master 8259.
outportb(I8259_A0, 0x11);
outportb(I8259_A1, 0x20);
outportb(I8259_A1, 0x04);
outportb(I8259_A1, 0x01);
outportb(I8259_A1, 0x00);
// Reprogram the slave 8259.
outportb(I8259_B0, 0x11);
outportb(I8259_B1, 0x28);
outportb(I8259_B1, 0x02);
outportb(I8259_B1, 0x01);
outportb(I8259_B1, 0x00);
}
// SetIntVector()
// Installs an interrupt handler.
void SetIntVector(int IntNo, PTR Offset)
{
SetIDTGate(IntNo, IDTDATE_INT, CS_SELECTOR, (INT32U) Offset);
}
// SetIDTGate()
// Install a generic gate in the IDT.
//
// Parameters:
// IntNo : The IDT entry no (0x00-0x3F)
// Type : IDTGATE_INT, IDTGATE_TRAP or IDTGATE_TASK
// Selector: Code selector, usually CS_SELECTOR
// Offset : Handler
void SetIDTGate(int IntNo, INT16U Type, INT16U Selector, INT32U Offset)
{
extern IDT_GATE Idt[];
IDT_GATE * pGate = &Idt[IntNo];
pGate->Offset = (INT16U) (Offset & 0xffff);
pGate->Offset2 = (INT16U) (Offset >> 16);
pGate->Selector = Selector;
pGate->Type = Type;
}
// TaskBucket()
// This is the function that is executed if a task inadvertedly
// returns from its main function. This is specified in OSTaskStkInit(),
// when a task's stack is being intialized.
void TaskBucket()
{
while (1)
;
}
// ShowRegister()
// A simple debug function that shows a INT32U, starting from the
// top left corner of the screen and going down each time it is invoked.
// It thus works 25 times for a 25-line monitor. It is useful to dump
// a few DWORDs from the stack at a given point (particularly during faults).
// Not sophisticated, but useful.
#ifdef _DEBUG
void ShowRegister(INT32U v)
{
static int i = 0;
char buffer[32];
itoa(v, buffer, 16);
OnScreen(0, i++, buffer, 14);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -