VxWorks启动代码rominit.s分析

来源:互联网 发布:linux卸载iso 编辑:程序博客网 时间:2024/05/23 11:30

        学习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()这个函数。