Vxworks的启动和所有的嵌入式操作系统一样,首先要启动boot程序,然后由boot引导真正的内核印象和版本。不同的是,vxworks的boot(也就是BSP)和大版本之间的代码有很多重入的地方,启动的过程也极其相似,这里就以MPC852为例,结合其BSP的源码分析一下整个启动的过程。
上图为BSP启动所要经历的几个文件中的几个函数,这个图相信大家已经看过很多次了,下面将以函数为单位一一介绍。
上电复位:
复位也是一种异常,向量号为0x100。异常向量表的基地址加上复位向量号即为复位向量,也就是CPU开始执行指令的地方。异常向量表在内存空间的可能位置有2个:0x00000000和0xFFF00000。具体是哪一个由MSR寄存器的IP位指定:若IP位为0,则异常向量表在0x0处,否则在0xFFF00000处。硬件复位时MSR的IP位由硬件配置字的IIP(Initial Interrupt Prefix)位决定,在本系统中IP为1,所以上电后的第一条指令是在0xFFF00100处读取的。
在MPC852内嵌的Memory Controller中,有系统的片选引脚,一般将片选引脚CS0连接到Boot Flash上,本系统中Boot Flash的大小为1M。决定该片选基地址和大小的是BR0和OR0两个寄存器的BA[0:16]位和OA[0:16]位,这两个寄存器的这些位在上电后值为全零,也就是说,在上电后,从0x00000000开始4GB的空间都是Boot Flash,每1M都重复映射到该空间,所以第一条指令0xFFF00100肯定是在BOOT中。
由Makefile文件的ROM_TEXT_ADRS = FFF00100 # ROM entry address 而ROM_TEXT_ADRS正是romInit函数在ROM中对应的位置(romInit标号在RAM中),所以可以得出上电后的第一句代码正是romInit()函数。
romInit()函数
该函数在romInit.s文件中,由PowerPC的汇编语言编写,主要完成最基本的CPU寄存器,初始化SDRAM,然后跳转到第一个C函数bootInit.c中的romstart()。下面为具体的代码:
_romInit:
romInit:
bl cold /* jump to the cold boot initialization */
bl start /* warm启动就直接跳到start*/
.ascii
.align 2
/*cold启动*/
cold:
li r3, BOOT_COLD /* BOOT_COLD将会作为启动类型被传送到romStart( )程序中去*/
/*下面这段所做的工作是计算标识start在ROM中的位置。为什么要计算呢,因为大多数的BSP的代码是在RAM中运行,所以连接器默认的标识都是处于RAM中,就像下面的标识start和romInit,前面又说过了,ROM_TEXT_ADRS是romInit在ROM中对应的位置以偏移的关系可以得出一些RAM中的标识在ROM中的位置,后面还会出现很多次。计算的公式为:ROM_ADRS(x) = (x) – romInit + ROM_TEXT_ARDS*/
lis r4, HIADJ(start) /* load r4 with the address */
addi r4, r4, LO(start) /* of start */
lis r5, HIADJ(romInit) /* load r5 with the address */
addi r5, r5, LO(romInit) /* of romInit() */
lis r6, HIADJ(ROM_TEXT_ADRS) /* load r6 with the address */
addi r6, r6, LO(ROM_TEXT_ADRS) /* of ROM_TEXT_ADRS */
sub r4, r4, r5
add r4, r4, r6
mtspr LR, r4 /* save destination address*/
/* into LR register */
blr /* jump to flash mem address */
start:
/*清除MSR,DER,ICR寄存器*/
xor r4, r4, r4 /* clear register R4 */
mtmsr r4 /* cleat the MSR register */
mtspr DER, r4
mtspr ICR, r4
/*初始化ICTRL寄存器*/
lis r5, HIADJ(0x00000007)
addi r5, r5, LO(0x00000007)
mtspr ICTRL, r5
/*禁止指令和数据CACHE */
lis r4, HIADJ ( CACHE_CMD_DISABLE) /* load disable cmd */
addi r4, r4, LO (CACHE_CMD_DISABLE)
mtspr IC_CST, r4 /* disable I cache */
mtspr DC_CST, r4 /* disable D cache */
lis r4, HIADJ ( CACHE_CMD_UNLOCK_ALL) /* load unlock cmd */
addi r4, r4, LO (CACHE_CMD_UNLOCK_ALL)
mtspr IC_CST, r4 /* unlock all I cache lines */
mtspr DC_CST, r4 /* unlock all D cache lines */
lis r4, HIADJ (CACHE_CMD_INVALIDATE) /* load invalidate cmd*/
addi r4, r4, LO (CACHE_CMD_INVALIDATE)
mtspr IC_CST, r4 /* invalidate all I cache lines */
mtspr DC_CST, r4 /* invalidate all D cache lines */
/*
设置IMMR的值,IMMR寄存器的值很关键,知道了这个寄存器的值,再根据Memory Map中的偏移就可以知道所有的寄存器的值。
*/
lis r4, HIADJ( INTERNAL_MEM_MAP_ADDR)
addi r4, r4, LO(INTERNAL_MEM_MAP_ADDR)
mtspr IMMR, r4 /* initialize the IMMR register */
mfspr r4, IMMR /* read it back, to be sure */
rlwinm r4, r4, 0, 0, 15 /* only high 16 bits count */
/* 设置SYPCR 寄存器,关闭 system protection stuff */
xor r5, r5, r5
oris r5, r5, 0xFFFF
addi r5, r5, LO(SYPCR_VAL)
stw r5, SYPCR(0)(r4)
/* 下面是设置片选寄存器,MPC852的4GB存储空间可以由8组寄存器BRx和Orx决定,这里设置了CS0和CS1的值 */
lis r5, HIADJ(BR0_VAL) /* BR0, OR0 */
addi r5, r5, LO(BR0_VAL)
stw r5, BR0(0)(r4)
lis r5, HIADJ(OR0_VAL)
addi r5, r5, LO(OR0_VAL)
stw r5, OR0(0)(r4)
/* For Flash */
lis r5, HIADJ(BR1_VAL) /* BR1, OR1 */
addi r5, r5, LO(BR1_VAL)
stw r5, BR1(0)(r4)
lis r5, HIADJ(OR1_VAL)
addi r5, r5, LO(OR1_VAL)
stw r5, OR1(0)(r4)
代码太多了,估计要写个3,4天,今天就写到这,明天继续。