在startup.s文件中包含一个startup的入口函数,该函数为eboot的最开始的入口。在系统上电或者冷启动的时候,这是第一个被执行的函数。该函数都是由汇编语言编写的,完成基于硬件平台的最初的初始化,也就是cpu的相关初始化,如果有必要,也可以在这里对外围的设备进行初始化。该函数执行到最后,会跳转到c语言的入口,一般是main函数,或者叫做ebootmain函数。
这里要多说的一件事情就是在bsp当中存在两个startup.s文件,一个是eboot的startup.s用于eboot本身,另一个是oal的startup.s用于wince内核。在很多情况下,两个startup.s所完成的任务非常的相近,所以一般都会合并成一个startup.s来完成相应的功能。比如你在eboot的startup.s中完成了相关的初始化操作以后,在oal的startup.s中只需要include位于eboot下的startup.s就可以了。当然,这两个startup.s也许不能完全一样,所以不管是真的存在两个startup.s文件还是共用一个startup.s文件,你可能都需要在startup.s中通过条件编译或者判断某个变量的方法来区分。
下面具体说一下在startup.s中,到底应该做些什么事情:
1. 在系统上电或者复位时,先将cpu设置到正确的模式下面。一般cpu本身会有几种模式,比如对于arm来说,这个时候一般会设置为管理模式。
2. 关闭所有的cpu中断。
3. 关闭内存管理单元mmu和tlb。
4. 关闭写缓冲和cache。
5. 初始化内存控制器。
6. 设置cpu的pll,设置时钟。
7. 创建堆栈。
8. 设置并打开mmu和cache。
9. 如果需要,自己拷贝eboot从flash到ram中。
10. 跳转到c代码中,一般是main函数或者ebootmain函数。
下面以arm为例,来看一个startup.s的模板:
startuptext
leaf_entrystartup
;设置arm的cpsr寄存器来设置arm为管理模式并屏蔽所有中断
mov r0,#(svc32mode:or:noints)
msr cpsr_c,r0
;设置cp15协处理器,关闭mmu和cache
ldr r0,=cp15controlinit
wrmmu_state r0
ldr r0,=cp15auxcontrolinit
wrmmu_aux_state r0
;刷新tlb表和cache
mov r0,#0x0
wrmmu_flushtb r0
wrcache_flushidc r0
;释放写缓冲
mov r0,#0
mcr p15,0,r0,c7,c10,4
cpwait
;创建一个临时的堆栈,使用sram中的头32kb
ldr sp,=(cpu_sram0+sz_32k-4)
bl disableints ;屏蔽外部中断
bl inituart ;初始化串口
bl initclocks ;初始化系统时钟
bl initstaticmem ;初始化flash片选控制器
bl initsdram ;初始化sdram控制器
bl sizesdram ;返回sdram的大小
ifeboot
;重定位flash中的代码到ram中
bl everythingrelocate
;重定位成功后,跳转到realstartup新地址运行,否则接着运行
cmp r0,#-1
movne pc,r0
endif
realstartup
ifeboot
bl ebootmain ;跳转到ebootmain函数,就是eboot的c语言代码中
else
adr r0,oemaddresstable ;r0=physicaladdressofoemmemorymap
bl kernelstart ;跳转到kernelstart函数,并传入物理虚拟地址映射表
endif
;这里是一个死循环,代码应该永远也执行不到这里
spin b spin
entry_end
整个startup.s的流程就是这样,一般开发这段代码需要对处理器及汇编语言比较了解,其实也不是很复杂,就是做最基本的初始化,该函数一般也就几百行。调试可能稍微费劲一些,在最开始的时候一般通过点灯(led)的方式来调试,就是说写个小的汇编函数,通过把gpio拉高拉低来点亮和熄灭led灯。然后在startup.s中的不同位置调用该函数从而判断函数是否执行到相应的地方。
![]()
如果喜欢wince eboot的入口startup.s - startup.s请收藏或告诉您的好朋友.
阅读(184) | 评论(0) | 转发(0) |