Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393709
  • 博文数量: 128
  • 博客积分: 2247
  • 博客等级: 大尉
  • 技术积分: 767
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-17 09:30
文章分类

全部博文(128)

文章存档

2011年(4)

2010年(124)

我的朋友

分类: 嵌入式

2010-07-25 10:53:07

本文以ARC600平台的某一实现为例,对U-BOOT的内存布局和启动方式进行简要的分析。


【内存布局】


在ARC600平台,U-BOOT的内存布局图1所示:

该 布局由board/arc600/u-boot.lds文件定义,在链接的时候生成相应的二进制映像。首先,定义起始地址为0x40800000,接下来 是中断向量表,大小为256字节,按每个中断向量占用4个字节的跳转地址算,最多可以有64个中断向量;第二部分是一些基础性的代码段,它为下一步加载 boot或者kernel做准备,其大小为0x1700字节;第三部分是代码段的后半部分,代码段的大部分代码都在这里;第四部分只读数据区;第五部分为 可读写数据区;第六部分为U-BOOT命令代码区;最后一部分为未初始化数据段。


有一点比较疑惑的就是U-BOOT命令代码区存放的分明是代码,但它却在数据段。内核中会把一些初始化代码放在数据区,因为这些代码只运行一次,放在数据区可以在内核启动后回收该区域内存。但显然U-BOOT命令不可能只运行一次,为何要把它放在数据段?不解!


【启动过程】


众 所周知,U-BOOT是存放在FLASH上的。系统启动时,CPU会映射FLASH到它的内存空间(映射一部分、还是全部FLASH空间?),然后执行 FLASH上的代码。首先,进入cpu/arc600/start.S中的入口_start,进行内存初始化,接着把U-BOOT的前0x1800字节从 FLASH复制到内存的0x40800000处,也就是链接时的地址;然后对bss段进行清零,设置堆栈指针,为运行C函数做准备;下一步,运行C函数检 测在规定时间内是否有按键发生,如有则加载boot的后半部分(0x40801800——DATA_END)并启动boot,无则加载kernel并启动 kernel。U-BOOT启动的前半部分流程如图2所示:




U-BOOT启动的后半部分,会进行heap、环境变量(env)的初始化,PHY驱动的加载等工作,然后进入一个无限循环开始shell的运行,shell运行过程中的内存示意如图3所示。其中,heap和stack依次排列在bss段的后面,图中所示的free area则为U-BOOT未用到的内存。


图 3中,heap区域为malloc()提供内存。在uClib库中,malloc()是通过sbrk()或者mmap()实现的,而sbrk()和 mmap()是在内核中实现的。U-BOOT作为系统最早运行的程序,没有内核的支持。为了实现malloc(),它定义一个32K的heap区域,在此 区域的基础上实现了简化版的sbrk()。


图3中,stack区域是在U-BOOT启动的前半部分中第三步设置的。它首先根据BSS_END、heap大小和stack大小算出stack_bottom的值,然后设置堆栈指针SP和帧指针FP为stack_bottom - 4


由于水平有限,文中不免会出现疏漏。如发现问题,请发邮件告知我,谢谢!





更新于2009年2月12日
----------------------------------
前几天有个疑惑是为什么U-BOOT命令代码区竟然放在数据段,其实是我理解错了。放在数据段的并不是U-BOOT命令代码区,而是一个数组,该数组中每 一个元素为一个U-BOOT命令结构体,里面包含了命令的名称、最大参数个数、命令主函数指针等。单独作为一个section有两个作用,一是结构清晰, 二是易于添加新命令,添加时只用使用宏U_BOOT_CMD即可。
阅读(1550) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~