Boot Loader之ARM Uboot移植 阶段一 理论篇
1.boot loader需要完成的任务:
1》设计程序的入口地址
2》建立异常中断处理向量
3》初始化CPU各种模式的堆栈和寄存器
4》初始化系统中要使用的各种片内外设备
5》初始化目标板
6》引导操作系统
2.boot loader 的实现流
在stage1中boot loader主要完成5方面的工作,依次为
1》基本的硬件的初始化
屏蔽所有的中断,设置CPU的速度和时钟频率,初始化内存的控制器,初始化串口,关闭CPU内部指令/数据cache
2》为加载stage2 准备内存空间
为了获得更快的运行速度,通常将stage2加载到RAM空间中执行,因此必须为加载boot loader的stage2准备好一段可用的RAM空间范围。由于stage2通常是c语言执行代码,因此在考虑空间大小时,除了要考虑stage2映像的大小,还应该考虑堆栈的大小。
3》复制stage2到内存空间中
复制的时候要注意两点 :
stage2的可执行映像在固态存储设备的存放起始地址和终止地址。
内存空间的起始地址
4》设置堆栈指针sp
因为堆栈是向下生长的,通常把sp的值设置为那个1MB的RAM空间的最顶端。
5》跳转到stage2的入口点
上述一切都就绪后,就可以跳转到bootloader 的stage2去执行了。
stage2 是用c代码书写,但是在编译连接的时候不能使用glibc 库的任何支持函数。带来一问题就是从哪里跳转进main函数呢?直接将main()函数的起始地址作为整个stage2执行映像的入口点或许是最直接的方法,但是这样做有两个缺点: 无法通过main()函数传递函数参数 无法处理main()函数返回的情况 另一种方法Trampoline(弹簧床)的概念,即用汇编语言写一段Trampoline 小程序,并将Trampoline程序来作为stage2可执行的映像的执行入口点。然后可以在Trampoline汇编小 程序中用CPU跳转指令跳入main()函数中去执行;而当main()函数返回时,CPU执行路径显然再次回到Trampoline程序。简而言之,这种方法的思想就是:用这段Trampoline程序作为main()函数的外部包裹(external wrapper)