关于armlinux或者uclinux的启动地址的问题?

pengjunjun0807 2009-10-14 09:45:29
以下来自“源码开放的嵌入式系统软件分析与实践”原文,对此不甚理解:

内核链接脚本文件vmlinux.lds定义各个模块的装载地址。内核的下载一般通过板子上的bootloader来完成,默认下载地址在0xc0008000处,下载地址可以通过修改arch/arm/Makefile文件的TEXTADDR来设置。TEXTADDR的值在make时传递给arch/arm/vmlinux.lds。在链接时,arm-linux ld将使用vmlinux.lds来定位内核的起始地址。

我们知道,任何二进制文件的装载都是通过装载工具来设置的啊?其装载地址也是自己设定的啊?比如ADS将系统的SDRAM映射到起始地址为0x0处,并将image.ram载入从0x8000开始的SDRAM中,加载后修改pc指针寄存器的值为0x8000并执行(出自“arm应用系统开发详解”)。

再说,假如我的开发板并没有映射那个地址(我映射到其他的地址上去了),vmlinux.lds又如何能确定内核的起始地址呢?怎么能通过这个文件来设置内核的起始地址呢?

一头雾水,望同仁们指定,不甚感激!!
...全文
139 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengjunjun0807 2009-10-16
  • 打赏
  • 举报
回复
多谢各位的诠释,小弟心中疑惑油然尽失,有了方向,便勇往直前...
pengjunjun0807 2009-10-15
  • 打赏
  • 举报
回复
谢谢,已经有很大启发了,再仔细琢磨琢磨
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
提醒,这是我的理解。我也是刚开始做Linux的内核移植,可能不对喔^_^。
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
ld脚本有两个地址,一个是VMA,一个是LMA。VMA用来在编译和链接是计算符号的地址,LMA是加载的地址。两者通常是一样的。
但当你把image烧到不同于VMA的地方是,那么你的LMA就要改成你烧写的地方(通过LD脚本的AT语句)。

在内核启动以前,MMU是不生效的,所以代码其实是运行在实模式。在这个阶段,符号地址需要自己去计算。比如你实际代码在0xf0000000而VMA是0xc0000000。那么你在使用jump或者branch类的指令是,你要把符号的位置(0xc。。。。。)转换成代码所在的真正位置(0xf。。。。。)

所以,简单地说,bootloader如果要把kernel加载到0xc0000000这个地址的话,那么它需要先建立MMU,如果不是,bootloader只能把kernel的镜像copy到内存,然后直接jump到kernel开始的位置(head.S)。由于kernel一开始运行在实模式,没有MMU,所以head.S的代码对于jump和branch指令的计算,需要代码自己来做。
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 pengjunjun0807 的回复:]
还是觉得8楼的话有道理,但是uclinux也是先运行在实模式下,然后切换到mmu模式的吗?
[/Quote]

这个就不是一两个帖子能说清楚的了。Understanding the Linux Kernel里面解释得比较详细。
简单来说就是建立初始的page table,这时要把实模式下的地址也写进这个page table,使得实模式下的地址在保护模式和实模式都可以用。然后通知硬件启用MMU。但对于没有MMU的平台,应该是要通知软件MMU开始运作。

还是参考一下书吧。有些功夫是不能省的,还要结合代码来看。
pengjunjun0807 2009-10-15
  • 打赏
  • 举报
回复
还是觉得8楼的话有道理,但是uclinux也是先运行在实模式下,然后切换到mmu模式的吗?
盘股之 2009-10-15
  • 打赏
  • 举报
回复
隐约记得好像是这样:
板子上电后CPU首先在地址0处找到存放bootloader的ROM或者Flash,当然有些CPU设计的上电启动地址并不是0x0000,而是0x8000,但是硬件在设计的时候,你的Flash或者ROM,RAM是要符合这种CPU架构的,也就是寻址Flash的地址必须从0x8000开始.这就是CPU上那几根地址选择线的作用.
上电后,Bootloader启动时,会初始化CPU的某些寄存器,包括中断向量寄存器,MMU单元的寄存器等等,然后还要设置一些内核存放地址等,这些设置完了之后,就进入bootloader的应用部分,应用部分可以有关于网络通讯的比如tftp,串口通讯的等等,提供一个界面,选择什么就用什么,这些都是用来下载内核,擦除烧写内核到Flash的工具而已.用这些工具将内核和文件系统准备好后,重新启动板子,到bootloader提示,这时如果选择启动内核,那么bootloader就会把CPU的地址指针跳转到存放内核的位置,然后内核就接管所有的指挥控制大权.
至于楼主所说的情况,首先是,如果写错了地址,bootloader找不到内核,除非你同时修改bootlaoder.
其次,往不存在的地址写数据,这句话本身我就没有明白,可能楼主想说所谓不存在的地址是超出了Flash或ROM的大小范围的地址吧,如果出现这种情况,可能会发生写入错误或者总线地址错误,因为你有可能把数据写到某些外设的地址空间去了或者总线无应答,出现地址错误.
应该是这样吧.
几年前搞过一点点,复习一下,请高人批评.
wxdcxp 2009-10-15
  • 打赏
  • 举报
回复
准备买板子搞移植
之前都是做嵌入式应用程序开发
充电宝111 2009-10-14
  • 打赏
  • 举报
回复
0xc0008000是虚拟地址,跟你bootloader加载的地址是两码事
chenhuafei 2009-10-14
  • 打赏
  • 举报
回复
这东西之前看过,忘了
不过
是我用串口烧写时并不将内核烧入0xc0008000,而是烧入到其他的位置,那会出现什么情况呢?
-----------bootloader在指定位置找不到内核,启动失败
假如我在vmlinux.lds中设置了起始地址为0xc0008000,但是我的开发板中并没有这个地址,那会出现什么情况呢?----呵呵,那你自责以下,没有这个地址你还不改过来阿,结果不是解压失败,就是启动失败啦。
另外
0xc0008000应该是ram中的地址,是kernel起始运行地址,
实际烧写到flash的地址似乎是ZTextaddr,这个google下,有人讲的很清楚的。
pengjunjun0807 2009-10-14
  • 打赏
  • 举报
回复
假如我在vmlinux.lds中设置了起始地址为0xc0008000,但是我用串口烧写时并不将内核烧入0xc0008000,而是烧入到其他的位置,那会出现什么情况呢?

假如我在vmlinux.lds中设置了起始地址为0xc0008000,但是我的开发板中并没有这个地址,那会出现什么情况呢?
pengjunjun0807 2009-10-14
  • 打赏
  • 举报
回复
那前面的问题如何解释啊?
zkuang82 2009-10-14
  • 打赏
  • 举报
回复
uclinux走的平台没有MMU,但内核似乎有相关软件层支持。
pengjunjun0807 2009-10-14
  • 打赏
  • 举报
回复
怎么么人回答啊,自己顶!
pengjunjun0807 2009-10-14
  • 打赏
  • 举报
回复
谢谢三楼,我也这么认为的,那请问uclinux中也有虚拟地址吗?它不是没有mmu的吗?

4,468

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧