s3c2410 u-boot源碼分析start.S

http://blogold.chinaunix.net/u3/93782/showart.php?id=2067190

根據board/samsumg/smdk2410下的u-boot.lds這個鏈接腳本知道u-boot啓動的第一階段函數是在cpu/arm920t/start.S。完成的功能主要包括

1:cpu自身的初始化:包括MMU,catch,時鐘系統,SDRAM控制系統的初始話。

2:重定位:把自己從flash中搬到SDRAM 中

3:分配堆棧空間,設置堆棧指針

4:清零BSS數據段

5:跳轉到第二階段入口函數。

具體分析如下:

.globl _start

@設置異常向量表,其中_start是GNU 彙編的默認入口標籤。注意ldr r0,0x1234是把0X1234中的內容寫到R0中,ldr r0,=0x1234,是將1234這個值寫到R0中,以及ADR 是用來加載地址。
_start: b       start_code 
        ldr     pc, _undefined_instruction
        ldr     pc, _software_interrupt
        ldr     pc, _prefetch_abort
        ldr     pc, _data_abort
        ldr     pc, _not_used
        ldr     pc, _irq
        ldr     pc, _fiq

@.word爲GUN 彙編分配一段字內存單元,下面幾句話相當於是C語言中的變量名和變量值。
_undefined_instruction: .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:        .word prefetch_abort
_data_abort:            .word data_abort
_not_used:              .word not_used
_irq:                   .word irq
_fiq:                   .word fiq

@全局符號定義

_TEXT_BASE:
        .word   TEXT_BASE@在board/samsumg/smdk2410中定義爲3ff80000..即UBOOT映像文件所在地址
.globl _armboot_start
_armboot_start:
        .word _start
@下面主要在u-boot.lds鏈接腳本中定義
.globl _bss_start
_bss_start:
        .word __bss_start

.globl _bss_end
_bss_end:
        .word _end

@下面主要爲start_code 的實現

start_code:
        @設置當前狀態爲SVC32模式
        mrs     r0,cpsr   
        bic     r0,r0,#0x1f   @相應位置清零
        orr     r0,r0,#0xd3  @相應位置1,同時關閉IRQ,FIQ。
        msr     cpsr,r0   

@關閉看門狗,關中斷,設置時鐘分頻控制寄存器。pWTCON是看門狗控制寄存器,INTMSK是中斷屏蔽寄存器,INTSUBMSK是中斷子屏蔽寄存器,CLKDIVN是clock divisor register,用來設置FCLK,HCLK,PCLK三者的比例。

         #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
        /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON                0x15300000
#  define INTMSK                0x14400008      /* Interupt-Controller base addresses */
#  define CLKDIVN       0x14800014      /* clock divisor register */
#else
#  define pWTCON                0x53000000
#  define INTMSK                0x4A000008      /* Interupt-Controller base addresses */
#  define INTSUBMSK     0x4A00001C
#  define CLKDIVN       0x4C000014      /* clock divisor register */
# endif
       @關看門狗
        ldr     r0, =pWTCON
        mov     r1, #0x0
        str     r1, [r0]

         @關閉主中斷屏蔽寄存器
         mov     r1, #0xffffffff
        ldr     r0, =INTMSK
        str     r1, [r0]
       # if defined(CONFIG_S3C2410)

      @關閉副中斷屏蔽寄存器

        ldr     r1, =0x3ff
        ldr     r0, =INTSUBMSK
        str     r1, [r0]
# endif

     @設置時鐘分頻控制寄存器。
 /* FCLK:HCLK:PCLK = 1:2:4 */FCLK爲核心提供時鐘,HCLK爲AHB(ARM920T,內存控制器,中斷控制器,LCD控制器,DMA和主USB模塊)提供時鐘,PCLK爲APB(看門狗、IIS、I2C、PWM、MMC、ADC、UART、GPIO、RTC、SPI)提供時鐘
        /* default FCLK is 120 MHz ! */


        ldr     r0, =CLKDIVN
        mov     r1, #3
        str     r1, [r0]
#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 */

@執行CPU初始話。

176 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
178       bl      cpu_init_crit @如果沒有定義CONFIG_SKIP_LOELEVEL_INIT,則執行cpu_init_crit.見236-268下
179  #endif

@重新定位u-boot到SDRAM中

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
181 relocate:                               /* relocate U-Boot to RAM           */
182         adr     r0, _start             @通過adr指令得到當前代碼的地址信息:如果U-boot是從RAM開始運行,則從adr,r0,_start得到的地址信息爲r0=_start=_TEXT_BASE=TEXT_BASE=0x3ff80000;如果U-boot從Flash開始運行,即從處理器對應的地址運行,則r0=0x0000,這時將會執行copy_loop標識的那段代碼了
183         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
184         cmp     r0, r1                  /* don't reloc during debug         */
185         beq     stack_setup   @如果r0等於r1,跳過重定位代碼
186
187         ldr     r2, _armboot_start@_start的內容寫入r2
188         ldr     r3, _bss_start  @_bss_start的內容寫入r3
189         sub     r2, r3, r2          @計算armboot所佔字節大小
190         add     r2, r0, r2             @armboot結束地址
191 @實現從flash中拷貝到_TEXT_BASE(0x3ff80000)所在的地址中去
192 copy_loop:
193         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
194         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
195         cmp     r0, r2                  /* until source end addreee [r2]    */
196         ble     copy_loop
197 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
198
199   @初始化堆棧                                                */
200 stack_setup:
201         ldr     r0, _TEXT_BASE      @3ff80000 
202         sub     r0, r0, #CONFIG_SYS_MALLOC_LEN  @ 向下內存分配,爲malloc預留分配空間
203         sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE@ 全局數據結構空間
204 #ifdef CONFIG_USE_IRQ
205         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)@ 爲IRQ,FIQ分配空間
206 #endif
207         sub     sp, r0, #12           @爲abort異常預留12字節的空間,並將當前的地址賦給sp,這樣就爲內存棧設置好了,之後如果在u-boot中運行程序時需要使用棧的時候就從這裏開始。
208 @清空數據段

209 clear_bss:
210         ldr     r0, _bss_start          /* find start of bss segment        */
211         ldr     r1, _bss_end            /* stop here                        */
212         mov     r2, #0x00000000         /* clear                            */
213
214 clbss_l:str     r2, [r0]                /* clear loop...                    */
215         add     r0, r0, #4
216         cmp     r0, r1
217         ble     clbss_l
219         ldr     pc, _start_armboot@跳轉到_start_armboot,也就是函數 start_armboot,此函數存放在u-boot-2009.03/lib_arm/board.c,這樣就到了u-boot的第二階段了。
220
221 _start_armboot: .word start_armboot

uboot存儲映像

@執行cpu_init_crit.

236 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
237 cpu_init_crit:
238         /*
239          * flush v4 I/D caches
240          */
241         mov     r0, #0
242         mcr     p15, 0, r0, c7, c7, 0   @使Icaches和Dcaches無效
243         mcr     p15, 0, r0, c8, c7, 0   @使TLB失效
244
245      關閉mmu和cache,這裏249行,將13,9,8bit清零(13—異常向量表基地址:0x0, 9—DisableSystem Protection, 8—Disable ROM Protection),250行,將7,2,1,0bit清零(7—爲0的時候表示小端字節序,2-- Data Cache Disabled,1-- Alignment Fault checkingdisabled,0—爲0的話MMU disabled),251行,將bit 1 設置爲1表示Fault checkingenabled,252行,將bit 12設置爲1表示使能 I-Cache。

@MRC指令的格式爲:
@MRC{條件} 協處理器編碼,協處理器操作碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操作碼2。
@MRC指令用於將協處理器寄存器中的數據傳送到ARM處理器寄存器中,若協處理器不能成功完成操作,則產生未定義指令異常。其中協處理器操作碼1和協處理器操作碼2爲協處理器將要執行的操作,目的寄存器爲ARM處理器的寄存器,源寄存器1和源寄存器2均爲協處理器的寄存器。  指令示例: MRC  P3,3,R0,C4,C5,6    ;該指令將協處理器P3的寄存器中的數據傳送到ARM處理器寄存器中。

248         mrc     p15, 0, r0, c1, c0, 0
249         bic    r0, r0, #0x00002300     @ clearbits 13, 9:8 (--V- --RS)
250         bic    r0, r0, #0x00000087     @ clearbits 7, 2:0 (B--- -CAM)
251         orr    r0, r0, #0x00000002     @ set bit2 (A) Align
252         orr    r0, r0, #0x00001000     @ set bit12 (I) I-Cache
253         mcr     p15, 0, r0, c1, c0, 0
254       

260         mov     ip, lr @保存當前鏈接寄存器中的值
261
262         bl      lowlevel_init @ @u-boot-2009.03/board/samsung/smdk2410/lowlevel_init.S ,主要是初始話存儲控制器件,共13個。只需要設置BWSCON和BANKCONx(x爲0-5),而BANK6,BANK7接SDRAM,除了設置BWSCON和BANKCONx(x爲6,7),還需要設置其他四個寄存器,而這13個寄存器的地址是連續的,BWSCON是第一個寄存器
263

264         mov     lr, ip
265         mov     pc, lr @返回執行relocate。

266 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

@以下就是各種中斷的處理。

 @.macro僞操作符標識宏定義的開始,.endm標識宏定義的結束。二者包含的一段代碼,稱爲宏定義體,這樣在程序中就可通過宏指令多次調用該代碼段。格式:
.macro macroname {parameter{,parameter}...}
  ...
 .endm
宏的參數可直接使用斜線“\字符”來引用,如下“\reg”所示。

  @略過     

這裏重聲一下ldr和b的區別:

b跳轉指令是個相對跳轉指令直接向PC寄存器賦值,依賴當前PC的值,這使得B指令不依賴代碼存儲的位置,被稱爲位置無關碼

ldr是從內存中的某個位置讀出數據,並給PC賦值這個位置的地址是當前PC寄存器的值加上偏移值。

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