http://blog.csdn.net/daniellee_ustb/article/details/9141867
学习vxworks的第一步当然是分析启动代码,vxworks有多种映像,无论哪种都要包括一段BootStrap的程序,我把它翻译为抽打型bootloader,意思是无论是操作系统还是引导程序都需要BootStrap进行加载,就像用鞭子抽打他们,他们才能执行起来一样。硬件上电时首先启动BootStrap,包括汇编级硬件初始化程序rominit.s,以及搬移程序bootinit.c.
下面注释下rominit.s是怎么启动的。
/* romInit.s - ARM Integrator ROMinitialization module */
/* modified by lyx for 2410CPU in 0609*/
/* Copyright 1999-2001 ARM Limited */
/* Copyright 1999-2001 Wind River Systems,Inc. */
/*
modification history
--------------------
01m,25jan02,m_h sdata needs "_" for bootrom_res
01l,09oct01,jpd added clock speed setting for 946ES.
01k,03oct01,jpd tidied slightly.
01j,28sep01,pr added support for ARM946ES.
01i,04jun01,rec memory clock rate changes for 740t
01h,21feb01,h_k added support for ARM966ES and ARM966ES_T.
01g,20nov00,jpd change speeds on 920T and add conditionalearly
enabling of I-cache on 920T.
01f,18sep00,rec Add delay during power up
01e,23feb00,jpd comments changes.
01d,22feb00,jpd changed copyright string.
01c,20jan00,jpd added support for ARM720T/ARM920T.
01b,13jan00,pr added support for ARM740T.
01a,30nov99,ajb created, based on PID version 01i.
*/
/*
DESCRIPTION
This module contains the entry code forVxWorks images that start
running from ROM, such as 'bootrom' and'vxWorks_rom'. The entry
point, romInit(), is the first codeexecuted on power-up. It performs
the minimal setup needed to call thegeneric C routine romStart() with
parameter BOOT_COLD.
romInit() masks interrupts in the processorand the interrupt
controller and sets the initial stackpointer (to STACK_ADRS which is
defined in configAll.h). Other hardware and device initialisation is
performed later in the sysHwInit routine insysLib.c.
The routine sysToMonitor() jumps to alocation after the beginning of
romInit, (defined by ROM_WARM_ADRS) toperform a "warm boot". This
entry point allows a parameter to be passedto romStart().
The routines in this module don't use the"C" frame pointer %r11@ ! or
establish a stack frame.
SEE ALSO:
.I "ARM Architecture ReferenceManual,"
.I "ARM 7TDMI Data Sheet,"
.
"ARM 720T Data Sheet,"
.I "ARM 740T Data Sheet,"
.I "ARM 920T Technical ReferenceManual",
.I "ARM 940T Technical ReferenceManual",
.I "ARM 946E-S Technical ReferenceManual",
.I "ARM 966E-S Technical ReferenceManual",
.I "ARM Reference PeripheralsSpecification,"
.I "ARM Integrator/AP UserGuide",
.I "ARM Integrator/CM7TDMI UserGuide",
.I "ARM Integrator/CM720T UserGuide",
.I "ARM Integrator/CM740T UserGuide",
.I "ARM Integrator/CM920T UserGuide",
.I "ARM Integrator/CM940T UserGuide",
.I "ARM Integrator/CM946E UserGuide",
.I "ARM Integrator/CM9x6ES Datasheet".
*/
#define _ASMLANGUAGE
#include "vxWorks.h"
#include "sysLib.h"
#include "asm.h"
#include "regs.h"
#include "config.h"
#include "arch/arm/mmuArmLib.h"
/* add by lyx for 2410 in 0609*/
/*头文件声明*/
#include "option.a"
#include "2410addr.s"
.data
.globl VAR(copyright_wind_river)
.long VAR(copyright_wind_river)
/* internals */
.globl FUNC(romInit) /* start of system code */
.globl VAR(sdata) /* start of data */
.globl _sdata
/* externals */
.extern FUNC(romStart) /* system initialization routine */
_sdata:
VAR_LABEL(sdata)
.asciz "start of data"
.balign 4
/* variables */
.data
.text
.balign4
/*******************************************************************************
*
* romInit - entry point for VxWorks in ROM
*
* romInit
* (
* int startType /@ only usedby 2nd entry point @/
* )
* INTERNAL
* sysToMonitor examines the ROM for thefirst instruction and the string
* "Copy" in the third word so ifthis changes, sysToMonitor must be updated.
*/
/*下一段代表了整个程序执行的流程,跳转到相应的函数*/
_ARM_FUNCTION(romInit)
_romInit:
B cold
B _romUndef
B _romSwi
B _romPrefetch
B _romDataAbort
B cold
B _romIRQ
B _romIRQ
//保存启动类型为BOOT_COLD
cold:
MOV r0, #BOOT_COLD /* fall through to warm boot entry */
//跳转到start处执行
warm:
B start
/*copyright notice appears at beginning of ROM (in TEXT segment) */
.ascii "Copyright 1999-2001 ARM Limited"
.ascii "\nCopyright 1999-2001 Wind RiverSystems, Inc."
.balign4
start:
/*
* There have been reports of problems withcertain boards and
* certain power supplies not coming up after apower-on reset,
* and adding a delay at the start of romInitappears to help
* with this.
*/
MOVR14,R0 // 暂存#BOOT_COLD
/*
* CPU INTERRUPTS DISABLED
*
* disable individual interrupts in theinterrupt controller
*/
ldrr1,=0x56000070 //PCONH // Load addresses to a register = ldr
//将地址0x56000070的一个int值读入r1
ldrr0,[r1] //将存储器地址为R1的字数据读入寄存器R0
bicr0,r0,#0x00000008 //将r0的第3位清0
orr r0,r0,#0X00000004 //将r0的第2位置1
str r0,[r1] //将r0的值写回地址0x56000070
//LDR Rd , addressing ;Rd←[addressing](load)
//STR Rd , addressing ;[addressing]←Rd (store)
ldrr1,=0x56000074 //PDATH //同样对地址0x56000074值的(1<<1)清0
ldrr0,[r1]
bicr0,r0,#0x0002 //PH1=0
str r0,[r1]
ldr r0,=WTCON @ watch dog disable //装载WTCON寄存器的值
ldr r1,=0x0 //装载0
str r1,[r0] //将0写入WTCON寄存器禁止看门狗
ldr r0,=INTMSK //禁止所有中断
ldr r1,=0xffffffff @ all interrupt disable
str r1,[r0]
ldr r0,=INTSUBMSK //禁止所有子中断
ldr r1,=0x7ff @all sub interrupt disable
str r1,[r0]
ldr r0,=SRCPND //清除所有中断源
ldr r1,=0xffffffff @ clear all interrupt source
str r1,[r0]
ldr r0,=INTPND //清除所有中断请求
ldr r1,=0xffffffff @ clear all interrupt pend
str r1,[r0]
ldr r0,=CLKDIVN //设置时钟分频
ldr r1,=0x03 @ HCLK=FLCK/2 PCLK=FCLK/4 busfrq=50Mhz
str r1,[r0]
ldr r0,=CLKCON //使能所有时钟
ldr r1,=0x7fff0 @ all clk enable
str r1,[r0]
ldr r0,=UPLLCON //设置PLL
ldr r1,=((40<<12)+(2<<4)+1) @ Fin=8MHz,Fout=FCLK in option.a
str r1,[r0]
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) @ Fin=8MHz,Fout=FCLK in option.a
str r1,[r0]
//initial ram here
/*;****************************************************
;* Set memory controlregisters *
;****************************************************/
ldr r0,L$_SMRDATA //must convert here 载入L$_SMRDATA地址
ldmia r0,{r1-r13} //L$_SMRDATA地址读出的数据存储到r1-r13,其实也就是SMRDATA的值,这是sdram的控制字,r0自增
ldr r0,=BWSCON //将BWSCON Address存入r0
stmia r0,{r1-r13} //将r1-r13的值依次写入BWSCON Address,r0自动加1
//上述功能完成了DRAM的初始化
/*
* Set processor and MMU to known state asfollows (we may have not
* been entered from a reset). We must do thisbefore setting the CPU
* mode as we must set PROG32/DATA32.
*
* MMU Control Register layout.
*
* bit
* 0 M 0MMU disabled
* 1 A 0Address alignment fault disabled, initially
* 2 C 0Data cache disabled
* 3 W 0Write Buffer disabled
* 4 P 1PROG32
* 5 D 1DATA32
* 6 L 1Should Be One (Late abort on earlier CPUs)
* 7 B ?Endianness (1 => big)
* 8 S 0System bit to zero } Modifies MMU protections, not really
* 9 R 1ROM bit to one } relevant until MMUswitched on later.
* 10 F 0 Should Be Zero
* 11 Z 0 Should Be Zero (Branch predictioncontrol on 810)
* 12 I 0 Instruction cache control
*/
/* Setup MMU Control Register */
MOV r1, #MMU_INIT_VALUE /* Defined in mmuArmLib.h */
ORRr1, r1, #0xc0000000 /* 2410特有的控制位,设置cpu工作在异步时钟*/
//使能cache
#ifdefined(INTEGRATOR_EARLY_I_CACHE_ENABLE)
ORR r1, r1, #MMUCR_I_ENABLE /* no define zj ##conditionally enable Icache*/
#endif
//将MMU_INIT_VALUE的值写入协处理器CP_MMU
MCR CP_MMU, 0, r1, c1, c0, 0 /* Write to MMU CR */
/*
* If MMU was on before this, then we'd betterhope it was set
* up for flat translation or there will be problems. Thenext
* 2/3 instructions will be fetched"translated" (number depends
* on CPU).
*
* We would like to discard the contents of theWrite-Buffer
* altogether, but there is no facility to dothis. Failing that,
* we do not want any pending writes to happenat a later stage,
* so drain the Write-Buffer, i.e. force anypending writes to
* happen now.
*/
//清空写缓冲区
MOV r1, #0 /*data SBZ */
MCR CP_MMU, 0, r1, c7, c10, 4 /* drain write-buffer */
/*Flush (invalidate) both I and D caches */
//禁止cache MCR操作协处理器与arm处理器数据传输,将arm的r1传到CP_MMU中
MCR CP_MMU, 0, r1, c7, c7, 0 /* R1 = 0 from above, data SBZ*/
/*
* Set Process ID Register to zero, thiseffectively disables
* the process ID remapping feature.
*/
//初始化CPU寄存器
MOV r1, #0
MCR CP_MMU, 0, r1, c13, c0, 0
/*disable interrupts in CPU and switch to SVC32 mode 管理模式(svc):操作系统使用的保护模式*/
//禁止CPU中断,是CPU工作在
MRS r1, cpsr // MSR Move from Stateregisterto Register
BIC r1, r1, #MASK_MODE //使用#MASK_MODE 对r1清0
ORR r1, r1, #MODE_SVC32 | I_BIT | F_BIT//使用#MODE_SVC32| I_BIT | F_BIT对r1置1
MSR cpsr, r1 //对状态寄存器进行设置
/* 因为看门狗芯片精度的问题,有可能在系统起来之前就复位,因此*/
/* 先喂狗,使用定时器3喂狗,added byxp 2012-6-14*/
ldr r0,=0x51000004
ldr r1,[r0] //读入
and r1,r1,#0xffff0fff //相应位清0
str r1,[r0] //回写
ldr r0,=0x51000004
ldr r1,[r0]
orr r1,r1,#0x3000 //相应位置1
str r1,[r0]
ldr r0,=0x51000030
ldr r1,=1000 //直写
str r1,[r0]
ldr r0,=0x51000034
ldr r1,=500 //直写
str r1,[r0]
ldr r0,=0x51000008
ldr r1,[r0]
and r1,r1,#0xfff0ffff //相应位清0
str r1,[r0]
ldr r0,=0x51000008
ldr r1,[r0]
orr r1,r1,#0x20000 //相应位写1
str r1,[r0]
ldr r0,=0x51000008
ldr r1,[r0]
and r1,r1,#0xfff0ffff //相应位1清0
str r1,[r0]
ldr r0,=0x51000008
ldr r1,[r0]
orr r1,r1,#0x90000 //相应位写1
str r1,[r0]
ldr r0,=0x56000010
ldr r1,[r0]
and r1,r1,#0xffffff3f //相应位1清0
str r1,[r0]
ldr r0,=0x56000010
ldr r1,[r0]
orr r1,r1,#0x80 //相应位写1
str r1,[r0]
MOV r0, r14 /* restore starttype to r0 from r14 #BOOT_COLD*/
/*jump to C entry point in ROM: routine - entry point + ROM base */
LDR sp, L$_STACK_ADDR //设置堆栈指针指向L$_STACK_ADDR
MOV fp, #0 /*zero frame pointer局部基指针清零,和sp结合使用*/
LDR pc, L$_rStrtInRom //跳转到L$_rStrtInRom去执行
乍一看这些汇编完全看不懂,其实学过一点微机原理的同学,耐心的结合百度看看每条语句,就会发现其实这个程序完成的工作不是那么难,相当简明扼要。可是仅仅实现了关中断、使能时钟、更改CPU运行模式、设置MMU以及喂看门狗等功能就用了这么大的汇编篇幅,不得不感叹C语言的精炼了。执行完这段代码,就可以执行C代码了,然后去执行romStart()这个函数。