您好,欢迎访问三七文档
starto.S这段代码放在地址0xbfc00000,即rom的起始地址,这段代码最长可达0x00400000start在此处首先定义了一个stack变量,用于说明pmon将来要用的栈的栈底,这个栈的位置在start程序段的起点下方0x4000处.即stack=start-0x4000.1.初始化CPU内的寄存器,清TLB.接下来执行一系列指令,先把cp0的状态寄存器清0,然后再把SR_BOOT_EXC_VEC载入cp0状态寄存器,即令BEV为1,进入bootstrap模式;然后在状态寄存器中开中断4,5,使系统可以响应中断级别4,5;把cp0的cause寄存器清0.再把全局变量stack的值赋给sp,即栈顶指针初始化为栈底位置.然后为全局变量指针gp赋值.然后把下一个要执行的pc值与上0xa0000000(实际上这一步通过子程序uncached实现).转换到uncached空间.然后执行locate子程序.locate首先通过las0,startsubus0,ra,s0ands0,0xffff0000得到当前代码相对于代码初始位置start的偏移量.然后调用CPU_TLBClear清空tlb,使用tlbwi指令将tlb中全部项都清0.接下来调用函数CPU_TLBInit,从0xc0000000开始递增的1G虚地址被映射到从0x0c000000开始递增的物理地址.每页大小16M.这64页的地址映射关系被装入TLB的32项中2.初始化北桥中的CPU接口寄存器返回到locate中执行下一条指令,把北桥中的PCI0,PCI1的IO,MEM0,MEM1,MEM2,MEM3的低地址译码寄存器都置为0x00000fff,把对应高低址译码寄存器清0,即使这些译码寄存器都无效.再给CPU跟PCI总线的接口译码寄存器赋值.PCI1的IO低地址寄存器和高地址寄存器赋值为0x00000101,PCI1的remap寄存器为0,即它的io地址限定为从0x10100000开始的1M空间.再初始化PCI1的CONFIGURATION_ADDRESS寄存器为0x80000004,即enable,并令要写的寄存器号为1;PCI_1CONFIGURATION_DATA_VIRTUAL寄存器的值为0x00000011.最后把PCI0,PCI1的仲裁控制寄存器最高位置1,即enable.接下来给北桥INTERNAL_SPACE_DECODE寄存器赋初值0x01000140,即令内部空间基址域为0x140,并初始化PCISwap域为1.然后开始初始化设备计时参数.设备控制器支持五个设备体,其中四个是设备体,另外一个是驱动设备,驱动设备的默认地址映射到MIPSCPU的驱动地址0x1fc00000,它的默认带宽会在启动时被采样.每个体的存储空间可以从1M~512M,因此总设备空间可以达到2.5G.每个设备体都有自己的参数寄存器.它们的带宽可以设置为8,16,32bits.设备参数寄存器可以设置为不同的值来支持不同的设备类型.设备参数寄存器有下列域,TurnOff,定义从完成设备读到cpu开始重新驱动地址线中间的Tclk时钟间隔,这是为了防止读数据时设备总线出现拥塞,最小值是1;Acc2First,定义从ALE有效到取得第一个数据的Tclk时钟间隔,最小值是3;Acc2Next,定义读取第一个数据和读取下一个数据之间的时钟间隔,在burst访问时用,最小值是1;ALE2Wr,定义从ALE重新有效到WR有效中间的时钟间隔,最小值是3;WrLow,定义WR有效的时间长度;WrHigh定义了在burstwrite操作时两次数据写之间WR无效的间隔时间.具体怎样执行设备参数初始化见tgt_setpar125mhz和tgt_setpar100mhz,它们的实现过程很巧妙,值得看一下对于125MHZ总线的设备参数初始化如下:设备CS0--PLDTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为2,8,8,3,3,5,扩展位全部为0.设备带宽初始化为8bits.设备CS1—RTCTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为2,13,13,5,7,5,扩展位全部为0.设备带宽初始化为8bits.设备CS2—UARTTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为3,15,15,5,0,5,扩展位分别为0,0,0,0,1,0.设备带宽初始化为8bits.对于100MHZ总线的设备参数初始化如下:设备CS0--PLDTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为3,6,6,3,3,5,扩展位全部为0.设备带宽初始化为8bits.设备CS1—RTCTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为3,10,10,5,6,5,扩展位全部为0.设备带宽初始化为8bits.设备CS2—UARTTurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为4,11,11,5,6,5,扩展位全部为0.设备带宽初始化为8bits.然后把CPU_CONFIG寄存器中的StopRetry位置1.即不允许PCI传输自动重试再设置CPU对外设的接口译码器寄存器的值.CS0对应SRAM,它的低地址指向SRAM在物理内存中的基址,值为0x1c0(单位是M);它的高地址指向SRAM的顶端,值为0x1c7.CS1对应RTC设备,它的低地址为0x1c8,高地址为0x1cf.CS2对应UART设备,它的低地址为0x1d0,高地址为0x1df.CS3对应FLASH设备,它的低地址为0x1f0,高地址为0x1fb.然后再初始化rom的设备参数.首先检查设备驱动体的带宽,如果是8bits,那么就把rom带宽置为32bits,否则就置为8bits.同时把rom的TurnOff,Acc2First,Acc2Next,ALE2Wr,WrLow,WrHigh分别初始化为2,1,1,5,7,7,扩展位分别为0,1,1,0,0,0.3.调用initserial函数初始化串行IO用于诊断输出(先略)4.初始化SDRAM首先判断是否已经载入SDRAM,如果当前地址0xb000000,那么说明SDRAM已经载入,则下面这部分应该跳过直接初始化CACHE./*先把SCS0~SCS3的译码器低地址置为0xfff,高地址置为0x000.若要快速运行SDRAM,则把参数寄存器置为0x00004515,否则置为0x0000072a.*/然后写北桥上的I2C寄存器,包括把软起动寄存器置为0,波特率状态寄存器置为0x24,控制寄存器enable.首先调用probe_sdram_size获得内存slot0,slot1的大小并把它们输出.然后再对它们分别进行配置.对slot0的配置如下:首先确定设备SIZE,然后读取设备来确定BankParameter的SDType域,其中16M--1,64M,128M--2,256M,512M--3.如果是快速访问SDRAM模式,则把对应域置1.接下来写北桥的CPU对内存的接口译码寄存器检查本插槽有1面还是有两面.若只有一面,检查它的SIZE是否0x10000000,若大于,输出错误信息.否则配置SCS0的译码器低地址为0,高地址为SIZE20-1.若为两面,则先检查它的SIZE是否0x20000000,若大于,输出错误信息,若SIZE=0x10000000,置SCS0的译码器低地址为0,SCS1的译码器低地址为SIZE21,SCS0的高地址为SIZE20,SCS1的高地址为SIZE20-1.若0x10000000=SIZE0x20000000,则置SCS0低地址为0,SCS0高地址为SIZE21,置SCS1低地址为HIGHMEM_BASE(即0x20000000),置SCS1高地址为(HIGHMEM_BASE+SIZE1)20-1.很明显这里空出了从0x10000000到0x20000000的一段空间.请注意最后用变量s1记录slot0内存到达的最高地址,下面会用到这一变量.对slot1的配置如下:仅当slot0不为空时,slot1的配置与slot0不同,SIZE置为本slot1的SIZE1+s1,并执行以下操作.此时若是一面:若SIZE10x10000000,输出出错信息,否则1)若SIZE=0x10000000,SCS2的低地址为s120,高地址为(s1+SIZE1)20;2)若0x10000000SIZE且s1小于等于HIGHMEM_BASE,则s1置为HIGHMEM_BASE,并重新计算SIZE=s1+SIZE1,然后继续执行操作3;3)SCS2的低地址等于s120,高地址等于(s1+SIZE1)20-1.显然这里只要当前的内存总SIZE大于0x10000000,那么即使slot0没有把0x0~0x10000000填满,也要把slot1的内存地址从0x20000000算起,当然若已经填满,则把slot1的内存地址从slot0的终结地址算起,这个地址已经在0x20000000以上了.此时若是两面且s1!=0:SIZE=s1+(SIZE11).即先处理slot1的前一半.根据SIZE值进入不同处理语句.1)若SIZE=0x10000000,SCS2低地址为s120,高地址为SIZE20-1;然后重置SIZE=s1+SIZE1,现在处理slot1的后一半,若SIZE0x10000000,转到4;否则令SCS3低地址为(s1+SIZE11)20,高地址为(s1+SIZE1)20-1,配置完成;2)到了此处后slot1的起始地址肯定要=0x20000000,若SIZE0x10000000,进而执行这些操作:若s1HIGHMEM_BASE,直接转到3,否则置s1为HIGHMEM_BASE,仍然接着执行3;3)先重置SIZE=SIZE11+s1,置SCS2的低地址为s120,置SCS3的低地址为SIZE20,SCS2的高地址为SIZE20-1,然后重新计算SIZE=SIZE1+s1,SCS3的高地址为SIZE20-1.配置完成;4)是从1跳转而来的,这种情况是slot1的前一半放在0x10000000以下,而后一半放在0x20000000以上.若s1HIGHMEM_BASE,转到5,否则,置s1=HIGHMEM_SIZE,仍转到5;5)SCS3的低地址为SIZE020,高地址为(SIZE11+s1)20-1;最后仍然把当前内存达到的最高地址赋给s1.然后执行函数do_dense来初始化SDRAM:若是快速访问SDRAM模式,CONFIGRATION寄存器置为0x00e0c200,否则为0x04e0c080;SDRAM_ADDRESS_DECODE寄存器初始化为2,SDRAM_OPERATION_MODE寄存器清0.若是快速访存模式,依次执行下列操作:OPERATION寄存器为3,地址0xa0000000处清0,等到OPERATION寄存器最高位被控制器写成1,再令OPERATION寄存器为3,然后再在地址0xa4000000处清0,最后再等待OPERATION寄存器最高位被控制器置1.再把OPERATION寄存器清0.然后输出SDRAM_CONFIGRATION,SDRAM_TIMING_PARAMETERS,SDRAM_BANKPARAMETERS,SCS_LOW_DECODE_ADDRESS,SCS_HIGH_DECODE_ADDRESS这些寄存器的值.从0xa0000000到0xa0000000+2*1024*1024这片空间被清0.因为CACHE的SIZE最大
本文标题:pmon启动分析
链接地址:https://www.777doc.com/doc-4769978 .html