當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Hi3515 start.S文件分析
Hi3515是華為海思半導(dǎo)體的一款多媒體處理芯片,這款芯片廣泛的被應(yīng)用于安防監(jiān)控行業(yè)。它采用arm9架構(gòu)的V5指令集,為了方便的以后的工作,加深對該芯片的了解,我對hi3515上電后執(zhí)行的一段匯編代碼做了大致分析,分析以注釋的形式書寫在start.s的文件中。
/*
board\hi3515v100\u-boot.lds 是UBOOT的鏈接腳本
其中 ENTRY(_start) 指定了程序的入口地址。
_start是cpu加電后執(zhí)行的第一條指令。
Hi3515在加電后0x0到0x0400000映射為啟動(dòng)器件的地址
可以為NOR-FLASH或NAND-FLASH
*/
.globl _start
_start:
@跳轉(zhuǎn)到reset執(zhí)行
b reset
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
_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
.balignl 16,0xdeadbeef
/*
*
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*
*/
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
.globl _img_end
_img_end:
.word __img_end
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
#ifdef CONFIG_HISILICON
_clr_remap_rom_entry:
.word ROM_TEXT_ADRS + do_clr_remap - TEXT_BASE
_clr_remap_nand_entry:
.word NAND_TEXT_ADRS + do_clr_remap - TEXT_BASE
#endif
/*
* the actual reset code
*/
reset:
/*
* set the cpu to SVC32 mode
*/
@設(shè)置ARM的工作模式為特權(quán)模式
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*
* flush v4 I/D caches
*/
@關(guān)閉P15協(xié)處理器,即關(guān)閉MMU和CACAHE
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
mcr p15, 0, r0, c1, c0, 0
@獲取3515的啟動(dòng)模式,判斷是從NOR或者NAND啟動(dòng),保存到R4中
ldr r0, =REG_BASE_SCTL
ldr r1, [r0, #0x8c]
and r1, r1, #0x60
lsr r4, r1, #5
@Check if I need jump to rom
@movs r0, pc, lsr#24 /* Z flag if r0 == 0 then 1 else 0 */
@bne do_clr_remap
/*判斷高8位是否為0,首次加電的時(shí)候,肯定是0,
如果已經(jīng)在RAM中運(yùn)行了,則不是零。*/
mov r0, pc, lsr#24
cmp r0, #0x0
bne do_clr_remap
@如果從r4中判斷是從NOR啟動(dòng),則PC指向以NOR-flash為基地址(0X80000000),以do_clr_remap函數(shù)為偏移量的地址。
@即PC指向了NOR-flash中的do_clr_remap函數(shù)
@如果從r4中判斷是從NAND啟動(dòng),則PC指向以NAND-flash為基地址(0X70000000),以do_clr_remap函數(shù)為偏移量的地址。
@即PC指向了NAND-flash中的do_clr_remap函數(shù)
cmp r4, #2 /* boot from nand flash*/
ldreq pc, _clr_remap_nand_entry
cmp r4, #0 /* boot from nor flash */
ldreq pc, _clr_remap_rom_entry
do_clr_remap:
ldr r4, =REG_BASE_SCTL
@ldr r0, =REG_VALUE_SC_NOLOCK
@str r0, [r4, #REG_VALUE_SC_LOCKED]
ldr r0, [r4, #REG_SC_CTRL]
@清除重映射
@Set clear remap bit.
orr r0, #(1<<8)
str r0, [r4, #REG_SC_CTRL]
@重映射后零地址不再指向NAND或NOR而是指向了ITCM(指令緊耦合存儲(chǔ)器),3515的ITCM的大小是2KB,地址從0x0到0x00000800
@設(shè)置ITCM的大小和啟用CACHE
@Setup ITCM (ENABLED, 2KB)
ldr r0, =( 1 | (MEM_CONF_ITCM_SIZE<<2) | MEM_BASE_ITCM)
mcr p15, 0, r0, c9, c1, 1
@enable I-Cache now
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
mcr p15, 0, r0, c1, c0, 0
@設(shè)置棧指針,指向ITCM區(qū)域后緊鄰的地址即 0x00000800
@Setup lowlevel sp
ldr sp, =(MEM_BASE_ITCM + MEM_SIZE_ITCM)
@通過檢測高四位地址,以判斷當(dāng)前指令實(shí)在是RAM還是FLASH中運(yùn)行,
@如果是在NOR中就是0X8 如果是在nand中就是0x7
@如果是在RAM中就是0XC
@首次加電的話就是0x8或0x7,即在FLASH中運(yùn)行
@Check if I'm running in static mem bank
mov r0, pc, lsr#28
cmp r0, #(TEXT_BASE>>28)
/*
* Go setup Memory and board specific bits prior to relocation.
*/
@如果判斷出已經(jīng)在內(nèi)存中,即跳轉(zhuǎn)到relocate,越過執(zhí)行l(wèi)owlevel_init,
@首次加電,肯定不會(huì)執(zhí)行跳轉(zhuǎn)
beq relocate
@初始化cpu、切換3515的系統(tǒng)運(yùn)行模式到NORMAL、啟用PLL鎖相環(huán)、啟用DDR控制器,也就是說這以后RAM才真正可用了
@具體代碼參考cpu\arm926ejs\hi3515v100\lowlevel_init.c中的void lowlevel_init(void)函數(shù)
bl lowlevel_init /* go setup pll,mux,memory */
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
@下面就開始把UBOOT從FLASH搬運(yùn)到RAM的準(zhǔn)備工作了
relocate: /* relocate U-Boot to RAM */
@從3515的SC_PERCTRL23寄存器讀取芯片選定的啟動(dòng)模式
ldr r0, =REG_BASE_SCTL
ldr r6, [r0, #0x8c]
and r6, #0x60
lsr r4, r6, #5
@R4=0 從NOR啟動(dòng) R4=2從NAND啟動(dòng)
@下面這一段代碼,有點(diǎn)不是很確定。
@果從FLASH啟動(dòng)那么 _start為0 _TEXT_BASE為0xc0500000
@其中 _TEXT_BASE的指定在board\hi3515v100\config.mk文件中
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
@ _armboot_start等價(jià)于 _start
ldr r2, _armboot_start
ldr r3, _img_end
sub r2, r3, r2 /* r2 <- size of armboot */
cmp r4, #2
ldreq r2, =(CFG_NAND_U_BOOT_ONE_PART)
add r2, r0, r2 /* r2 <- source end address */
@把UBOOT搬運(yùn)到RAM中去,循環(huán)操作,如果是從NOR中搬運(yùn),第一次循環(huán)時(shí)R0=0X80000000 R1=_TEXT_BASE為0xc0500000
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack */
@設(shè)置0XC0500000-CFG_MALLOC_LEN-CFG_GBL_DATA_SIZ-3的內(nèi)存為棧地址
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
@對BSS段的內(nèi)存數(shù)據(jù)清零
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
@調(diào)用start_armboot函數(shù),進(jìn)入C代碼階段,以后PC就指向RAM的地址了,代碼在RAM中運(yùn)行
ldr pc, _start_armboot
_start_armboot:
.word start_armboot