|
RT-Thread MIPS分支连载:MIPS32的内存地址空间
[复制链接]
MIPS核心是一个很规范很简洁的核心,简洁到,有些事情需要软件来帮核心考虑。例如MIPS的内存空间,按照MIPS的规定,所有软件访问的地址都需要经过虚拟地址到物理地址的转换,而地址空间则统一划分为:<联想到ARM的各厂商芯片五花八门的地址空间>
kseg2 1G 0xC000 0000 kseg1 512M 0xA000 0000 kseg0 512M 0x8000 0000 kuseg 2G 0x0000 0000 大致4个区域:kseg0,kseg1都是映射到相同的物理地址,一般是:0x0000 0000 - 0x2000 0000。两者的区别是:kseg1是uncached,kseg0 是cached。而kuseg是为user模式而准备的。对于一个实时系统而言,一般仅使用kernel模式,以获得更直接的访问权限。kseg0和 kseg1还是非常有特点的,例如,普通的代码,一般需要跑得尽可能的快,那么cache是必然的,所以放到kseg0运行就好。但是另外一些特殊代码,例如用于DMA的数据,希望它是真真实实的写入到相应的内存地址,然后再启动DMA进行搬送,那么给出的地址是kseg1就可以满足要求了(都不再需要手工的写指令去刷cache,省事!)。
当机器上电时,MIPS芯片只有kseg0和kseg1 是可以存取的,并且从0xbfc0 0000 处开始运行。很明显,把RT-Thread Kernel放到kseg0运行无疑是最合理的(速度,速度!没有cache的操作系统运行如蜗牛)。但是,机器上电运行的位置是0xbfc0 0000,为什么不从这个位置去运行?
- 通常编译一个程序,最后的一道工序是链接,链接可以附带一个链接脚本。如果说在链接脚本中把入口点放在0xbfc0 0000,然后再程序手动跳转到0x80000000 + offset。这样的链接脚本下出来肯定没问题的,但是,当最后链接生成image文件时,会发现这个image会爆大(当然也有技巧整小些……)。
- 另外一个原因是,通常开发板上都带了一个boot loader,MIPS平台上常用的是pmon(功能很强,能够直接载入tftp上的elf文件,获得符号表等等)。当这个boot loader运行起来时,它的运行空间已经是0x8000 0000 + offset了,并且能够把一个elf或者bin文件加载到0x8000 + offset的kseg0空间。
所以,直接把RT-Thread Kernel的其实地址放到kseg0中比较合理。但是把它直接放到0x8000 0000上则不见得合理,因为boot loader通常会占用了这块空间,例如pmon,它基本上不允许下载到这块内存空间;另外是,0x8000 0000 ~ 0x8000 0200是MIPS的统一的异常处理入口。
在龙芯SoC 3210开发板上,自身已经携带了pmon,所以可以直接使用而不需要去烧写flash。并选择RT-Thread Kernel的入口为0x8020 0000这个位置。对于0x8000 0000 ~ 0x8000 0200的异常入口,则采取在代码及链接脚本中放置一个小的section,当RT-Thread启动时,采用多段加载的形式把它复制到0x8000 0000地址去。
[ 本帖最后由 ffxz 于 2010-10-29 17:27 编辑 ]
|
|