侏儒症是什么意思?:MPC860上电初始化流程分析 - 我的文章 - VxWorks

来源:百度文库 编辑:偶看新闻 时间:2024/04/19 16:06:21
MPC860上电初始化流程分析

MPC860上电初始化流程分析
作者: 村姑

【复位向量】
860复位后,执行的第一条指令位于4GB地址空间的什么地方?
对于PowerPC,复位也是一种异常(你可以理解为CPU自己产生的中断),向量号为0x100。异常向量表的基地址加上复位向量号即为复位向量,也就是CPU开始执行指令的地方。异常向量表在内存空间的可能位置有2个:0x00000000和0xFFF00000。具体是哪一个由MSR寄存器的IP位指定:若IP位为0,则异常向量表在0x0处,否则在0xFFF00000处。860有多种复位方式,对于hard reset,MSR的IP位由硬件配置字的IIP(Initial Interrupt Prefix)位决定。
所以PowerPC的复位向量为0x100或者0xFFF00100。以下我们假定0xFFF00100。
【硬件配置字】
TBD
【Flash Memory】
假设有128K字节的Flash,并打算把它映射到CPU内存空间的0xFE000000开始的地方。但由于复位向量为0xFFF00100,那么怎么才能让CPU从Flash中偏移0x100的地方开始执行指令呢?
860内嵌的memory controller有个引脚,#CS0,称为global boot chip select,一般把它连接到Flash或EPROM的片选上。假定这128K Flash是8位数据宽度,地址线A16..0分别连接到860的A15..A31(注意A31为860地址线的最低位),数据线D0..7分别和860的D0..7相连。再看控制#CS0的BR0和OR0寄存器,CPU复位后,BR0.V=1(Valid)且BR0.BA[0..16]=0,OR0.AM[0..16]=0。由于地址掩码AM位全为0,意味内存控制器会忽略所有参与片选逻辑的地址线A0..A16,所以产生的#CS0总是有效的。这样,上电后Flash总会被选中。CPU从Flash偏移0x100的地方取指令。这个结果和复位向量表基地址,以及以后Flash映射到CPU内存空间的什么位置都是无关的。
以上结果还有一个现象,就是复位后,CPU的4GB内存空间内都是Flash。4GB空间的每个128K的块都被映射到Flash。原因用一句话概括:Flash只使用了32位地址线的低17根,且缺省地被选中。
【VxWorks初始化】
/* romInit.s - Motorola 860mbx ROM initialization module */
/* Copyright 1984-1998 Wind River Systems, Inc. */
/* Copyright 1997,1998 Motorola, Inc. All Rights Reserved */
.data
■ 定义数据段。
    .globl copyright_wind_river
    .long   copyright_wind_river
■ 申明(declare)全局变量_copyright_wind_river并使用它定义一个新变量。
■ 注意”.globl”是申明而非定义。”_copyright_wind_river”变量在Tornado的库(对于MPC860,为[Tornado]/target/lib/libPPC860gnuvx.a)中的一个模块copyright.o中定义。
■ ”.long”定义一个32-bit的全局变量(没有变量名),变量的初始值为_copyright_wind_river的值(还是地址?)。由于在Makefile中规定了romInit.o为第一个链接的模块,所以这个无名变量将出现在数据段的最开始。
■ 不清楚_copyright_wind_river的用途,以及这个无名变量的用途。
#define _ASMLANGUAGE
■ 定义_ASMLANGUAGE。GNU汇编器GAS看到这个定义后,会按照C的语法进行预处理,所以GAS预处理器能够认识C头文件中定义的类型和宏(?)。如果不定义_ASMLANGUAGE,以下的#include语句将无法编译。
#include "vxWorks.h"
#include "asm.h"
#include "cacheLib.h"
#include "config.h"
#include "regs.h"
#include "sysLib.h"
#include "drv/multi/ppc860Siu.h"
    .globl _romInit
    .globl romInit
    .extern romStart
    .extern mbxI2cConfigParamsGet
    .extern mbxI2cMemcConfig
    .text
    .align 2
/******************************************************************************
* romInit - entry point for VxWorks in ROM
*/
_romInit:
romInit:
■ 同时定义_romInit和romInit的原因是,有些编译器产生的对外部符号的调用不加下划线,而有些加。
    bl cold
    bl start
■ 若是热启动,则跳转到start。激活热启动的代码将跳转到romInit+4处。注意PowerPC的所有指令都占4字节(32位)。
    /* copyright notice appears at beginning of ROM (in TEXT segment) */
    .ascii "Copyright 1984-1997 Wind River Systems, Inc."
.align 2
■ 以上定义的版权申明字符串将出现在代码段中。
■ 不清楚这个字符串的作用。
cold:
    li      r3, BOOT_COLD                /* r3 = BOOT_COLD */
    lis     r4, HIADJ(start)
    addi    r4, r4, LO(start)           /* r4 = @start */
    lis     r5, HIADJ(romInit)
    addi    r5, r5, LO(romInit)         /* r5 = @romInit */
    lis     r6, HIADJ(ROM_TEXT_ADRS)
    addi    r6, r6, LO(ROM_TEXT_ADRS)   /* r6 = ROM_TEXT_ADRS */
    sub     r4, r4, r5                    /* r4 = r4 – r5 */
    add     r4, r4, r6                    /* r4 = r4 + r6 */
■ 计算start在Flash中的位置,为:start-romInit+ROM_TEXT_ADRS。并跳转到这个位置(下面)。为什么要这样?
■ 由前面的分析可知,CPU从0xFFF00100启动;由于在CPU看来,全部的4GB空间中的每个128K的块都被映射到了Flash,所以0xFFF00100这个地址仍在Flash的偏移0x100处。这是起始状态,但不可能真的就把全部4GB空间都给Flash,在以后的初始化中,必定要把RAM,IMMR和外设等也要映射进来。做这些之前,需要把Flash的位置固定一下,比如映射到0xFE000000;方法是写OR0和BR0寄存器。但在写OR0时,CPU还在从0xFFF00000的那一块取指令,而Flash就要被映射到0xFE000000块,所以程序必定跑飞掉。所以,要对程序计数器(PC)进行调整。然而PC指针对程序员是不可见的,我们打算用跳转指令修改它。
■ 不能直接跳转到start处,必须自己计算地址。why?在链接时,我们曾指示ld将代码段定位于RAM_HIGH_ADRS(bootrom;对vxWorks_rom是RAM_LOW_ADRS;参考相关的Makefile)。在我们的例子里RAM_HIGH_ADRS=0x00200000,即2M的地方。毕竟大部分代码还要在RAM中执行,是吧!现在的问题在于romInit也在代码段中,但它是从ROM中执行的(0xFE000100),而不是在连接器假定的位置执行的。对连接器而言,符号romInit和start的值都是假定了程序在RAM中。可以想象,对链接器而言,romInit=0x00200000,指向RAM区。同样start也指向RAM区。欲得到start在ROM中的位置,计算方法就是start-romInit+ROM_TEXT_ADRS,其中ROM_TEXT_ADRS=0xFE000100。
■ 以上代码叫PIC(Position Independent Code)。在程序将自身拷贝到RAM之前,需要注意。
■ 另外一个结论是,ROM映射到CPU地址空间何处都可以,只要不和其它东西冲突。
    mtspr   LR, r4
    blr                                 /* jump to flash mem adress */
■ 把r4值放入LR寄存器,利用blr跳转到LR指定的地址。

■ 以上代码似乎可以用以下代码代替(?):
lis     r4, HIADJ(start – romInit + ROM_TEXT_ADRS)
addi    r4, r4, LO(start – romInit + ROM_TEXT_ADRS)
mtspr   LR, r4
blr
start:
(略)
■ 以下进行系统初始化工作,包括:
初始化CPU核心寄存器;
禁止cache;
初始化IMMR;
初始化SIU;
初始化时钟和中断控制寄存器;
初始化CPM;
初始化UPM。等等。