MIPS地址空间(转)
时间:2010-10-12 来源:xiaoQ008
![](/bbs/images/af892f611c69821a6241e454b5344008.png)
kuseg: 0x000 0000 - 0x7FFF FFFF (低端2G):这些地址是用户态可用的地址。在有MMU 的机器里,这些地址将一概被MMU 作转换。除非MMU 的设置被建立好,这2G 地址是不可用的。对于没有MMU 的机器,存取这2G 地址的操作与具体机器相关。你的CPU 具体厂商提供的手册将会告诉你关于这方面的信息。如果想要你的代码在有或没有MMU 的MIPS 处理器之间有兼容性,尽量避免这块区域的存取。 kseg0: 0x8000 0000 - 0x9FFF FFFF(512M): 这些地址映射到物理地址简单的通过把最高位清零,然后把它们映射到物理地址低段512M(0x0000 0000 - 0x1FFF FFFF)。因为这种映射是很简单的,通常称之为“非转换的“地址区域。几乎全部的对这段地址的存取都会通过快速缓存(cache)。因此在cache 设置好之前,不能随便使用这段地址。通常一个没有MMU 的系统会使用这段地址作为其绝大多数程序和数据的存放位置。对于有MMU 的系统,操作系统核心会存放在这个区域。 kseg1: 0xA000 0000 - 0xBFFF FFFF(512M): 这些地址通过把最高3 位清零的方法来映射到相应的物理地址上,与kseg0 映射的物理地址一样。但kseg1 是非cache 存取的。kseg1 是唯一的在系统重启时能正常工作的地址空间。这也是为什么重新启动时的入口向量是0xBFC0 0000。这个向量相应的物理地址是0x1FC0 0000。你将使用这段地址空间去存取你的初始化ROM。大多数人在这段空间使用I/O 寄存器。如果你的硬件工程师要把这段地址空间映射到非低段512M 空间,你得劝说他。 kseg2: 0xC000 0000 - 0xFFFF FFFF (1G): 这段地址空间只能在核心态下使用并且要经过MMU 的转换。在MMU 设置好之前,不能存取这段区域。除非你在写一个真正的操作系统,一般来说你不需要使用这段地址空间。
> 一个 物理地址的两个虚拟地址映射关系,不冲突.
>
实际上使用时并不会真的用2个不同的虚地址去映射同一个物理地址,因为这两个区域的属性不同。
kseg0是unmapping,cached;而kseg1是unmapping,uncached的,所以真正使用时kseg0一般 给
内核使用,kseg1作为设备地址空间使用,划分的话,可以各占一半,譬如在mips32里,kseg0使用
0x8000_0000到0x9000_0000;kseg1使用0xB000_0000到0xC000_0000,各256M即可
编辑者: bob2004 (09-01-07 13:18) 文章选项: |
|||
yjfpb04 (member) 09-01-07 13:11 |
|
||
呵呵.友情顶一记. 文章选项: |
|||
bob2004 (old hand) 09-01-07 14:25 |
|
||
找到一篇好文: 文章选项: |
|||
1help1 (old hand) 09-01-07 14:30 |
|
||
>2, 到底什么时候用0xbfc00000 , 什么时候用0x1fc00000 呢? 也就是什么用物理地址,什么时候用虚拟地址呢? 文章选项: |
|||
bob2004 (old hand) 09-01-07 15:04 |
|
||
太感谢您的回答了, 我好像理解你的意思了。 文章选项: |
|||
bob2004 (old hand) 09-01-07 15:11 |
|
||
最后一个问题, 还没有搞清楚。 文章选项: |
|||
1help1 (old hand) 09-01-07 15:30 |
|
||
>我觉得应该是 接到 0x1fc00000 或者 0x1e000000 地址上吧 ? 文章选项: |
|||
bob2004 (old hand) 09-01-07 15:40 |
|
||
再次感谢, 我再研究研究, 有什么问题, 再请教您。 文章选项: |
|||
1help1 (old hand) 09-01-07 15:41 |
|
||
>最后一个问题, 还没有搞清楚。
前言 3.2 寄存器 1)通用寄存器$0-$31 ----------------------------------------------------------------------------------------- | 寄存器 | 别名 | 主要用途 | ----------------------------------------------------------------------------------------- |$0 | | 值总是为0,可能主要用途是清空内存地址空间,以及做一些与或非 | | | | 的操作,访问速度快。 | ----------------------------------------------------------------------------------------- |$1 | $AT | 是为编译器保留的寄存器 | ----------------------------------------------------------------------------------------- |$2..$3 | V0..V1| 保存函数返回值用 | ----------------------------------------------------------------------------------------- |$4..$11 | A0..A7| 函数调用时传递参数,可以传递8个整型参数 | ----------------------------------------------------------------------------------------- |$12..$15 | T0..T3| 临时寄存器,用于保存临时变量的值,也是用的最多的寄存器 | ----------------------------------------------------------------------------------------- |$16..$23 | S0-S7 | 他们的值在过程调用的时候保持不变,可以用于传递参数或者返回值 | ----------------------------------------------------------------------------------------- |$24..$25 | T8..T9| 临时寄存器,用于保存临时变量的值,也是用的最多的寄存器 | ----------------------------------------------------------------------------------------- |$26..$27 | K0..K1| 保留给操作系统内核使用 | ----------------------------------------------------------------------------------------- |$28 | GP | 保存全局指针 | ----------------------------------------------------------------------------------------- |$29 | SP | 保存堆栈指针 | ----------------------------------------------------------------------------------------- |$30 | FP或S8| 保存帧指针,也可以和S0..S7一样使用 | ----------------------------------------------------------------------------------------- |$31 | RA | 保存返回地址 | ----------------------------------------------------------------------------------------- 2) 专用寄存器 HI和LO主要用于地址转换使选择页面,PC是指令计数器。 3)控制寄存器 在au1500中有很多的控制寄存 器,象串口、网卡、时钟、中断、PCI,内存、DMA等等的设置都是通过这些寄存器来完成的,这些寄存器的操作是通过内存中特定的地址空间来进行的,读或 写这些地址空间就是读取或设置相应寄存器的值。 ----------------------------------------------- | 控制器 | 基地址 | ----------------------------------------------- | 内存控制器(FLASH,SDRAM)| 0xB4000000 | ----------------------------------------------- |PCI 控制器 | 0x014005000 | ----------------------------------------------- |DMA 控制器 | 0xB4002000 | ----------------------------------------------- | 中断控制器1 | 0xB0400000 | ----------------------------------------------- | 中断控制器2 | 0xB1800000 | ----------------------------------------------- |AC97 的 | 0XB0000000 | ----------------------------------------------- |USB HOST | 0XB0100000 | ----------------------------------------------- |USB DEVICE | 0XB0200000 | ----------------------------------------------- |Ethernet MAC0 | 0XB1500000 | ----------------------------------------------- |Ethernet MAC1 | 0XB1510000 | ----------------------------------------------- |UART0 | 0XB1100000 | ----------------------------------------------- |UART3 | 0XB1400000 | ----------------------------------------------- |GPIO2 | 0XB1700000 | ----------------------------------------------- | 系统控制(CLOCK,POWER) | 0XB1900000 | ----------------------------------------------- 3.3 内存 内存分为静态存储(FLASH/ROM),动态存储(SDRAM,SYNCFLASH)。 AU1500的虚地址空间有4G,物理地 址空间有512M。 内存的CSBA和CSMASK是在系统初始化的时候设定的。 虚拟地址空间 物理地址空间 |-------------|0xffffffff /\------------|-------------|0x1fffffff | | | /|\ | bootzone | | | | | | ---->0x1fc00000启动地址 | | | | | 32M flash1 | | | | | | | | kseg3 |通过MMU映射为物理地址使用| | | -----------0x1e000000 | | | | | bootzone | | | | | | ---->0x1dc00000启动地址 | | | | | 32M flash0 | | | | | | | |-------------|0xe0000000 | | |-------------|0x1c000000 | | | | | | | kseg2 |通过MMU映射为物理地址使用| | | | | | | | | | | |0xc0000000 | | | | |-------------|0xbfffffff------------->| | |-------------|0x04000000 | | | | | | kseg1 |直接对应为物理地址使用 | | 64M SDRAM | | | | | | |-------------|0xa0000000--------------------------->|-------------|0x00000000 | |0x9fffffff--------------------->| /|\ | | | | kseg0 |直接对应为物理地址使用 | | | | |-------------|0x80000000--------------------------->| | | | kuseg |映射为物理地址使用 | | |-------------|0x00000000 3.4 启动 PB1500启动所选择的FLASH可以通过开关S13来选择两组中的一组,分别对应物理基地址0x1fc00000和 0x1dc00000. 系统加电的时候cpu就从此地址处开始读入代码执行。此地址也就是系统异常处理向量表的第一项(reset)。 3、 bootloader PB1500自带一个引导程序YAMON,同时YAMON还完成一些系统配置和程序调试的功能。再启动过程中主要涉及的 yamon的几个主要文件依次 为:reset.S-->reset_pb1500.S-->init.S-->main.c-->shell_init.c 下 面对yamon的启动流程做一个简要的说明:(详细的注释可以查看相关文件的注释) 0xbfc00000 系统的第一条指令,无他,和许多系统的一样,跳!b reset_au1xxx,跳到了标号reset_au1xxx促 执行,此标号处是个include指令,系统随即进入了reser_pb1500中,那reset.S作了什么?原来reset设置了系统的一些参数和一 些入口地址,象异常处理,中断,shell函数入口等。以便下面的程序执行时出现异常有地方可去,不至于莫名其妙的死掉。reset_pb1500.S完 成了系统的大部分初始化工作,设置寄存器,初始化cpu,初始化SDRAM,初始化FLASH等,然后回到reset.S,reset.S剩下的代码没几 行,主要是根据cpu的endian mode来决定接下来跳转的函数,_reset_handler_be/_reset_handler_le,这两个标号再连接脚本中定义,分别指向两种 mode下的入口函数的地址,0xbfc90000/0xbfc10000,此地址也就是函数__reset_handler_end函数的地址,这个函 数位于init.s文件中,此文件所作的工作是初始化和pb1500以及yamon运行环境相关的一些环境,包括 cpu,cache,mem,stack,uart等,然后调用了系统的第一个c函数,终于熬出苦海了:-),main.c函数还是在设置系统环境,不知 道哪里有这么多的东西要设置,最后调用shell_setup函数,进入shell_init.c文件,此文件准备了shell的环境,终于我们期待已久 的提示符 YAMON>出现了。 下面按指令的顺序开始介绍: 0xbfc00000 jump to reset_au1x00 3个nop 板子id nop 1个测试数据 0xbfc00400 异常处理的入口,进入中断或死循环 0xbfc00480 EJTAG的处理 0xbfc00500 shell函数的入口,22个表项 0xbfc00558 reset_pb1x00 设置cpu的endian mode 设置cp0的状态 失效watchpoint 失效性能计数器 设置EJTAG寄存器 设置CAUSE寄存器 初始化cache,并转到cachable的内存中执行指令从kseg1-->kseg0 初始化TLB 设置cpu pll频率 设置系统总线 设置AUX PLL频率 开始32KHz的震荡? 初始化静态存储器 设置外设 探测reset的原因(硬件,睡眠,运行期) 初始化动态存储器 初始化外设 到init.S中 init.S 初始化cp0-cause寄存器 探测板子 初始化串口 显示cpu信息 初始化cpu 初始化cache 内存测试 拷贝代码到ram中,并转到ram中继续执行 拷贝数据 设置堆栈 设置系统信息和cache 调用c_entry,进入main.c main.c 初始化平台相关的参数 初始化模块 参数优化 设置loader的参数 shell_setup shell_init.c 加载shell的函数 加载shell命令 进入shell循环:shell():YAMON> yamon对于内核加载的完成步骤: 使用load命令 load命令调用loader函数 loader函数从网络上通过tftp获取内核映象 将映象存储在shell_load_addr全局变量中 设置shell_load_addr_valid全局变量为true 使用go命令 go命令将shell_load_addr存储在cp0-epc寄存器中 用break命令产生一个exception 系统转到shell_load_addr去执行异常处理函数,也就是我们的内核的入口 AU1200 SoC 及 NorFlash 物理地址与虚拟地址的映射机制 收藏基准文档: au1200_datasheet.pdf, ml2010-0129.pdf(美菱项目电路图), S29GL064N90TFI04 Flash datasheet
以上为AU1200 SoC的结构/接口示意图,其中左上角为MIPS32 Core(Au1 Core),其他模块均为各种SoC片上的外设控制器,所有的这些片内模块都是通过SoC内部的System Bus 和 Peripheral Bus 进行连接和通信的。 Au1 Core作为一个典型的MIPS32架构的CPU,其特性符合《See MIPS Run, 2nd》文档中的描述,此处参考该文 2.8 节中的描述的MIPS架构地址空间基本概念和图示。在程序中(即使是已经过编译、汇编和链接得到的可执行二进制程序,也不论是应用程序还是系统程序)使用 的任何地址都是虚拟地址,当MIPS-Core读取这些程序的机器指令时,这些虚拟地址都要通过特定的地址映射机制进行地址转换(不一定非得是通过 MMU),从而由Au1 Core的数据总线送出物理地址到 SoC 的 System Bus 上。虽然MIPS的地址映射机制与x86不一样,VM中某些区域的虚拟地址到物理地址的转换非常简单,但是虚拟地址和物理地址的值肯定时不一样的。 MIPS CPU运行的状态同样也分为用户态和内核态,不过和其他处理器的内核态/用户态机制不同,MIPS架构下当从内核态切换到用户态时,除了应用程序不能访问 虚拟地址空间高2GB区域(虚拟地址最高位为1),否则会引发错误导致trap之外,其他并没有任何区别。程序所见的虚拟地址空间布局如下:
AU1200 SoC 中,Au1-Core 会将32位的虚拟地址转换为36-bit的物理地址送上 System Bus(datasheet, 2.5),System Bus 的36-bit物理总线由 36-bits 地址总线sysbus_addr[35:0] 和 32-bits数据总线sysbus_data[31:0] 复用。 AU1200 SoC中,Flash、ROM等外设是通过片内的SRAM Controller控制和连接的。SRAM Controller描述位于datasheet中的3.2节,它包括4个片选(chip select),在美菱项目原理图中,这个四个片选信号对应于AU_CS0~AU_CS3引脚,我们使用的是AU_CS0来作为NorFlash的片使能 (见原理图P7)。 对于sysbus_addr[36], sysbus_addr[35:32]的值见AU1200 datasheet, Table 20 所述,我们使用SRAM Controller连接的是NorFlash,因此对于NorFlash,System Bus传递过来的36-bits物理地址中高四位为0。 在AU1200 datasheet 3.2.5 节中描述了SRAM Controller 连接NorFlash时,发送给NorFlash的各种信号,其中的RAD[14:0]就是AU1200 SoC真正发送给NorFlash物理设备的地址信号 ,RAD[14:0]在美菱项目电路图中对应于 AU_ADDR[0:14] 这一组15根引脚。由于SRAM Controller内部实现的地址锁存机制(Datasheet 3.2.2节),最终AU1200 SoC传出给NorFlash、ROM设备的地址数据可以达到 30 bits,即可以寻址最大1 GB的 NorFLash设备,而这30 bits的地址值正是SoC内的System Bus传递给SRAM Controller的36-bits 物理地址中的低30 bits,分两次发送到NorFlash物理外设的地址引脚上。 在美菱项目中, 我们使用的 8MB NorFlash(型号:S29GL064N90TFI04, 其中的64表示64Mbit)是按word(16 bits)进行寻址的,并且由于我们在电路设计中, NorFlash 的 BYTE# 引脚被拉高,所以每次NorFlash读写都是2 Bytes的数据(详见 Flash datasheet)。因此,我们使 用的8MB NorFlash实际有效的地址引脚共22根(A0~A21) ,222 × 2 Bytes = 8MB,即NorFlash的地址总线为23 bits。在电路原理图中所标识出来的A23实际是无效的,仅仅只是为了一个系列NorFlash封装一致,才往往将该系列NorFlash封装的地址引 脚数统一为该系列中大容量NorFlash的地址引脚数。
我们只使用了SRAM Controller通过 RAD[14:0]+锁存 送出来的30-bits地址中的22位, 即对应于原理图Page 7中所示的 AU_ADDR1 ~ AU_ADDR14 和 LATCH_ADDR15 ~ LATCH_ADDR22 。 在美菱项目电路原 理图Page 7中可见,我们外加了一个地址锁存器SN74LVC16374ADGGR,锁存 AU_ADDR[0:15]中的AU_ADDR[0:7],这正是SRAM Controller通过内部的锁存机制送出来的15-bits物理地址的低8位。 AU_ADDR[1:14] 和 LATCH_ADDR[15:22] 这22根引脚,依次对应于SoC片内System Bus传递的 sysbus_addr[0:35] 中的 sysbus_addr[1:22] ,对应连接至NorFlash外设的 A0~A21这22根引脚。 为什么将 AU_ADDR1 和 A0 连接而不是将 AU_ADDR0 和 A0 连接呢?这还是因为我们使用的NorFlash是以word(16 bits)寻址的,而程序所面对的虚拟地址空间则是按8-bits字节寻址的,假设在程序中需要操作0xBFD0 0000 和 0xBFD0 0001 这两个地址中的字节数据,但是这两个8-bits数据在NorFlash中其实是同一个16-bits单元中的数据,因此我们在程序中使用的 0xBFD0 0000 和 0xBFD0 0001 这两个地址需要在NorFlash中对应于同一个基本数据单元——将 AU_ADDR1 和 A0 引脚连接就可以达到这个目的。 最后来说明程序中(这里的“程序”包括在机器上跑的典型应用程序,flash_eraseall、flashcp等flash软件,也包 括BDI内置软件,BDI控制台下使用erase、prog、go等命令时都是直接使用虚拟地址 )所使用的系统上电启动地址 0xBFC0 0000 是如何一步一步映射到NorFlash A0~A21这22根引脚上的:
综上,上电启动地址对应到NorFlash的地址引脚的值 ( 10 0000 0000 0000 0000 0000 = 0x20000 0) 所标识的物理地址位于NorFlash中的最后 4MB 起始处,注意:此处的NorFlash的基本存储单元是16 bits=2 Bytes,因此上电启动地址之后的NorFlash容量为 (0x3FFFFF - 0x200000 + 1)*2 = 4MB,也就意为着作为上电执行的Yamon程序,应该保存在NorFlash的最后4MB起始处。 如果NorFlash仍然保持word寻址,当NorFlash容量变为至4 MB,即NorFlash设备有效地址引脚变为 A0~A20,相应地,地址锁存器锁存的 AU1200 SoC 第二次输出的地址信号的 AU_ADDR[0:6], 最终NorFlash 地址总线引脚 A20~A0 上对应的值应该是 ( 0 0000 0000 0000 0000 0000 =0x000000 ), 即NorFlash的起始处。此时, Yamon程序仍然应该保存在NorFlash的最后4MB起始处,只是此时最后 4MB也就是最开始的4MB而已 。 当NorFlash容量小于 4 MB的时候,则无论容量是多少, 0xBFC0 0000 上电启动地址对应的NorFlash 地址总线引脚 A0~An (n<20)上信号全为0,则此时YAMON程序应该放在NorFlash的起始位置。
同理,当NorFlash容量扩大至16 MB的时候, NorFlash 设备有效地址引脚变为 A0~A22, 相应地,地址锁存 器锁存的 AU1200 SoC 第二次输出的地址信号的 AU_ADDR[0:8], 最终 NorFlash 地址总线引脚 A20~A0 上对应的值应该是 ( 110 0000 0000 0000 0000 0000 =0x600000 ), 上电启动地址之后 的NorFlash容量为 (0x7FFFFF - 0x600000 + 1)*2 = 4MB ,即Yamon程序仍然应该保存在NorFlash的最后4MB起始处。 同理,如果 NorFlash容量扩大至512 MB的时候, 假设引脚数也是足够的, NorFlash 设备有效地址引脚变为 A0~A27, 相应地,地址锁存器锁存 AU1200 SoC 第二次输出的地址信号中的AU_ADDR[0:13], 最终 NorFlash 地址总线引脚 A27~A0 上对应的值应该是 ( 1111 1110 0000 0000 0000 0000 0000 =0xFE00000 ), 上电启动地址之后 的NorFlash容量为 (0xFFFFFFF - 0xFE00000 + 1)*2 = 4MB, 即Yamon程序 仍然应该保存在NorFlash的最后4MB起始处。 但是,当NorFlash容量扩大至1024 MB时, NorFlash 设备有效地址引脚变为 A0~A28, 地址锁存器锁存 SoC 第二次输出的地址信号中的全部AU_ADDR[0:14], 最终 NorFlash 地址总线引脚 A28~A0 上对应的值应该是 ( 0 1111 1110 0000 0000 0000 0000 0000 =0x0FE00000 ), 此时 上电启动地址之后 的NorFlash容量变为了 (0x1FFFFFFF - 0x0FE00000 + 1)*2 = 516 MB 了,即此时 Yamon程序仍 然应该保存在NorFlash的最后516MB起始处。而此时的情况也就是AU1200能够通过SRAM Controller寻址的最大容量NorFlash 了。 |