1.首先确定CPU,在这里为了简单,就选用嵌入式的CPU,比如ARM系列,之所以用RISC(简单指令集) 类型的CPU,其方便之处是没有实模式与保护模式之分,采用线性的统一寻址,也就是不需要进行段 页式内存管理,还有就是芯片内部集成了一些常用外设控制器,比如以太网卡,串口等等,不需要像 在PC机的主板上那么多外设芯片 2.确定要实现的模块和功能,为了简单,只实现多任务调度(但有限制,比如最多不超过10),实 现中断处理(不支持中断优先级),不进行动态SHELL交互,不实现动态模块加载,不实现fork之类 的动态进程派生和加载(也就是说要想在你的操作系统上加入用户程序,只能静态编译进内核中;不 支持文件系统,不支持网络,不支持PCI,USB,磁盘等外设(除了支持串口,呵呵,串口最简单嘛), 不支持虚拟内存管理(也就是说多任务中的每个进程都可以访问到任何地址,这样做的话,一个程序 死了,那么这个操作系统也就玩完了) 3.确定要使用的编译器,这里采用GCC,文件采用ELF格式,当然,最终的文件就是BIN格式,GCC和 LINUX有着紧密的联系,自己的操作系统,需要C库支持和系统调用支持,所以需要自己去裁剪C库, 自己去实现系统调用 4.实现步骤:首先是CPU选型,交叉编译环境的建立,然后就是写BOOTLOADER,写操作系统
如何实现BOOTLOADER
1.之所以要实现一个专用的BOOTLOADER,一是为了更好的移植和自身的升级,二是为了方便操作系统的调试,当然,你完全可以将这部分所要实现的与操作系统相关的功能集成到
操作系统中去 2.确定一个简单的BOOTLOADER所要完成的功能:我们这里只需要完成两个主要功能,一是将操作系统加载到内存中去运行,二是将自己和操作系统内核固化到ROM存储区(这里的
ROM可以是很多设备热缜度胧叫酒械?/SPAN>FLASH,PC机上的软盘,U盘,硬盘等)
3.BOOTLOADER的编写: 第一步:要进行相关硬件的初使化,比如在at91rm9200这块嵌入式板子上(以后都使用这一款芯片,主要是我对这款芯片比较熟悉,嘿嘿),大概要做接下来的几方面的工作,其
一:将CPU模式切换进系统模式,关闭系统中断,关闭看门狗,根据具体情况进行内存区域映射,初始化内存控制区,包括所使用的内存条的相关参数,刷新频率等,其二:设定系
统运行频率,包括使用外部晶振,设置 CPU频率,设置总线频率,设置外部设备所采用的频率等。其三:设置系统中断相关,包括定时器中断,是否使用FIQ中断,外部中断等,还有就是中断优先级设置,这里只实现两
个优先级,只有时钟中断高一级,其它都一样,而中断向量初始化时都将这些中断向量指向0x18处,并关闭这里的所有中断,如果板子还接有诸如FLASH设备的话,还需要设置诸如
FLASH相关操制寄存器,其四:需要关闭CACHE,到此为止,芯片相关内容就完成初始化了
第二步:中断向量表,ARM的中断与PC机芯片的中断向量表有一点差异,嵌入式设备为了简单,当发生中断时,由CPU直接跳入由0x0开始的一部分区域(ARM芯片自身决定了它中断
时就会跳入0x0开始的一片区域内,具体跳到哪个地址是由中断的模式决定的,一般用到的就是复位中断,FIQ,IRQ中断,SWI中断,指令异常中断,数据异常中断,预取指令异常
中断),而当CPU进入相应的由0x0开始的向量表中时,这就需要用户自己编程接管中断处理程序了,这就是需要用户自己编写中断向量表,中断向量表里存放的就是一些跳转指令
,比如当CPU发生一个IRQ中断时,就会自动跳入到0x18处,这里就是用户自己编写的一个跳转指令,假如用户在此编写了一条跳转到0x20010000处的指令,那么这个地址就是一个
总的IRQ中断处理入口,一个CPU可能有多个IRQ中断,在这个总的入口处如何区分不同的中断呢?就由用户编程来决定了,具体实现请参见以后相关部分,中断向量表的一般用一个
vector.S文件,当然,如何命名那是你自己的喜爱,但有一点需要声明,那就是在链接时一定要将它定位在0x0处
第三步:设置堆栈,一般使用三个栈,一个是IRQ栈,一个是系统模式下的栈(系统模式下和用户模式共享寄存器和内存空间,这主要是为了简单),设置栈的目的主要是为了进行
函数调用和局部变量的存放,不可能全用汇编,也不可能不用局部变量
第四步:将自己以后的代码段和数据段全部拷贝至内存,并将BSS段清零
第五步:进行串口的初始化(主要是为了与用户交互,进行与PC机的文件传输),FLASH的初始化这里在FLASH中存放BOOT和内核),FLASH驱动的编写(这里的驱动有别于平常所说
的驱动,由于FLASH不像SDRAM,只要设定了相关控制器之后就可以直接读写指定地址的数据,对FLASH的写操作是一块一块数据进行,而不是一个字节一个字节地写,具体请查阅相
关资料) 第六步:等待一定的秒数,来接收用户进行输入,如果在指定的秒数内用户未输入任何字符,那么 BOOT就开始在FLASH中的指定位置(可以由自己指定,这么做主要是为了简单)读取内核的所有数据到内存中(具体是内存中的什么位置由自己指定,也可以采用LINUX之类的做法
,就是在内存的起始位置加上一个0x8000处),将跳转到内核的第一条代码处);如果用户在指定的秒数内键入了字符(这主要是为了方便开发,如果开发定型之后完全可以不要
这段代码),那么就在串口与用户进行交互,接受用户在串口输入的命令,比如用户要求下载文件在FLASH中指定的位置等,具体内容可参考U-BOOT之类的开源项目到这里为止,
BOOT部分已完成,这个BOOT非常简单,仅仅只是将PC机上传下来的文件固化到FLASH中,然后再将FLASH中的操作系统内核部分加载进内存中,并将CPU的控制权交给操作系统,下一
页开始讲解如何写一个最简单的操作系统,呵,到现在才开始切入正题呢!!!! |