PowerPC VxWorks BSP分析(4.3)——BSP定製

?

1.1 源碼剖析

處理器首先跳到ROM的入口地址,設置狀態字並創建一個啞堆棧(dummy stack) 。下面是PPC860的romInit示例:

/* internals */

FUNC_EXPORT(_romInit) /* start of system code */

FUNC_EXPORT(romInit) /* start of system code */

.globl FUNC(sdata) /* start of data */

.globl _sdata

#ifdef INCLUDE_QUICK_BOOT

/* lch 2005-3-25 13:24 Add these two functions to speed up booting */

.globl fillLongs

.globl copyLongs

#endif /*INCLUDE_QUICK_BOOT*/

/* externals */

.extern romStart /* system initialization routine */

_sdata:

FUNC_LABEL(sdata)

.asciz "start of data"

.balign 4

_WRS_TEXT_SEG_START

/******************************************************************************

*

* romInit - entry point for VxWorks in ROM

*

* romInit

* (

* int startType /@ only used by 2nd entry point @/

* )

*/

FUNC_BEGIN(_romInit)

FUNC_BEGIN(romInit)

bl cold /* jump to the cold boot initialization */

bl start /* jump to the warm boot initialization */

/* copyright notice appears at beginning of ROM (in TEXT segment) */

.ascii "Copyright 1984-2003 Wind River Systems, Inc."

.balign _PPC_TEXT_SEG_ALIGN

cold:

li r3, BOOT_COLD /* set cold boot as start type */

/*

* When the PowerPC 860 is powered on, the processor fletch the

* instructions located at the address 0x100. We need to jump

* from the address 0x100 to the Flash space.

*/

/* SYPCR - turn off the system protection stuff */

mfspr r4, IMMR /* read it back, to be sure */

rlwinm r4, r4, 0, 0, 15 /* only high 16 bits count */

lis r5, HIADJ(0xFFFFFF88) /* Disable watchdog */

addi r5, r5, LO(0xffffff88) /* Disable watchdog */

stw r5, SYPCR(0)(r4)

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 */

/*MPC860內部的CS0片選信號是默認的系統啓動片選信號,已被連接到Flash的片選線上。上電時,內存控制器會忽略所有參與徵選邏輯的地址線的高17位,CS0總是有效。這樣,Flash總會被選中,CPU從Flash偏移0x100的地方取指令,此時CPU的4GB內存空間的每個128KB的塊都被映射到Flash。*/

start:

xor r4, r4, r4 /* clear register R4 */

/* set the MSR register to a known state */

mtmsr r4 /* cleat the MSR register */

/* DER - clear the Debug Enable Register */

mtspr DER, r4

/* ICR - clear the Interrupt Cause Register */

mtspr ICR, r4

/* ICTRL - initialize the Intstruction Support Control register */

lis r5, HIADJ(0x00000007)

addi r5, r5, LO(0x00000007)

mtspr ICTRL, r5

/* disable the instruction/data 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 */

/* unlock the instruction/data 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 */

/* invalidate the instruction/data cache */

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 */

/*

* initialize the IMMR register before any non-core registers

* modification.

*/

IMMR指示特殊設備和內部存儲器映像的基地址,這是一個32位的寄存器,其中0~15bit爲基地址的值(ISB),根據系統復位時配置字的值來定。

/* INTERNAL_MEM_MAP_ADDR =0x02b00000,defined in ads860.h. noted by dgs*/

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 */

/*XXXXX lch config Port C 6 to output high*/

xor r5, r5, r5

sth r5, PCPAR(0)(r4)

xor r5, r5, r5

sth r5, PCSO(0)(r4)

lis r5, HIADJ( PCDIR_VALUE)

addi r5, r5, LO(PCDIR_VALUE)

sth r5, PCDIR(0)(r4)

lis r5, HIADJ( PCDAT_VALUE)

addi r5, r5, LO(PCDAT_VALUE)

sth r5, PCDAT(0)(r4)

/*

* Map the bank 0 to the flash area - On the ADS board at reset time

* the bank 0 is already used to map the flash.

*/

/*上電時,由於只有一個片選信號有效,它選通了 Flash,而RAM和其它存儲設備地址無效,需要經過地址空間重映射才能訪問。MPC860的地址空間重映射是通過設置0R0~OR7、BR0~BR7 這十六個寄存器完成的。由於上電時4GB的地址空間均被Flash佔用,所以0xFFF00100這個地址仍在Flash的偏移0x100處。在寄存器初始化過程中,需要把SDRAM、MPC860內部寄存器空間以及外設等也映射進來。在進行這些操作前,需要把Flash的位置固定下來,例如映射到 0xFE000000,這個操作是通過設置OR0和BR0寄存器實現的。但在寫OR0時,CPU仍然在0xFFF00000的那一塊取指令,而Flash 即將被映射到0xFE000000塊,所以程序必定出現“跑飛”的現象,必須對程序計數器(PC)進行調整,然而PC指針對程序員是不可見的,必須用跳轉指令修改它。在Flash地址映射完成後,通過設置OR1~OR7、BR1~BR7可以完成對所有存儲器空間的映射,各種存儲設備可映射在CPU地址空間 中的任意位置,但相互之間不能衝突。*/

基寄存器(BR0-BR7)包含了基地址和地址類型,以及存儲器屬性和處理存儲器操作選擇的模塊(machine)。

/*CS0 : bootrom(sst39vf040,512k*8)

* Base - 0xFE000000

* Width - 8Bit

* Size - 0x80000 (512KB)

*/

lis r5, HIADJ( (ROM_BASE_ADRS & BR_BA_MSK) | BR_V | BR_PS_8)

addi r5, r5, LO((ROM_BASE_ADRS & BR_BA_MSK) | BR_V | BR_PS_8)

stw r5, BR0(0)(r4)

lis r5, HIADJ( 0xFFF80000 | OR_CSNT_SAM | OR_BI | OR_SCY_4_CLK )

addi r5, r5, LO( 0xFFF80000 | OR_CSNT_SAM | OR_BI | OR_SCY_4_CLK )

stw r5, OR0(0)(r4)

/* CS1 - FLASH */

lis r5, HIADJ (CS1_FLASH_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK| OR_ACS_DIV2)

addi r5, r5, LO (CS1_FLASH_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK | OR_ACS_DIV2)

stw r5, OR1(0)(r4)

lis r5, HIADJ (CS1_FLASH_BASE | BR_MS_GPCM | CS1_FLASH_WIDTH | BR_V)

addi r5, r5, LO (CS1_FLASH_BASE | BR_MS_GPCM | CS1_FLASH_WIDTH | BR_V)

stw r5, BR1(0)(r4)

/* CS2 - SDRAM */

/* CS3 */

lis r5, HIADJ (CS3_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_6_CLK | OR_ACS_DIV4)

addi r5, r5, LO (CS3_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_6_CLK |OR_ACS_DIV4)

stw r5, OR3(0)(r4)

lis r5, HIADJ (CS3_CHIP_BASE | BR_MS_GPCM | CS3_CHIP_WIDTH | BR_V)

addi r5, r5, LO (CS3_CHIP_BASE | BR_MS_GPCM | CS3_CHIP_WIDTH | BR_V)

stw r5, BR3(0)(r4)

/* CS4 */

lis r5, HIADJ (CS4_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_3_CLK | OR_ACS_DIV4 | OR_TRLX )

addi r5, r5, LO (CS4_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_3_CLK| OR_ACS_DIV4 |OR_TRLX)

stw r5, OR4(0)(r4)

lis r5, HIADJ (CS4_CHIP_BASE | BR_MS_GPCM | CS4_CHIP_WIDTH | BR_V)

addi r5, r5, LO (CS4_CHIP_BASE | BR_MS_GPCM | CS4_CHIP_WIDTH | BR_V)

stw r5, BR4(0)(r4)

/* CS5 */

lis r5, HIADJ (CS5_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK| OR_ACS_DIV2)

addi r5, r5, LO (CS5_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK| OR_ACS_DIV2)

stw r5, OR5(0)(r4)

lis r5, HIADJ (CS5_CHIP_BASE | BR_MS_GPCM | CS5_CHIP_WIDTH | BR_V)

addi r5, r5, LO (CS5_CHIP_BASE | BR_MS_GPCM | CS5_CHIP_WIDTH | BR_V)

stw r5, BR5(0)(r4)

/* CS6 */

lis r5, HIADJ (CS6_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK| OR_ACS_DIV2)

addi r5, r5, LO (CS6_CHIP_MASK | OR_CSNT_SAM | OR_BI | OR_SCY_15_CLK| OR_ACS_DIV2)

stw r5, OR6(0)(r4)

lis r5, HIADJ (CS6_CHIP_BASE | BR_MS_GPCM | CS6_CHIP_WIDTH | BR_V)

addi r5, r5, LO (CS6_CHIP_BASE | BR_MS_GPCM | CS6_CHIP_WIDTH | BR_V)

stw r5, BR6(0)(r4)

/* SYPCR - turn off the system protection stuff */

lis r5, HIADJ( SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF)

addi r5, r5, LO(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF)

stw r5, SYPCR(0)(r4)

/* SPR 65678 - Lock the Key Registers (they protect the register

* values from corruption on power cycle. See MCG's EWT # 867 for

* the symptoms and outcome of corrupted registers.

*

* r4 holds the address of the IMMR

*

* xxK registers are locked by writing any value other than 0x55CCAA33

* to the register, or by reading the register. They are unlocked

* by writing 0x55CCAA33 to the register. After locking, any write

* access to the locked SIU register will cause a MCE. (in one case,

* not an MCE but a software emulation exception. See the MPC860

* user's manual, section 11 page 11 ff.)

*/

#ifdef USE_KEYED_REGS

/* pre-loading r7 with '~KEYED_REG_UNLOCK_VALUE' (ie, 'lock it')

* pre-loading r8 with ' KEYED_REG_UNLOCK_VALUE' (ie, 'unlock it')

***/

lis r7, HIADJ( ~KEYED_REG_UNLOCK_VALUE )

addi r7, r7, LO( ~KEYED_REG_UNLOCK_VALUE )

lis r8, HIADJ( KEYED_REG_UNLOCK_VALUE )

addi r8, r8, LO( KEYED_REG_UNLOCK_VALUE )

#else

/* pre-loading r7 with ' KEYED_REG_UNLOCK_VALUE' (ie, 'unlock it') */

lis r7, HIADJ( KEYED_REG_UNLOCK_VALUE )

addi r7, r7, LO( KEYED_REG_UNLOCK_VALUE )

#endif

stw r7, TBSCRK(0)(r4)

stw r7, TBREFF0K(0)(r4)

stw r7, TBREFF1K(0)(r4)

stw r7, TBK(0)(r4)

stw r7, RTCSCK(0)(r4)

stw r7, RTCK(0)(r4)

stw r7, RTSECK(0)(r4)

stw r7, RTCALK(0)(r4)

stw r7, PISCRK(0)(r4)

stw r7, PITCK(0)(r4)

stw r7, SCCRK(0)(r4)

stw r7, PLPRCRK(0)(r4)

stw r7, RSRK(0)(r4)

isync

/* TBSCR - initialize the Time Base Status and Control register */

#ifdef USE_KEYED_REGS

stw r8, TBSCRK(0)(r4) /* others are TBREFF0K, TBREFF1K and TBK */

isync

#endif

lis r5, HIADJ( TBSCR_REFA | TBSCR_REFB)

addi r5, r5, LO(TBSCR_REFA | TBSCR_REFB)

sth r5, TBSCR(0)(r4)

#ifdef USE_KEYED_REGS

stw r7, TBSCRK(0)(r4)

#endif

#ifdef USE_KEYED_REGS

stw r8, PISCRK(0)(r4) /* others are TBREFF0K, TBREFF1K and TBK */

isync

#endif

/* set PIT status and control init value */

li r5, PISCR_PS | PISCR_PITF

sth r5, PISCR(0)(r4)

#ifdef USE_KEYED_REGS

stw r7, PISCRK(0)(r4)

#endif

/* set the SPLL frequency */

lis r5, HIADJ(PLPRCR_VAL)

addi r5, r5, LO(PLPRCR_VAL)

#ifdef USE_KEYED_REGS

stw r8, PLPRCRK(0)(r4) /* others are TBREFF0K, TBREFF1K and TBK */

isync

#endif

/*

* For Errata MPC860 SIU9

* Delay to stop bus access while bus stablises after write to this register

* Set delay to the longest bus access possible for your setup

* Can cause reset if delay isn't long enough

* Note cache not enabled at this point

*/

nop

nop

isync

stw r5, PLPRCR(0)(r4)

isync

divw r5, r4, r4 /* waste time (r4 != 0) */

divw r5, r4, r5 /* 13 clocks */

nop

nop

isync

#ifdef USE_KEYED_REGS

stw r7, PLPRCRK(0)(r4)

#endif

/* SIUMCR */

/*modified by dgs for using irq4*/

lis r6, HIADJ(SIUMCR_FRC)

addi r6, r6, LO(SIUMCR_FRC)

lwz r5, SIUMCR(0)(r4)

or r5, r5, r6

stw r5, SIUMCR(0)(r4)

divw r5, r4, r4 /* waste time (r4 != 0) */

divw r5, r4, r5 /* 13 clocks */

nop

nop

isync

/*new add by dgs for compare with zl_bsp*/

lis r5, HIADJ (0xff800000) /* Clear memory status register */

addi r5, r5,LO (0xff800000)

stw r5, MSTAT(0)(r4)

/*new add end*/

/*

* we program the MPTPR with the largest allowed divider

* and the PTA value accordingly. So here we figure out the

* correct value for the PTA field.

*/

li r6, MPTPR_PTP_DIV64

lis r11, HIADJ ((REFRESH_VALUE / 64) <&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 64) &lt;&lt; MAMR_PTA_SHIFT)

cmpwi r11,0

bne mptprInit

/* try with the divider by 32 */

li r6, MPTPR_PTP_DIV32

lis r11, HIADJ ((REFRESH_VALUE / 32) &lt;&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 32) &lt;&lt; MAMR_PTA_SHIFT)

cmpwi r11,0

bne mptprInit

/* try with the divider by 16 */

li r6, MPTPR_PTP_DIV16

lis r11, HIADJ ((REFRESH_VALUE / 16) &lt;&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 16) &lt;&lt; MAMR_PTA_SHIFT)

cmpwi r11,0

bne mptprInit

/* try with the divider by 8 */

li r6, MPTPR_PTP_DIV8

lis r11, HIADJ ((REFRESH_VALUE / 8) &lt;&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 8) &lt;&lt; MAMR_PTA_SHIFT)

cmpwi r11,0

bne mptprInit

/* try with the divider by 4 */

li r6, MPTPR_PTP_DIV4

lis r11, HIADJ ((REFRESH_VALUE / 4) &lt;&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 4) &lt;&lt; MAMR_PTA_SHIFT)

cmpwi r11,0

bne mptprInit

/* it has to be the divide by 2 */

li r6, MPTPR_PTP_DIV2

lis r11, HIADJ ((REFRESH_VALUE / 2) &lt;&lt; MAMR_PTA_SHIFT)

addi r11, r11, LO ((REFRESH_VALUE / 2) &lt;&lt; MAMR_PTA_SHIFT)

mptprInit:

/* program the MPTPR */

sth r6, MPTPR(0)(r4)

/*

* initialize MxMR but don't enable refresh until after

* SDRAM initialization.

*/

lis r6, HIADJ (MAMR_DEFAULT_VALUE)

addi r6, r6, LO (MAMR_DEFAULT_VALUE)

or r6, r6, r11

stw r6, MAMR(0)(r4)

/*del by dgs for compare with zl_bsp

lis r6, HIADJ (MBMR_DEFAULT_VALUE)

end del by dgs */

upmaInit: /* 初始化內存控制器(UPM) */

/*

* load r6/r7 with the start/end address of the UPM table for an

* SDRAM @ 50MHZ.

*/

lis r6, HIADJ( upmaTableSdram)

addi r6, r6, LO(upmaTableSdram)

lis r7, HIADJ( upmaTableSdramEnd)

addi r7, r7, LO(upmaTableSdramEnd)

/* init UPMA for memory access */

sub r5, r7, r6 /* compute table size */

srawi r5, r5, 2 /* in integer size */

/* convert UpmTable to ROM based addressing */

lis r7, HIADJ(romInit)

addi r7, r7, LO(romInit)

lis r8, HIADJ(ROM_TEXT_ADRS)

addi r8, r8, LO(ROM_TEXT_ADRS)

sub r6, r6, r7 /* subtract romInit base address */

add r6, r6, r8 /* add in ROM_TEXT_ADRS address */

lis r9, HIADJ (MCR_OP_WRITE | MCR_UM_UPMA | MCR_MB_CS0)

addi r9, r9, LO(MCR_OP_WRITE | MCR_UM_UPMA | MCR_MB_CS0)

UpmaWriteLoop:

/* write the UPM table in the UPM */

lwz r10, 0(r6) /* get data from table */

stw r10, MDR(0)(r4) /* store the data to MD register */

stw r9, MCR(0)(r4) /* issue command to MCR register */

addi r6, r6, 4 /* next entry in the table */

addi r9, r9, 1 /* next MAD address */

addi r5,r5,-1

cmpwi r5,0

bne UpmaWriteLoop

/*

* Configure the 32 bit address to be output on the address bus

* if AMX = 0xb11.

* See section 16.6.4.1 "RAM Words". The following values must

* be placed on the defined SDRAM address pins:

* A[9] = 0 burst write mode

* A[6:4] = 010 cas latency of two

* A[3] = 0 sequential mode

* A[2:0] = 010 burst length 4

*

* The address must be shifted left by 2 bits for 32 bit wide SDRAM...

* (0b0100010 &lt;&lt; 2) = 0x88

*/

lis r5, HIADJ(LOCAL_MEM_LOCAL_ADRS | 0x88)

addi r5, r5, LO(LOCAL_MEM_LOCAL_ADRS | 0x88)

stw r5, MAR(0)(r4)

/*

* Issue precharge command (PRCG) and wait the precharge time (t-rp).

* Run precharge pattern from UPMB location 5.

*/

lis r5, HIADJ(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_1X | 0x5)

addi r5, r5, LO(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_1X | 0x5)

stw r5, MCR(0)(r4)

/* run refresh pattern 8 times */

lis r5, HIADJ(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_8X | 0x30)

addi r5, r5, LO(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_8X | 0x30)

stw r5, MCR(0)(r4)

/*

* issue a mode register set (MRS) to initialize the SDRAM mode

* register. This programs the burst length, CAS latency and

* write mode. Run MRS pattern from UPMB location 6.

*/

lis r5, HIADJ(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_1X | 0x6)

addi r5, r5, LO(MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS2 | \

MCR_MCLF_1X | 0x6)

stw r5, MCR(0)(r4)

/* program OR2 and BR2 for 64/32 Mbytes SDRAM Memory Array */

lis r5, HIADJ ((~(SDRAM_SIZE - 1)) | OR_CSNT_SAM)

addi r5, r5, LO ((~(SDRAM_SIZE - 1)) | OR_CSNT_SAM)

stw r5, OR2(0)(r4) /* set OR2 to the previously computed value */

lis r5, HIADJ ((LOCAL_MEM_LOCAL_ADRS & BR_BA_MSK) | BR_MS_UPMA \

| BR_V)

addi r5, r5, LO ((LOCAL_MEM_LOCAL_ADRS & BR_BA_MSK) | BR_MS_UPMA \

| BR_V)

stw r5, BR2(0)(r4)

/* enable SDRAM refresh cycles */

lis r5, HIADJ (MAMR_DEFAULT_VALUE | MAMR_PTAE)

addi r5, r5,LO (MAMR_DEFAULT_VALUE | MAMR_PTAE)

add r5, r5, r11

stw r5, MAMR(0)(r4)

/* initialize the stack pointer */

lis sp, HIADJ(STACK_ADRS)

addi sp, sp, LO(STACK_ADRS)

/* initialize r2 and r13 according to EABI standard */

#if FALSE /* SDA Not supported yet */

lis r2, HIADJ(_SDA2_BASE_)

addi r2, r2, LO(_SDA2_BASE_)

lis r13, HIADJ(_SDA_BASE_)

addi r13, r13, LO(_SDA_BASE_)

#endif

/* go to C entry point */

addi sp, sp, -FRAMEBASESZ /* get frame stack */

/*

* calculate C entry point: routine - entry point + ROM base

* routine = romStart

* entry point = romInit = R7

* ROM base = ROM_TEXT_ADRS = R8

* C entry point: romStart - R7 + R8

*/

lis r6, HIADJ(romStart)

addi r6, r6, LO(romStart) /* load R6 with C entry point */

sub r6, r6, r7 /* routine - entry point */

add r6, r6, r8 /* + ROM base */

mtlr r6 /* move C entry point to LR */

blr /* jump to the C entry point */

FUNC_END(_romInit)

FUNC_END(romInit)

/* This 50 MHz SDRAM table is for...

* 860EN Rev B.1 9829 and newer silicon

* 860T Rev B.3 9832 and newer silicon

*

* This table will NOT work with older 860EN or 860T parts.

*/

upmaTableSdram:

/* single read (offset 0x00 in upm ram) */

.long 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBEEC00

.long 0x1FFDDC47, 0x1FFDDF35, 0xEFEEAF34, 0x1FBD5F35

/* burst read (offset 0x08 in upm ram) */

.long 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00

.long 0xF0AFFC00, 0xF1AFFC00, 0xEFBEEC00, 0x1FFDDC47

.long 0x00FFF000, 0x11FFF447, 0xFFFFFC47, 0xFFFFFC04

.long 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0x1F2DFC04

/* single write (offset 0x18 in upm ram) */

.long 0x1F2DFC04, 0xEEAFAC00, 0x01BE4C04, 0x1FFDDC47

.long 0x00AF0004, 0x1FFDD447, 0xFFFFFC44, 0x1F0DFC04

/* burst write (offset 0x20 in upm ram) */

.long 0x1F0DFC04, 0xEEAFAC00, 0x10AF5C00, 0xF0AFFC00

.long 0xF0AFFC00, 0xE1BEEC04, 0x1FFDDC47, 0x00FFF004

.long 0x11FFF447, 0xFFFFFC47, 0xFFFFFC04, 0xFFFFFC04

.long 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0x1FFD7C84

/* refresh (offset 0x30 in upm ram) */

.long 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04

.long 0xFFFFFC84, 0xFFFFFC07, 0xFFFFFC04, 0xFFFFFC04

.long 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0x7FFFFC07

/* exception (offset 0x3C in upm ram) */

.long 0x7FFFFC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF

upmaTableSdramEnd:

#ifdef INCLUDE_QUICK_BOOT

/* lch 2005-3-25 13:24 Add these two functions to speed up booting */

/*******************************************************************************

*

* fillLongs - fill a buffer with a value a long at a time

*

* This routine fills the first &lt;nlongs> longs of the buffer with <val>.

*

* LOCAL void fillLongs (buf, nlongs, val)

* UINT *buf; pointer to buffer

* UINT nlongs; number of longs to fill

* UINT val; char with which to fill buffer

*/

fillLongs:

cmpwi r4, 0

beqlr

mtctr r4

subi r3, r3, 4

flsCont:

stwu r5, 4(r3)

bdnz flsCont

blr

/*******************************************************************************

*

* copyLongs - copy one buffer to another a long at a time

*

* This routine copies the first <nlongs> longs from <source> to <destination>.

*

* LOCAL void copyLongs (source, destination, nlongs)

* UINT *source; pointer to source buffer

* UINT *destination; pointer to destination buffer

* UINT nlongs; number of longs to copy

*/

copyLongs:

cmpwi r5, 0

beqlr

cmpw r3, r4

beqlr

li r6, 0

bgt sourceGreat

slwi r11, r5, 2

add r3, r3, r11

add r4, r4, r11

b sourceLess

sourceGreat:

subi r3, r3, 4

subi r4, r4, 4

mtctr r5

sourceGreatCont:

lwzu r7, 4(r3)

stwu r7, 4(r4)

bdnz sourceGreatCont

mr. r5, r6

beqlr

sourceLess:

mtctr r5

sourceLessCont:

lwzu r7, -4(r3)

stwu r7, -4(r4)

bdnz sourceLessCont

mr. r5, r6

beqlr

#endif /*INCLUDE_QUICK_BOOT*/

上述程序中romInit()函數做的工作有:

? 將相關寄存器清零和置位;

? 屏蔽中斷;

? 關閉數據、指令Cache;

? 初始化內存:對SDRAM接口各寄存器進行配置;

? 初始化堆棧指針;

? 計算romStart()函數地址,然後跳轉到該函數執行C語言代碼,並不再返回。

romInit()函數應該以浮動代碼代碼的形式存在。浮動代碼(Position Independent Code,位置無關代碼,簡稱PIC)使用的轉移指令都是相對於當前程序計數器(PC)的偏移量;代碼中引用變量、函數的地址都是相對於某個基地址的偏移量。總之,從不引用一個絕對地址,這樣,無論程序被加載到什麼地址空間,不用修補代碼就可以正常工作。

跳到C程序的入口地址romStart後,該函數根據啞堆棧中的參數決定是否清零內存RAM(若是冷啓動則清零),再把ROM段的剩餘部分拷貝到RAM,拷貝的過程如下:

(1)代碼段不是駐留在ROM中,要拷貝代碼段和數據段;

(2)如代碼段是駐留在ROM中,則只拷貝數據段;

(3)未用的內存清零;

(4)如果ROM代碼是壓縮的,要進行解壓縮。

下面是從romStart()函數中提取的骨幹:

/* bootInit.c - ROM initialization module */

void romStart(FAST int startType /* start type */)

{

volatile FUNCPTR absEntry;

/* 從ROM複製到RAM */

#ifdef ROM_RESIDENT

/* ROM駐留的VxWorks,只COPY數據段 */

copyLongs((UINT*)etext, (UINT*)RESIDENT_DATA, ((UINT)wrs_kernel_data_end -

(UINT)RESIDENT_DATA) / sizeof(long));

#else /* RAM中運行 */

#ifdef UNCOMPRESS /*未壓縮的,複製TEXT、DATA段*/

((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS, (UINT)romInit,

ROM_COPY_SIZE / sizeof(long));

#else /*壓縮的,複製非壓縮型區域*/

((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS, (UINT)romInit,

((UINT) binArrayStart - (UINT)romInit) / sizeof(long));

((FUNCPTR)ROM_OFFSET(copyLongs))((UINT*)((UINT)ROM_TEXT_ADRS +

((UINT)BINARRAYEND_ROUNDOFF - (UINT)romInit)),

(UINT*)BINARRAYEND_ROUNDOFF,

( (UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof(long));

#endif /* UNCOMPRESS */

#endif /* ROM_RESIDENT */

/* 清內存 */

#if (!defined (BOOTCODE_IN_RAM))

/* 冷啓動,清楚所有內存 */

if (startType &BOOT_CLEAR)

{

#ifdef ROM_RESIDENT

fillLongs((UINT*)SYS_MEM_BOTTOM, ((UINT)RESIDENT_DATA - STACK_SAVE -

(UINT)SYS_MEM_BOTTOM) / sizeof(long), 0);

fillLongs(((UINT*)wrs_kernel_data_end), ((UINT)SYS_MEM_TOP - ((UINT)

wrs_kernel_data_end)) / sizeof(long), 0);

#else /* ROM_RESIDENT */

fillLongs((UINT*)(SYS_MEM_BOTTOM), ((UINT)romInit - STACK_SAVE –

(UINT)SYS_MEM_BOTTOM) / sizeof(long), 0);

#if defined (UNCOMPRESS)

fillLongs((UINT*)((UINT)romInit + ROM_COPY_SIZE),

((UINT)SYS_MEM_TOP

- ((UINT)romInit + ROM_COPY_SIZE)) / sizeof(long), 0);

#else

fillLongs((UINT*)wrs_kernel_data_end, ((UINT)SYS_MEM_TOP - (UINT)

wrs_kernel_data_end) / sizeof(long), 0);

#endif /* UNCOMPRESS */

#endif /* ROM_RESIDENT */

/* 確保啓動行爲空 */

*(BOOT_LINE_ADRS) = EOS;

}

#endif

/* 跳到usrInit()*/

#if defined (UNCOMPRESS) || defined (ROM_RESIDENT)

absEntry = (FUNCPTR)usrInit; /* on to bootConfig */

#else

{

/* 解壓縮到RAM_DST_ADRS */

if (UNCMP_RTN((UCHAR*)ROM_OFFSET(binArrayStart),

(UCHAR*)RAM_DST_ADRS, binArrayEnd - binArrayStart) != OK)

return ; /* if we return then ROM's will halt */

absEntry = (FUNCPTR)RAM_DST_ADRS; /* RAM入口點 */

}

#endif /* defined UNCOMPRESS || defined ROM_RESIDENT */

(absEntry)(startType);

}

romStart()函數會調用預內核的通用初始化函數usrInit(),位於usrConfig.C或bootConfig.C中。romStart關中斷,存儲有關啓動類型(boot type)的信息,在VxWorks內核運行前進行必要的初始化。

(1)初始化cache模式,設置爲安全狀態,在usrInit()結束時使cache有效;

(2)清零系統bss段;

(3)初始化中斷向量表,調用VectBaseSet(),exeVecInit();

(4)初始化系統硬件,但使之進入“Quiescent”狀態,調用sysHwInit(),這是一個與硬件有關的過程,是我們要針對不同的目標板進行修改的重要部分,其中涉及到串口,網口的初始化,CONSOLE的配置等;

(5)調用usrKernelInit(),並使能cache;

(6)調用kernelInit(),創建usrRoot()。

usrConfig.C中的usrInit()和bootConfig.C中的相似。bootConfig.C中的usrInit()流程如下:

void usrInit(int startType)

{

while (trapValue1 != TRAP_VALUE_1 || trapValue2 != TRAP_VALUE_2)

{

/* infinite loop */;

}

#ifdef INCLUDE_SYS_HW_INIT_0

SYS_HW_INIT_0();

#endif /* INCLUDE_SYS_HW_INIT_0 */

/* configure data and instruction cache if available and leave disabled */

#ifdef INCLUDE_CACHE_SUPPORT

/*

* SPR 73609: If a cache is not to be enabled, don't require

* its mode to be defined. Instead, default it to disabled.

*/

#if (!defined(USER_D_CACHE_ENABLE) && !defined(USER_D_CACHE_MODE))

#define USER_D_CACHE_MODE CACHE_DISABLED

#endif /* !USER_D_CACHE_ENABLE && !USER_D_CACHE_MODE */

#if (!defined(USER_I_CACHE_ENABLE) && !defined(USER_I_CACHE_MODE))

#define USER_I_CACHE_MODE CACHE_DISABLED

#endif /* !USER_I_CACHE_ENABLE && !USER_I_CACHE_MODE */

cacheLibInit(USER_I_CACHE_MODE, USER_D_CACHE_MODE);

#endif /* INCLUDE_CACHE_SUPPORT */

/* don't assume bss variables are zero before this call */

bzero(edata, end - edata); /* zero out bss variables */

sysStartType = startType;

intVecBaseSet((FUNCPTR*)VEC_BASE_ADRS); /* set vector base table */

excVecInit(); /* install exception vectors */

sysHwInit(); /* initialize system hardware */

usrKernelInit(); /* configure the Wind kernel */

#ifdef INCLUDE_CACHE_SUPPORT

#ifdef USER_I_CACHE_ENABLE

cacheEnable(INSTRUCTION_CACHE); /* enable instruction cache */

#endif /* USER_I_CACHE_ENABLE */

#endif /* INCLUDE_CACHE_SUPPORT */

/* start the kernel specifying usrRoot as the root task */

kernelInit((FUNCPTR)usrRoot, ROOT_STACK_SIZE,

(char*)MEM_POOL_START_ADRS,

sysMemTop(), ISR_STACK_SIZE, INT_LOCK_LEVEL);

}

sysHwInit()定義於syslib.c中,大部分硬件初始化工作都在這部分完成。系統可將包括串口、網口等硬件設備的初始化入口程序添加到該函數中,相關設備的驅動程序可作爲子文件引入syslib.c。

usrKernelInit()初始化多任務環境,依次調用classLibInit(),taskLibInit(),taskHookInit(),semBLibInit(),semMLibInit(),semCLibInit(),semOLibInit(),wbLibInit(),msgQLibInit(),qInit(),workQInit()。

kernelInit()初始化內核可選組建(kernel facility)並啓動根任務。函數功能:

(1)激活intLockLevelSet()

(2)從內存池頂部創建堆棧和TCB

(3)調用taskInit(),taskActivate(),用於usrRoot()

(4)調用usrRoot()

usrRoot初始化I/O系統、驅動器、設備(在configAll.h和config.h中指定),並啓動其它任務。bootConfig.C中的usrRoot()流程如下:

/* 初始化和啓動boot command loop task */

void usrRoot(char *pMemPoolStart, /* start of system memory partition */

unsigned memPoolSize /* initial size of mem pool */)

{

char tyName[20];

int ix;

#ifdef INCLUDE_END

int count;

END_TBL_ENTRY *pDevTbl;

#endif /* INCLUDE_END */

/* 初始化內存池 */

memInit(pMemPoolStart, memPoolSize); /* XXX select between memPartLibInit */

/* 設置系統定時器 */

sysClkConnect((FUNCPTR)usrClock, 0); /* connect clock interrupt routine */

sysClkRateSet(SYS_CLK_RATE); /* set system clock rate */

sysClkEnable(); /* start it */

/* select library需要在tyLib模塊前初始化 */

#ifdef INCLUDE_SELECT

selectInit(NUM_FILES);

#endif /* INCLUDE_SELECT */

/* 初始化I/O和文件系統 */

iosInit(NUM_DRIVERS, NUM_FILES, "/null");

consoleFd = NONE;

/* 給板上設備安裝驅動 */

#ifdef INCLUDE_TYCODRV_5_2

#ifdef INCLUDE_TTY_DEV

if (NUM_TTY &gt; 0)

{

tyCoDrv(); /* install console driver */

for (ix = 0; ix < NUM_TTY; ix++)

/* create serial devices */

{

sprintf(tyName, "%s%d", "/tyCo/", ix);

(void)tyCoDevCreate(tyName, ix, 512, 512);

if (ix == CONSOLE_TTY)

strcpy(consoleName, tyName);

/* store console name */

}

consoleFd = open(consoleName, O_RDWR, 0);

/* set baud rate */

(void)ioctl(consoleFd, FIOBAUDRATE, CONSOLE_BAUD_RATE);

(void)ioctl(consoleFd, FIOSETOPTIONS, OPT_ECHO | OPT_CRMOD |

OPT_TANDEM | OPT_7_BIT);

}

#endif /* INCLUDE_TTY_DEV */

#else /* !INCLUDE_TYCODRV_5_2 */

#ifdef INCLUDE_TTY_DEV

if (NUM_TTY > 0)

{

ttyDrv(); /* install console driver */

for (ix = 0; ix < NUM_TTY; ix++)

/* create serial devices */

{

#if (defined(INCLUDE_WDB) && (WDB_COMM_TYPE ==

WDB_COMM_SERIAL))

if (ix == WDB_TTY_CHANNEL)

/* don't use WDBs channel */

continue;

#endif

sprintf(tyName, "%s%d", "/tyCo/", ix);

(void)ttyDevCreate(tyName, sysSerialChanGet(ix), 512, 512);

if (ix == CONSOLE_TTY)

/* init the tty console */

{

strcpy(consoleName, tyName);

consoleFd = open(consoleName, O_RDWR, 0);

(void)ioctl(consoleFd, FIOBAUDRATE, CONSOLE_BAUD_RATE);

(void)ioctl(consoleFd, FIOSETOPTIONS, OPT_ECHO | OPT_CRMOD |

OPT_TANDEM | OPT_7_BIT);

}

}

}

#endif /* INCLUDE_TTY_DEV */

#ifdef INCLUDE_PC_CONSOLE

pcConDrv();

for (ix = 0; ix &lt; N_VIRTUAL_CONSOLES; ix++)

{

sprintf(tyName, "%s%d", "/pcConsole/", ix);

(void)pcConDevCreate(tyName, ix, 512, 512);

if (ix == PC_CONSOLE)

/* init the console device */

{

strcpy(consoleName, tyName);

consoleFd = open(consoleName, O_RDWR, 0);

(void)ioctl(consoleFd, FIOBAUDRATE, CONSOLE_BAUD_RATE);

(void)ioctl(consoleFd, FIOSETOPTIONS, OPT_ECHO | OPT_CRMOD |

OPT_TANDEM | OPT_7_BIT);

}

}

#endif /* INCLUDE_PC_CONSOLE */

#endif /* !INCLUDE_TYCODRV_5_2 */

#ifdef INCLUDE_WDB

wdbConfig(); /* configure and initialize the WDB agent */

vxBootFile[0] = NULL; /* clear boot line set by wdbConfig() */

#if defined(INCLUDE_TSFS_BOOT) &&

defined(INCLUDE_TSFS_BOOT_VIO_CONSOLE)

consoleFd = open("/vio/0", O_RDWR, 0); /* for Target Server Console */

#endif

#endif /* INCLUDE_WDB */

ioGlobalStdSet(STD_IN, consoleFd);

ioGlobalStdSet(STD_OUT, consoleFd);

ioGlobalStdSet(STD_ERR, consoleFd);

pipeDrv(); /* install pipe driver */

#if defined(INCLUDE_EXC_HANDLING) && defined(INCLUDE_EXC_TASK)

#ifdef INCLUDE_EXC_SHOW

excShowInit(); /* init exception show routines */

#endif

excInit(); /* initialize exception handling */

#endif /* defined(INCLUDE_EXC_HANDLING) && defined(INCLUDE_EXC_TASK) */

excHookAdd((FUNCPTR)bootExcHandler); /* install exc handler */

logInit(consoleFd, 5); /* initialize logging */

#ifdef INCLUDE_DOSFS

hashLibInit(); /* hashLib used by dosFS */

#endif

/* initialize object module loader */

#if defined(INCLUDE_AOUT)

bootAoutInit(); /* use a.out format */

#else /* coff or ecoff */

#if defined(INCLUDE_ECOFF)

bootEcoffInit(); /* use ecoff format */

#else /* coff */

#if defined(INCLUDE_COFF)

bootCoffInit(); /* use coff format */

#else /* coff */

#if defined(INCLUDE_ELF)

bootElfInit(); /* use elf format */

#endif

#endif /* mips cpp no elif */

#endif

#endif

#ifdef INCLUDE_PCMCIA

pcmciaInit(); /* init PCMCIA Lib */

#endif /* INCLUDE_PCMCIA */

#ifdef INCLUDE_END

/* initialize the MUX */

muxMaxBinds = MUX_MAX_BINDS;

if (muxLibInit() == ERROR)

return ;

/* can't return ERROR */

/* Initialize all the available devices. */

for (count = 0, pDevTbl = endDevTbl; pDevTbl->endLoadFunc != END_TBL_END;

pDevTbl++, count++)

{

cookieTbl[count].pCookie = muxDevLoad(pDevTbl-&gt;unit, pDevTbl-&gt;endLoadFunc,

pDevTbl-&gt;endLoadString, pDevTbl-&gt;endLoan, pDevTbl-&gt;pBSP);

if (cookieTbl[count].pCookie == NULL)

{

printf("muxLoad failed!\n");

}

cookieTbl[count].unitNo = pDevTbl-&gt;unit;

bzero((void*)cookieTbl[count].devName, END_NAME_MAX);

pDevTbl-&gt;endLoadFunc((char*)cookieTbl[count].devName, NULL);

}

#endif /* INCLUDE_END */

taskSpawn("tBoot", bootCmdTaskPriority, bootCmdTaskOptions,

bootCmdTaskStackSize, (FUNCPTR)bootCmdLoop, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

}

最後啓動的“tBoot”任務,對應bootCmdLoop()函數的作用是:讀取和執行用戶的控制命令直到啓動。VxWorks的引導最終通過bootLoad()函數完成:

LOCAL STATUS bootLoad(char *bootString, FUNCPTR *pEntry)

{

BOOT_PARAMS params;

/* copy bootString to low mem address, if specified */

if ((bootString != NULL) && (*bootString != EOS))

strcpy(BOOT_LINE_ADRS, bootString);

/* interpret boot command */

if (usrBootLineCrack(BOOT_LINE_ADRS, &params) != OK)

return (ERROR);

/* Display boot parameters */

bootParamsShow(BOOT_LINE_ADRS);

/* set our processor number: may establish vme access, etc. */

sysFlags = params.flags;

sysProcNumSet(params.procNum);

#ifdef INCLUDE_SCSI_BOOT

if (strncmp(params.bootDev, "scsi", 4) == 0){…}

#endif /* INCLUDE_SCSI_BOOT */

#ifdef INCLUDE_FD

if (strncmp(params.bootDev, "fd", 2) == 0){…}

#endif /* INCLUDE_FD */

#ifdef INCLUDE_IDE

if (strncmp(params.bootDev, "ide", 3) == 0){…}

#endif /* INCLUDE_IDE */

#ifdef INCLUDE_ATA

if (strncmp(params.bootDev, "ata", 3) == 0){…}

#endif /* INCLUDE_ATA */

#ifndef INCLUDE_NETWORK

printf("\nError loading file: networking code not present.\n");

return (ERROR);

#else /* INCLUDE_NETWORK */

/* start the network */

/* initialize the generic socket library */

if (sockLibInit(NUM_FILES) == ERROR)

return (ERROR);

//...

#endif

}

跳到VxWorks入口點則是通過go()函數:

LOCAL void go(FUNCPTR entry)

{

printf("Starting at 0x%x...\n\n", (int)entry);

taskDelay(sysClkRateGet()); /* give the network a moment to close */

#ifdef INCLUDE_NETWORK

ifreset(); /* reset network to avoid interrupts */

#ifdef INCLUDE_END

/* Stop all ENDs to restore to known state for interrupts and DMA */

(void)muxDevStopAll(0);

#endif /* INCLUDE_END */

#endif /* INCLUDE_NETWORK */

#if (CPU_FAMILY == PPC)

cacheTextUpdate((void*)(LOCAL_MEM_LOCAL_ADRS), /* cache coherency */

(size_t)(sysMemTop() - LOCAL_MEM_LOCAL_ADRS));

#else

#ifdef INCLUDE_CACHE_SUPPORT

cacheClear(DATA_CACHE, NULL, ENTIRE_CACHE); /* push cache to mem */

#endif /* INCLUDE_CACHE_SUPPORT */

#endif /* (CPU_FAMILY == PPC) */

#if (CPU_FAMILY == I80X86)

sysClkDisable(); /* disable the system clock interrupt */

sysIntLock(); /* lock the used/owned interrupts */

#if defined (SYMMETRIC_IO_MODE) || defined (VIRTUAL_WIRE_MODE)

{

extern void loApicEnable();

loApicEnable(FALSE); /* disable the LOAPIC */

}

#if defined (SYMMETRIC_IO_MODE)

{

extern BOOL sysBp; /* TRUE for BP, FALSE for AP */

extern void ioApicEnable();

if (sysBp)

ioApicEnable(FALSE);

/* disable the IO APIC */

}

#endif /* (SYMMETRIC_IO_MODE) */

#endif /* (SYMMETRIC_IO_MODE) || (VIRTUAL_WIRE_MODE) */

#endif /* (CPU_FAMILY == I80X86) */

/* Lock interrupts before jumping out of boot image. The interrupts

* enabled during system initialization in sysHwInit()

*/

intLock();

(entry)(); /* go to entry point - never to return */

}

usrConfig.C中的usrRoot()流程和上面基本類似,不同於上述程序僅僅初始化必要的硬件和軟件模塊,usrConfig.C中的usrRoot()要初始化的東西非常多,所以代碼量大,而且最終進入的是應用程序:

#ifdef INCLUDE_USER_APPL

/* Startup the user's application */

USER_APPL_INIT; /* must be a valid C statement or block */

#endif

Loadable的VxWork映像入口點爲sysInit:

FUNC_LABEL(sysInit)

FUNC_BEGIN(_sysInit)

/*

* disable external interrupts and Instruction/Data MMU, set

* the exception prefix

*/

mfmsr p0 /* p0 = msr */

INT_MASK(p0, p1) /* mask EE bit */

rlwinm p1, p1, 0, _PPC_MSR_BIT_DR + 1, _PPC_MSR_BIT_IR - 1

rlwinm p1, p1, 0, _PPC_MSR_BIT_IP + 1, _PPC_MSR_BIT_IP - 1

mtmsr p1 /* msr = p1 */

isync /* ISYNC */

/* disable instruction and data caches */

lis p1, HIADJ ( CACHE_CMD_DISABLE) /* load disable cmd */

addi p1, p1, LO (CACHE_CMD_DISABLE)

mtspr IC_CST, p1 /* Disable I cache */

mtspr DC_CST, p1 /* Disable D cache */

/* unlock instruction and data caches */

lis p1, HIADJ ( CACHE_CMD_UNLOCK_ALL) /* load unlock cmd */

addi p1, p1, LO (CACHE_CMD_UNLOCK_ALL)

mtspr IC_CST, p1 /* Unlock I cache */

mtspr DC_CST, p1 /* Unlock D cache */

/* invalidate instruction and data caches */

lis p1, HIADJ ( CACHE_CMD_INVALIDATE) /* load invalidate cmd*/

addi p1, p1, LO (CACHE_CMD_INVALIDATE)

mtspr IC_CST, p1 /* Invalidate I cache */

mtspr DC_CST, p1 /* Invalidate D cache */

/* invalidate entries within both TLBs */

tlbia

/* initialize the stack pointer */

lis sp, HIADJ( RAM_LOW_ADRS)

addi sp, sp, LO(RAM_LOW_ADRS)

/* set the default boot code */

lis r3, HIADJ( BOOT_WARM_AUTOBOOT)

addi r3, r3, LO(BOOT_WARM_AUTOBOOT)

/* jump to usrInit */

addi sp, sp, -FRAMEBASESZ /* get frame stack */

b usrInit /* never returns - starts up kernel */

FUNC_END(_sysInit)

1.2 修改配置

configAll.h

缺省定義了所有VxWorks的設置,如果不用缺省的設置,可在BSP目錄下的config.h文件中用#define或#undef方式來更改設置;

config.h

config.h 文件包括了所有的特定CPU板的包含文件和定義。config.h 文件內容的標準組織如下:

(1)BSP 版本和修訂 ID 號碼;

(2)configAll.h (#included);

(3)內存cache 和MMU 配置;

(4)共享內存網絡定義;

(5)片上內存的地址和大小;

(6)ROM 地址和大小;

(7)NVRAM 參數;

(8)缺省啓動行(bootline)參數;

關於加載VxWorks影像文件,在啓動行(boot line)設置可以從硬盤,軟盤,網絡,串口,ppp等等。示例:

硬盤

"ata=0,0(0,0)host:/ata0/vxWorks h=90.0.0.3 e=90.0.0.50 u=target"

軟盤

"fd=0,0(0,0)host:/fd0/vxWorks h=90.0.0.3 e=90.0.0.50 u=target"

網絡

"fei=0,0(0,0)host:/fei00/vxWorks h=90.0.0.3 e=90.0.0.50 u=target"

從ATA啓動的解釋如下:

bootline :  ata=1,0(0,0)host:/ata1/vxWorks
| |
| |__drive(master or slave)
|
|__controller(0 refers to ata controller 0,1 refers to  ata controller 1)

下面看boot line結構:

bootDev(unitNum,procNum) hostname:bootFile e=ead b=bad h=had g=gad u=username pw=password f=flags tn=targetName s=startupScript o=other

bootDev // 設備名,軟盤:fd; 硬盤:ATA;網絡要根據網卡的類型來做:NE2000及其兼容網卡爲ENE,3COM以太網卡爲ELT,Intel網卡爲EEX,Intel82559網卡爲fei ,3C905B PCI網卡爲elPci。

unitNum / 設備單元號,一般指爲0

procnum / cpu的處理器號,一般爲0

flags / 標識,十六進制數,意義如下:

0x01: 關閉對處理器0的系統控制

0x02: 將局部symbols和全局symbols裝入目標機symbols表

0x04: 禁止自動啓動(即由用戶輸入boot line)

0x08: 快速boot(不計數等待用戶輸入)

0x40: 使用BOOTP or DHCP client

0x80: 使用TFTP獲取image,否則使用RSH或FTP,用FTP時pw不爲空

0x100: 使目標機登記爲一個代理ARP client

ead / 目標機ip地址,此值如爲空,網絡接口不被幫定

bad / 背板接口

had / 主機ip地址

gad / 網關地址,如果主機和目標機不在一個局域網裏,需要

bootFile: / 存放VxWorks image的路徑

usr: / 使用FTP或RSH時的用戶名

passwd: / ftp password

other: / 從網絡啓動時此值可爲空,當從軟盤或硬盤啓動時,如果此值爲你的網絡

設備,boot會爲你綁定網絡設備

hostname: / 主機名,任意

targetName:/目標機名

startupScript: / 腳本名,在boot以後的target shell裏執行

在boot line中,e,b,h等等參數都不要求次序,你也可以讓它爲空值,如”pw= ”就是指口令爲空參數,看一個例子:

ene(0,0) raisecom:c:/tornado/target/config/pc486/VxWorks e="10".132.3.40 h="10".132.3.37 u="x86" pw="apue" tn="rod"

在上例中,網卡爲NE2000及兼容網卡,主機名爲raisecom,VxWorks image存放在c:\tornado\target\config\pc486這個目錄下,目標機的網絡地址爲10.132.3.40,主機的網絡地址爲10.132.3.37,通過FTP服務器下載,用戶名爲x86,口令爲apue,目標機名爲rod

再看一個例子:

fd="0",0(0,0) lijun:/fd0/vxWorks e="10".132.3.40 h="10".132.3.37 u="x86" o="ene"

這個例子裏面,用的是軟盤啓動VxWorks,在軟盤做好boot後,還需要把VxWorks image拷入軟盤,在boot 起來以後,引導程序會在軟盤裏尋找VxWorks,並把它啓動。

軟盤用fd0表示,硬盤用ATA(0,0),最後的參數o="ene" 表示網絡設備是NE2000網卡,並將之和ip地址綁定。

(9)時間戳驅動支持;

(10)外部總線地址映射;

(11)網絡設備和中斷向量;

(12)bspname.h 文件 (#included)。

bspname.h

根據具體目標板設置串行接口、時鐘以及I/O設備等。在該文件中必須包含以下內容:

(1)中斷向量/級別;

(2)I/O設備地址;

(3)設備寄存器位的含義;

(4)系統和附加時鐘參數(最大和最小速率)。

configNet.h

網絡設備描述、配置。以下是網絡設備描述的一個例子,在系統中應該添加類似的描述到configNet.h 文件中。

#define MOT_FCC_LOAD_FUNC sysMotFccEndLoad

#define MOT_FCC_LOAD_STRING ""

IMPORT END_OBJ* MOT_FCC_LOAD_FUNC (char *, void*);

在每一個網絡設備的配置中,應該定義以上兩個常量,以下對着兩個常量進行說明:

LOAD_FUNC:

規定驅動endLoad()函數的入口點。例如,如果驅動的endLoad()入口點是sysMotFccEndLoad(),那麼編輯configNet.h 包括以下的定義:

#define MOT_FCC_LOAD_FUNC sysMotFccEndLoad

LOAD_STRING:

在網絡初始化過程中,作爲initString參數,傳遞給muxDevLoad( )的初始化參數。這個字符串也一併傳給endLoad()函數,它的內同取決於驅動的需要。

必須編輯endDevTbl()的定義(在configNet.h中規定包括在鏡像中的ENDS)從而包含被加載的每一個設備的入口。

例如:

END_TBL_ENTRY endDevTbl [] =

{

{ 0, LOAD_FUNC_0, LOAD_STRING_0, BSP_0, NULL, FALSE },

{ 1, LOAD_FUNC_1, LOAD_STRING_1, BSP_1, NULL, FALSE },

{ 0, END_TBL_END, NULL, 0, NULL, FALSE },

};

上面的第一個參數規定設備號。在最後的FALSE 表示入口還沒有被處理。在系統成功的加載驅動後,這個值變爲TRUE。如果想要禁止系統自動加載驅動,那麼可以把這個值設爲TRUE。

這樣,就準備好重新編譯VxWorks 從而包括新的END 驅動。當新編譯的VxWorks 啓動時,系統給在table 中每一個設備按照列出來的順序調用muxDevLoad()。

常見的一些配置宏定義如下:

? CPU:目標板的CPU

? TOOL:主機開發工具

? ROM_TEXT_ADRS:啓動ROM的16進制入口地址,多數目標板設置爲ROM的起始地址

? ROM_SIZE:ROM的16進制空間大小

? ROM_LOW_ADRS:VxWorks裝入的起始地址

? ROM_HIGH_ADRS:boot ROM拷貝到RAM的起始地址

? LOCAL_MEM_LOCAL_ADRS:目標板存儲空間的起始地址

? LOCAL_MEM_SIZE:固定(靜態)存儲器大小

? USER_RESERVED_MEM:保留內存大小

? RAM_HIGH_ADRS:拷貝boot ROM映像的目標地址

? ROM_BASE_ADRS:ROM起始地址

? ROM_TEXT_ADRS:boot ROM的入口地址,多數爲ROM空間的起始地址

? ROM_WARM_ADRS:熱啓動的入口地址

? ROM_SIZE:ROM空間的大小

其中ROM_TEXT_ADRS和ROM_SIZE的定義必須和Makefile一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章