1.操作系统的的移植就是指一个操作系统能够在某个微处理平台上运行,uc/os-II是一个基于优先级的抢占式实时多任务内核。uc/os-II的大部分代码是用ANSIC语言编写的,也包含一小部分汇编语言代码,使之可以提供给不同构架的微处理器使用。
移植uC/0S-Ⅱ需要一个C编译器,并且是针对用户用的CPU的。因为u C/0S-II是一个可剥夺型内核,用户只有通过C编译器来产生可重入代码;C编译器还要支持汇编语言程序。绝大部分的C编译器都是为嵌入式系统设计的,它包括汇编器、连接器和定位器。连接器用来将不同的模块(编译过和汇编过的文件)连接成目标文件。定位器则允许用户将代码和数据放置在目标处理器的指定内存映射空间中。所用的C编译器还必须提供一个机制来从C中打开和关闭中断。一些编译器允许用户在C源代码中插入汇编语言。这就使得插入合适的处理器指令来允许和禁止中断变得非常容易了。还有一些编译器实际上包括了语言扩展功能,可以直接从C中允许和禁止中断,故本次实验我选择使用Borland C++4.5集成开发环境进行程序的编译和调试。
而80x86是一个的 16位微处理器,专门用于多任务的操作系统,并为需要高性能的应用所设计。16位的寄存器和数据通道支持16位的寻址方式和数据类型,处理器使用一种特殊的机制,寻址最高可达1GB 的地址空间,计算方法是:段地址寄存器的内容的左移4位(乘以16),再加上偏移量寄存器(其他6个寄存器中的一个(AX,BP,SP,SI,DI或IP)的内容,产生了可寻址 1MB的20位物理地址。
2.基本原理
处理器的C编译器能产生可重入代码;
在程序中可以打开/关闭中断;
处理器支持中断,并且能产生定时中断;
处理器能支持一定数量的数据存储硬件堆栈;
处理器有将堆栈指针及其CPU寄存器内容读出,并存储到堆栈或内存的命令
3.移植步骤与关键代码
3.1准备工作:
1.使用VM安装xp系列的虚拟机:
这里我装的是x86的,上网找一下产品密钥激活就可以了
2.安装BC++4.5和Tasm5.0
1、安装BORLAND C++4.5 到 C:\BC45
2、安装BORLAND TASM5.0 到 C:\TASM
因为BorlandC++ 3.0由于没有工程的概念所以需要自己写makefile比较不好用,用BorlandC++4.5会比较好些,但是4.5里没有TASM.exe。所以要安装TASM 5.0;之后在环境变量-用户变量-path中的“C:\BC45\BIN”后添加“C:\TASM\BIN”,到此编译器的问题解决了,不然的话在编译过程中编译器会出现“could not locate TASM.exe”这个报错信息。
3.2 UcosII的移植:
在c 盘下建立 test 文件 夹,在其下建立子文件夹 project(存放工程),obj(存放编译连接过程产生的临 时文件),final(存放最终生成的 exe 文件),source(存放移植过程中用到的文件)
以下是source中所用到的文件:
uC/OS-II 的内核文件(共 11 个,与处理器无关):
OS_CORE.C
OS_FLAG..C
OS_MBOX.C
OS_MEM.C
OS_MUTEX.C
OS_Q.C
OS_SEM.C
OS_TASK.C
OS_TIME.C
uCOS_II.C
uCOS_II.H
uC/OS-II 的配置文件(2 个,与应用有关):
OS_CFG.H
INCLUDES.H
uC/OS-II 移植文件(3 个,与处理器相关):
OS_CPU.H
OS_CPU_A.ASM OS_CPU_C.C
下面三个文件使我移植的应用文件:
PC.C 和 PC.H 与 PC 机相关,
TEST.C 是我自己编写的文件,也就是系统要执行的任务。
3.3使用BC++4.5创建项目:
1.启动BORLAND C++4.5,创建工程。
菜单Project --->New project,弹出“New Target”对话框。
2.在“Project path and name”中指定工程路径:c:\test\project\test.ide
3.在“Target Type”下选择“Application[.exe]”
4.在“PlatForm”下选择“DOS[Standard]”
5.在“Target Modet”下选择“Large”
6.单击“OK”按钮
接着,在 options—project 下配置好编译环境。默认的两个 c:\bc45\include
和 c:\bc45\lib 不用变,这是软件运行需要的包含文件文件和库文件,这些都
在软件自身的安装目录下。
Include 后添加;c:\test\source 这是为了让编译器找到 INCLUDES.H 这
个文件;
Source 后添加实验文件所在的文件夹;
Intermediate 是临时文件输出,选择 obj 文件夹;
Final 是 exe 输出,选择 final 文件夹。
工程中添加如下5个文件(需要删除工程自带的那个*.cpp文件)
1. c:\test\source\TEST.C
2. c:\test\source\OS_CPU_C.C
3. c:\test\source\OS_CPU_A.ASM
4. c:\test\source\uCOS_II.C
5. c:\test\source\PC.C
之后,project—>compile。链接通过后,debug
—>run 运行程序。
关键代码:
(1)OSStartHighRdy(); //使得最高优先级的任务运行的函数
OSStart()函数调用OSStartHighRdy()来使得就绪太任务中最高优先级的任务开始运行
void OSStartHighRdy()
{
调用用户定义的OSTaskSwHook();
OSRunning = TRUE;
//得到将要恢复运行的任务的堆栈指针。
stack pointer = OSTcbHighRdy->OSTCBStkPtr;
//从新的堆栈中恢复处理器的所有的寄存器,就是把刚刚切换的堆栈保存到别的地方当中
//执行中断返回,然后跳转PC指针到别的地方中去。
}
2)OSCtxSw(); 任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TPAP陷阱指令执行的。中断服务子程序,陷阱或者异常处理的向量的地址必须指向OSCtxSw():
//任务的切换的函数:
void OSCtxSw()
{
保存处理器寄存器;
在当前的任务的任务控制块中保存当前任务的堆栈指针;
OSTCBCur->OSTCBStkPtr = stack pointer;
OSTaskSwHook();
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
//得到将要重新开始运行的任务的堆栈指针:
stack pointer = OSTCBHighRdy->OSTCBstkPtr;
//从新的任务堆栈中恢复所有的寄存器的值;
//执行中断返回的指令。
}
(3)OSIntCtxSw();
void OSTickISR(void)
{
//保存处理器的寄存器
//调用OSIntEnter或者直接给OSIntNesting加1
if(OSIntNesting ==1)
{
OSTCBCur->OSTCBStkPtr = Stack Pointer;
}
//给产生中断的设备清中断
//重新允许中断
OSTimeTick(); //硬件的产生中断的原理
OSIntExit(); //中断退出
//恢复处理器寄存器
//执行中断返回指令
}
(4)OSTickISR();
void OSintCtxSw(void)
{
//调整堆栈指针
OSintExit();
OSINTCtxSw();
}
- 界面截图