WinCE OAL中的Startup.s介绍

应该说Startup.s是OAL最开始的入口,就像EBOOT中的Startup.s一样,它也是WinCE内核最开始运行的代码。一般在BSP中,EBOOT的Startup.s和OAL的Startup.s的功能应该是一样的,但是还是会有些区别,很多情况取决于BSP的开发者,两个Startup.s之间可以共享很多代码,也可以部分共享或者彼此独立。
  OAL中的Startup的起始位置定义如下:
  LEAF_ENTRY   Startup
  …
  主要就是原始化CPU,对于ARM来说,大致步骤如下:
  1. 配置 CPU为supervisor模式
  2. 禁用IRQ和FIQ中断
  3. 关上 MMU和指令数据Cache
  4. 刷新Cache和TLB,清空write buffer
  5. 确认启动原由,可能是EBOOT跳转过来启动,冷启动,热启动,Watchdog复位等
  6. 配置GPIO来点亮LED
  7. 配置Memory控制器及时序
  8. 配置中断控制器,清理所有中断
  9. 原始化RTC
  10. 配置CPU的电源管理
  11. 配置 CPU的时钟及有关的外设的时钟
  12. 将OEMAddressTable的起始地址写入r0寄存器
  13. 跳转到Kernelstart中
  程序最后会跳转到KernelStart中,在Private目录下的armstart.s中,这里仍然是汇编,大致步骤如下:
  1. 基于传入的OEMAddresstable原始化一级页表
  2. 使能MMU和Cache
  3. 为每一种ARM模式建立堆栈
  4. 调用ARMInit函数获得kernel.dll的入口,该函数在arminit.c中定义
  5. 返回kernel.dll的入口为NKStartup,在mdarm.c中定义,跳转到kernel.dll入口开始运行
  6. 在NKStartup中读取CPU的ID判断ARMv6架构,原始化内核的全局变量
  7. 调用OEMInitDebugSerial原始化调试串口
  8. 调用OEMInit原始化有关的外设接口
  9. 调用OEMCacheRangeFlush刷新Cache和TLB
  10. 调用KernelFindMemory来划分对象存储空间和程序内存空间
  11. 调用kernelstart函数,它与最开始的kernelstart不同,它在armtrap.s中定义
  到此应该说CPU有关的原始化基本完成了,下面就是要开始WinCE内核的原始化了,大致步骤如下:
  1. 跳转到armstrap.s中的kernelstart继续执行
2. 调用KernelInit函数,在nkinit.c中定义,主要完成API集的原始化,内核Heap的原始化,内存池的原始化,进程和线程的原始化,最后是映射文件的原始化
  3. 在执行完KernelInit之后,会跳转到FirstSchedule执行 第一次系统调度,到此内核已经运行起来了。
  这里把整个的原始化流程介绍了一下,实际上Startup.s只是WinCE启动最开始的部分,完成CPU级别的原始化,这段代码都是汇编,调试起来也基本也困难,基本是因为都是顺序执行的,只是原始化CPU,困难是因为没有好的调试手段,一般在这里都是通过点LED的方式来判断程序执行的位置。

你可能感兴趣的:(汇编,cache,api,存储,buffer,WinCE)