原创 analysis bootloader YLP-S3C2440

2009-2-27 13:01 2782 4 4 分类: MCU/ 嵌入式

https://static.assets-stash.eet-china.com/album/old-resources/2009/2/27/233bb0fd-6457-4dbd-b62e-a62e69f16391.rar


1define the address of program


The entry address must be specified by the initialization program:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


      AREA    Init,CODE,READONLY


      ENTRY


Here use “AREA” pseudo-operation define a code segment Init, use “ENTRY” pseudo-operation define the entry address of program.


;1)The code, which converts to Big-endian, should be in little endian code.


;2)The following little endian code will be compiled in Big-Endian mode.


;  The code byte order should be changed as the memory bus width.


;3)The pseudo instruction,DCD can't be used here because the linker generates error.


[ ENDIAN_CHANGE


    ASSERT  :DEF:ENTRY_BUS_WIDTH


    [ ENTRY_BUS_WIDTH=32


           b       ChangeBigEndian             ;DCD 0xea000007


    ]


 


    [ ENTRY_BUS_WIDTH=16


           andeq         r14,r7,r0,lsl #20   ;DCD 0x0007ea00


    ]


 


    [ ENTRY_BUS_WIDTH=8


           streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea


    ]


|


    b         ResetHandler


    ]


From option.inc, ENDIAN_CHANGE is been defined, ENTRY_BUS_WIDTH  is also been defined in addition as follows:


           GBLL        ENDIAN_CHANGE


ENDIAN_CHANGE    SETL         {FALSE}


 


           GBLA        ENTRY_BUS_WIDTH


ENTRY_BUS_WIDTH          SETA         16


From the definiens of ENDIAN_CHANGE and ENTRY_BUS_WIDTH, we know IF pseudo-operation’s logic expression is FALSE, and the program can also see as:


    b         ResetHandler


When difine ENDIAN_CHANGE { FALSE }, the content of 0x0 address in 2440.init.s.list is as follows:


   97 00000000                 ASSERT  :DEF:ENDIAN_CHANGE


   98 00000000                 [       ENDIAN_CHANGE


  112 00000000 EAFFFFFE        b       ResetHandler


  113 00000004                 ]


   97 00000000                 ASSERT  :DEF:ENDIAN_CHANGE


   98 00000000                 [       ENDIAN_CHANGE


   99 00000000                 ASSERT  :DEF:ENTRY_BUS_WIDTH


When difine ENDIAN_CHANGE { TRUE }, the content of 0x0 address in 2440.init.s.list is as follows:


  100 00000000                 [       ENTRY_BUS_WIDTH=32


  102                          ]


  103 00000000        


  104 00000000                 [       ENTRY_BUS_WIDTH=16


  105 00000000 0007EA00        andeq   r14,r7,r0,lsl #20 ;DCD 0x0007ea00


  106 00000004                 ]


  107 00000004        


  108 00000004                 [       ENTRY_BUS_WIDTH=8


  110                          ]


  111 00000004                 |


  113                          ]


  114 00000004 EAFFFFFE        b       HandlerUndef ;handler for Undefined mode     


2Disable the watchdog and interruption


When reset the system, watchdog, interruption and so on, should be disable at once or initialization, otherwise cpu would reset or enter an unknown state.


ResetHandler


           ldr     r0,=WTCON       ;watch dog disable


         ldr     r1,=0x0


         str     r1,[r0]


WTCON is watchdog control register, here write it 0x0, to disable all function of it, include timer interrupt, overflow interrupt and overflow reset.


ldr     r0,=INTMSK


         ldr     r1,=0xffffffff  ;all interrupt disable


         str     r1,[r0]


INTMSK is interrupt mask register, write it 0xffffffff, is to disable all interrupted, because of the interrupt vector table hasn’t been initialization.


         ldr     r0,=INTSUBMSK


         ldr     r1,=0x7fff            ;all sub interrupt disable


         str     r1,[r0]


S3C2440’s peripherals interrupt source is too much, INTMSK didn’t enough, also required INTSUBMSK to disable the interruption remaining.


3Test the LED display


           [ {FALSE}


           ; rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);


           ; Led_Display


           ldr     r0,=GPFCON


           ldr     r1,=0x5500


           str     r1,[r0]


           ldr     r0,=GPFDAT


           ldr     r1,=0x10


           str     r1,[r0]


           ]


First of all, set LED I/O(GPF[7:4]) output (GPFCON = 0x5500), and then light three of them (GPFDAT = 0x10, low level is light on). The code is use IF and ENDIF([{FALSE}……]) pseudo-operation, and the logic of IF is {FALSE}, so the code didn’t compile into the object file.


4System clock initialization


         ;To reduce PLL lock time, adjust the LOCKTIME register.


           ldr     r0,=LOCKTIME


         ldr     r1,=0xffffff


         str     r1,[r0]


LOCKTIME is PLL(lock time count register).


5memory control register initialization


Memory control register initialization is set S3C2440’s Memory Bank[7:0]. Because the apply program is run in SDRAM(Bank 6) finally, and stack interrupt vector table positioning in SDRAM, so it must initialize them before deal with them.


;************************************************


; NAME    : MEMCFG.A


; DESC         : Memory bank configuration file


; Revision: 02.28.2002 ver 0.0


; Revision: 03.11.2003 ver 0.0        Attatched for 2440


;************************************************


……


;BANK0CON


 


B0_Tacs              EQU 0x0    ;0clk


B0_Tcos              EQU 0x1    ;0clk


B0_Tacc              EQU 0x7    ;14clk


B0_Tcoh             EQU 0x1    ;0clk


B0_Tah               EQU 0x0    ;0clk


B0_Tacp             EQU 0x0


B0_PMC            EQU 0x0    ;normal


;Bank 6 parameter


B6_MT               EQU 0x3    ;SDRAM


B6_Trcd              EQU 0x1    ;3clk


B6_SCAN           EQU 0x1    ;9bit


……


;REFRESH parameter


REFEN               EQU 0x1    ;Refresh enable


TREFMD           EQU 0x0    ;CBR(CAS before RAS)/Auto refresh


Trp                      EQU 0x1    ;3clk


Tsrc            EQU 0x1    ;5clk  Trc= Trp(3)+Tsrc(5) = 8clock


Tchr           EQU 0x2    ;3clk


;REFCNT           EQU 1580 ;HCLK=60Mhz, (2048+1-7.81*60) hzh


;REFCNT           EQU 1502 ;HCLK=70Mhz, (2048+1-7.81*70) hzh


;REFCNT           EQU 1424 ;HCLK=80Mhz, (2048+1-7.81*80) hzh


REFCNT            EQU 1346 ;HCLK=90Mhz, (2048+1-7.81*90) hzh


;REFCNT           EQU 1268 ;HCLK=100Mhz, (2048+1-7.81*100) hzht


This part can be found in Memcfg.inc, it defined memory controller associated special register of all functional specific numerical.


SMRDATA DATA


; Memory configuration should be optimized for best performance


; The following parameter is not optimized.


; Memory access cycle parameter strategy


; 1) The memory settings is  safe parameters even at HCLK="75Mhz".


; 2) SDRAM refresh period is for HCLK<=75Mhz.


 


         DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))


         DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0


         DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))   ;GCS1


         DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))   ;GCS2


         DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))   ;GCS3


         DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))   ;GCS4


         DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))   ;GCS5


         DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6


         DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7


         DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)


 


         DCD 0x32     ;SCLK power saving mode, BANKSIZE 128M/128M


         ;DCD 0x02              ;SCLK power saving disable, BANKSIZE 128M/128M


 


         DCD 0x30     ;MRSR6 CL="3clk"


         DCD 0x30     ;MRSR7 CL="3clk"


The beginning of this program, use DATA pseudo-operation designate SMRDATA is a Section of data, not code. And then, use DCD admeasure of a single word of memory cell, and initialized to count the register value with parameters which defined in memcfg.inc, total 13 words(52 bytes).


Set memory control registers


        ldr     r0,=SMRDATA  ;be careful!, hzh


         ldr     r1,=BWSCON    ;BWSCON Address


         add    r2, r0, #52  ;End address of SMRDATA


0


         ldr     r3, [r0], #4


         str     r3, [r1], #4


         cmp  r2, r0


         bne    %B0


This code is to carry SMRDATA DATA table to memory controler so as to initialize them.


6stack initialization


Arm has many modes, different mode has different stack point.


;Start address of each stacks,


_STACK_BASEADDRESS  EQU 0x33ff8000


;The location of stacks


UserStack  EQU (_STACK_BASEADDRESS-0x3800)     ;0x33ff4800 ~


SVCStack   EQU (_STACK_BASEADDRESS-0x2800)     ;0x33ff5800 ~


UndefStack         EQU (_STACK_BASEADDRESS-0x2400)     ;0x33ff5c00 ~


AbortStack          EQU (_STACK_BASEADDRESS-0x2000)     ;0x33ff6000 ~


IRQStack   EQU (_STACK_BASEADDRESS-0x1000)     ;0x33ff7000 ~


FIQStack   EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~


Stack base address defined “_STACK_BASEADDRESS   EQU 0x33ff8000” local in option.inc, but different mode stack point is defined in 2440init.s. The address of 0x33ff8000 belong to Bank6’s 64MB SDRAM space.


Initialize stacks of different mode.


         ;Initialize stacks


         bl      InitStacks


……


;function initializing stacks


InitStacks


         ;Don't use DRAM,such as stmfd,ldmfd......


         ;SVCstack is initialized before


         ;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'


         mrs   r0,cpsr


         bic     r0,r0,#MODEMASK


         orr     r1,r0,#UNDEFMODE|NOINT


         msr   cpsr_cxsf,r1                  ;UndefMode


         ldr     sp,=UndefStack           ; UndefStack="0x33FF"_5C00


The program use mrs operation read the static register value to r0 first, and change the r0 corresponding processor mode bit, and then write to static register, at last the stack point point to UndefStack. The same to other mode:


         orr     r1,r0,#ABORTMODE|NOINT


         msr   cpsr_cxsf,r1                  ;AbortMode


         ldr     sp,=AbortStack            ; AbortStack="0x33FF"_6000


 


         orr     r1,r0,#IRQMODE|NOINT


         msr   cpsr_cxsf,r1                  ;IRQMode


         ldr     sp,=IRQStack              ; IRQStack="0x33FF"_7000


 


         orr     r1,r0,#FIQMODE|NOINT


         msr   cpsr_cxsf,r1                  ;FIQMode


         ldr     sp,=FIQStack               ; FIQStack="0x33FF"_8000


 


         bic     r0,r0,#MODEMASK|NOINT


         orr     r1,r0,#SVCMODE


         msr   cpsr_cxsf,r1                  ;SVCMode


         ldr     sp,=SVCStack              ; SVCStack="0x33FF"_5800


 


         ;USER mode has not be initialized.


 


         mov  pc,lr


         ;The LR register won't be valid if the current mode is not SVC mode.


Here USER mode has not be initialized, because of system didn’t access to user mode.


7interrupt vector table


The entrance of interruption


         AREA    Init,CODE,READONLY


 


         ENTRY


         b       ResetHandler


         b       HandlerUndef     ;handler for Undefined mode


         b       HandlerSWI        ;handler for SWI interrupt


         b       HandlerPabort     ;handler for PAbort


         b       HandlerDabort    ;handler for DAbort


         b       .                  ;reserved


         b       HandlerIRQ        ;handler for IRQ interrupt


         b       HandlerFIQ         ;handler for FIQ interrupt


This part is start at the address of 0x0 that successive 32 bytes. It’s the entrance of interruption, each interruption occupy 4 word memory space. For S3C2440, these entrance of interruption is fixed and only.


Interrupt service program entrance address table


_ISR_STARTADDRESS       EQU 0x33ffff00


This part is defined in option.inc, to save Interrupt service program entrance address, memory table address.


         ALIGN


 


         AREA RamData, DATA, READWRITE


 


         ^   _ISR_STARTADDRESS                 ; _ISR_STARTADDRESS=0x33FF_FF00


HandleReset       #   4


HandleUndef      #   4


HandleSWI                   #   4


HandlePabort    #   4


HandleDabort    #   4


HandleReserved  #   4


HandleIRQ                   #   4


HandleFIQ          #   4


 


;Don't use the label 'IntVectorTable',


;The value of IntVectorTable is different with the address you think it may be.


;IntVectorTable


;@0x33FF_FF20


HandleEINT0               #   4


HandleEINT1               #   4


……


HandleRTC                 #   4


HandleADC                #   4


;@0x33FF_FFA0


This part is defined in 2440init.s. Firstly, use “AREA” pseudo-operation define a readable writeable data segment, and use “MAP(^)” pseudo-operation define a struct memory table that beginning address as 0x33ffff00(_ISR_STARTADDRESS), use “FIELD(#)” define the data domain of memory table. Other operation reference Label before FIELD to read and write the entrance address of interruption.


       ; Setup IRQ handler


         ldr     r0,=HandleIRQ       ;This routine is needed


         ldr     r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c


         str     r1,[r0]


Save the address of IRQ interrupt service program’s IsrIRQ Label in data domain of HandleIR in memory table.


HandlerFIQ      HANDLER HandleFIQ


$HandlerLabel


         sub    sp,sp,#4     ;decrement sp(to store jump address)


         stmfd         sp!,{r0}     ;PUSH the work register to stack(lr does't push because it return to original address)


         ldr     r0,=$HandleLabel ;load the address of HandleXXX to r0


         ldr     r0,[r0]   ;load the contents(service routine start address) of HandleXXX


         str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack


         ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)


         MEND


This part is from IRQ entrance address of interrupt(0x18) jump to run program, it read entrance address of IRQ interrupt(IsrIRQ) from data domain of HandleIRQ in memory table to PC, so as to go into IsrIRQ program and run.


……


#define _ISR_STARTADDRESS 0x33ffff00


……


This part defined in option.h, to save Interrupt service program entrance address, memory table address. It is the same with _ISR_STARTADDRESS  in assembly document, because they are the same table.


// Exception vector


#define pISR_RESET            (*(unsigned *)(_ISR_STARTADDRESS+0x0))


#define pISR_UNDEF          (*(unsigned *)(_ISR_STARTADDRESS+0x4))


#define pISR_SWI                 (*(unsigned *)(_ISR_STARTADDRESS+0x8))


#define pISR_PABORT                 (*(unsigned *)(_ISR_STARTADDRESS+0xc))


#define pISR_DABORT                (*(unsigned *)(_ISR_STARTADDRESS+0x10))


#define pISR_RESERVED    (*(unsigned *)(_ISR_STARTADDRESS+0x14))


#define pISR_IRQ                 (*(unsigned *)(_ISR_STARTADDRESS+0x18))


#define pISR_FIQ                 (*(unsigned *)(_ISR_STARTADDRESS+0x1c))


// Interrupt vector


#define pISR_EINT0            (*(unsigned *)(_ISR_STARTADDRESS+0x20))


#define pISR_EINT1            (*(unsigned *)(_ISR_STARTADDRESS+0x24))


……


#define pISR_CAM              (*(unsigned *)(_ISR_STARTADDRESS+0x38))                // Added for 2440.


……


#define pISR_NFCON                   (*(unsigned *)(_ISR_STARTADDRESS+0x80))                // Added for 2440.


……


#define pISR_RTC                (*(unsigned *)(_ISR_STARTADDRESS+0x98))


#define pISR_ADC               (*(unsigned *)(_ISR_STARTADDRESS+0x9c))


This part is defined by 2440addr.h, it is the same with assembly document (2410init.s) to save the entrance address of interrupt service program’s memory table. It’s usually initialize them with the entrance address of interrupt service program, in interrupt initialize program, as follows:


         pISR_UNDEF=(unsigned)HaltUndef;


         pISR_SWI  =(unsigned)HaltSwi;


         pISR_PABORT=(unsigned)HaltPabort;


         pISR_DABORT=(unsigned)HaltDabort;


……


It is interrupt service program at the right side of equal mark, for example:


void HaltUndef(void)


{


         Uart_Printf("Undefined instruction exception!!!\n");


         while(1);


}


……


The search process of interrupt service program


HandlerFIQ      HANDLER HandleFIQ


HandlerIRQ      HANDLER HandleIRQ


HandlerUndef    HANDLER HandleUndef


HandlerSWI      HANDLER HandleSWI


HandlerDabort   HANDLER HandleDabort


HandlerPabort   HANDLER HandlePabort


……


                   MACRO


$HandlerLabel HANDLER $HandleLabel


 


$HandlerLabel


         sub    sp,sp,#4     ;decrement sp(to store jump address)


         stmfd         sp!,{r0}     ;PUSH the work register to stack(lr does't push because it return to original address)


         ldr     r0,=$HandleLabel;load the address of HandleXXX to r0


         ldr     r0,[r0]   ;load the contents(service routine start address) of HandleXXX


         str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack


         ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)


         MEND


Because of every interrupt has the same process code, use “MACRO” to define them. You can only write the name of macrodefinition to use the code. For example, FIQ code in 2440init.s.list is as follows:


  148 00000048         HandlerFIQ


                               HANDLER HandleFIQ


   65 00000048


   66 00000048         HandlerFIQ


   67 00000048 E24DD004        sub     sp,sp,#4    ;decrement sp(to store jump


                                                   address)


   68 0000004C E92D0001        stmfd   sp!,{r0}    ;PUSH the work register to s


                                                   tack(lr does't push because


                                                   it return to original addres


                                                   s)


   69 00000050 E59F00A4        ldr     r0,=HandleFIQ ;load the address of Handl


                                                   eXXX to r0


   70 00000054 E5900000        ldr     r0,[r0]     ;load the contents(service r


                                                   outine start address) of Han


                                                   dleXXX


   71 00000058 E58D0004        str     r0,[sp,#4]  ;store the contents(ISR) of


                                                   HandleXXX to stack


   72 0000005C E8BD8001        ldmfd   sp!,{r0,pc} ;POP the work register and p


                                                   c(jump to ISR)


When the FIQ interrupt appear, firstly, PC point to the entrance address of FIQ 0x1c to rum jump operation to HandlerFIQ label. Assume SP = 0x33ff8000, after run “sub   sp, sp, #4”, SP = 0x33ff7ffc; “stmfd     sp!, {r0}” operation is SP decrease 1 word to be 0x33ff7ffc, and then push the data of r0 into the address where sp point to, that is the content of the address at 0x33ff7ff8 is the data of r0; “ldr       r0, =HandleFIQ” operation is send the address(0x33ffff1c) of HandleFIQ label to r0; “ldr r0,[r0]” load the contents(service routine start address) of HandleIRQ; “str              r0,[sp,#4]” operation is to store the contents(ISR) of HandleIRQ to stack at the address of SP + 4(0x33ff7ffc), the value of SP didn’t changed, it is still 0x33ff7ff8; the contents of 0x33ff7ff8 is the first value of r0, the contents of 0x33ff7ffc is the entrance address of interrupt service program of FIQ; “ldmfd   sp!,{r0,pc}” operation is to send the content of sp point to to r0, and then increase 1 word to be 0x33ff8000. PC jump to interrupt service program of FIQ and run at this time.


The search process of interrupt service program of peripheral equipment


       ; Setup IRQ handler


         ldr     r0,=HandleIRQ       ;This routine is needed


         ldr     r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c


         str     r1,[r0]


This part of code is to save the address of IsrIRQ label to data domain of HandleIRQ in the entrance address table of interruption, so that when IRQ interrupt appear, PC point to the entrance address of IRQ(0x18), to run “b       HandlerIRQ”, so as to let PC enter “HandlerIRQ      HANDLER HandleIRQ”. PC jump to interrupt service program IsrIRQ in the data domain of HandleIRQ, the program of IsrIRQ is as follows:


IsrIRQ


         sub    sp,sp,#4       ;reserved for PC


         stmfd         sp!,{r8-r9}


 


         ldr     r9,=INTOFFSET


         ldr     r9,[r9]


         ldr     r8,=HandleEINT0


         add    r8,r8,r9,lsl #2


         ldr     r8,[r8]


         str     r8,[sp,#8]


         ldmfd         sp!,{r8-r9,pc}


Assume SP = 0x33ff7000 under the IRQ mode, after run “sub  sp,sp,#4”, SP = 0x33ff6ffc; the meaning of “stmfd   sp!,{r8-r9}” is SP decrease 1 word to be 0x33ff6ff8, send r9 to the address of SP point to, and then SP decrease 1 word to be 0x33ff6ff4, send r8 to the address of SP point to, so after runed the operation, SP = 0x33ff6ff4, 0x33ff6ff8 saved the content of r9, 0x33ff6ff4 saved the content of r8; “ldr     r9,=INTOFFSET” operation is to send INTOFFSET register (Indicate the IRQinterrupt request source, it show the request one, the table of the register show what the value it is in S3C2440A datasheet ) to r9; “ldr r9, [r9]” operation is to send the content of r9 to r9, that is, to send the value of INTOFFSET register to r9; “ldr r8,=HandleEINT0” operation is to send the address of HandleIRQ in interrupt service program entrance address table to r8; “add       r8,r8,r9,lsl #2” operation is shift left r9 two and add Original value of r8, and then send it to r8. Shift left r9 two is the reason of every interrupt source occupy 4 bytes; “ldr     r8,[r8]operation is to send the content of r8 to r8, that is , to send the entrance address of interrupt service program which interrupt source appear saved in table to r8; “str r8,[sp,#8]” operation is to send the value of r8 to SP+8, that is send to 0x33ff6ffc, keep SP unchanged, 0x33ff6ff4 saved the entrance address of interrupt processing function this time; “ldmfd  sp!,{r8-r9,pc}” operation is to send the content which SP point to(0x33ff6ff8) to r8, and then SP increase 1 word, send the content which SP point to(0x33ff6ffc) to PC, and then SP increase 1 word. SP = 0x33ff6700, PC point to the interrupt source service function which interrupt appear and run at this time.


8Image file running domain initialization


Running domain initialization


In the startup code, the initialize mission is the operation of copy image document from loading domain to running domain.


Initialize code is as follows:


         IMPORT  |Image$$RO$$Base|    ; Base of ROM code


         IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)


         IMPORT  |Image$$RW$$Base|   ; Base of RAM to initialise


         IMPORT  |Image$$ZI$$Base|   ; Base and limit of area


         IMPORT  |Image$$ZI$$Limit|  ; to zero initialise


……


;        ;Copy and paste RW data/zero initialized data


;        ldr     r0, =|Image$$RO$$Limit| ; Get pointer to ROM data


;        ldr     r1, =|Image$$RW$$Base|  ; and RAM copy


;        ldr     r3, =|Image$$ZI$$Base|


;


;        ;Zero init base => top of initialised data


;        cmp  r0, r1      ; Check that they are different


;        beq    %F2


;1


;        cmp  r1, r3      ; Copy init data


;        ldrcc  r2, [r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4


;        strcc  r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4


;        bcc    %B1


;2


;        ldr     r1, =|Image$$ZI$$Limit| ; Top of zero init segment


;        mov  r2, #0


;3


;        cmp  r3, r1      ; Zero init


;        strcc  r2, [r3], #4


;        bcc    %B3


First of all, import external symbol |Image$$RO$$Limit| and so on, they are the symbol made by linker, to read the end address of RO, the beginning address of RW and the beginning address of ZI; compare the end address of RO and the beginning address of RW, if equal, skip copy the data of RW segment. “beq %F2”, “2” is label 2, ‘F’ is follow; “%B1”, “B” is before.


9jump into C program


    [ :LNOT:THUMBCODE


                  bl      Main ;Don't use main() because ......


                  ;ldr    pc, =Main  ;hzh


                  b       .


    ]


 


    [ THUMBCODE ;for start-up code for Thumb mode


                  orr     lr,pc,#1


                  bx      lr


                  CODE16


                  bl      Main ;Don't use main() because ......


                  b       .


                   CODE32


    ]


At the beginning of code, “:LNOT:THUMBCODE” is the value of not THUMBCODE, THUMBCODE is label of linker, it is true here, so the code is:


                  bl      Main ;Don't use main() because ......


文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /2 下一条