地址:http://write.blog.csdn.net/postedit/8960858
#include
#include
#include
#include
/* 内部96K SRAM,有一信息头,共16字节。前4字节为BL1大小(此处为.word 0x2000,即BL1大小为8K);4到8字节为保留位,
默认为0;8到12字节为checkSum,校验位,此处默认为0;最后4字节为保留字节,默认为0 */
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
.globl _start
_start: b reset
reset:
/*
* set the cpu to SVC32 mode and IRQ & FIQ disable,设置CPU为管理模式,禁止中断及快速中断
*/
@;mrs r0,cpsr
@;bic r0,r0,#0x1f
@;orr r0,r0,#0xd3
@;msr cpsr,r0
msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC
cpu_init_crit:
bl disable_l2cache
.global disable_l2cache
disable_l2cache:
mrc p15, 0, r0, c1, c0, 1 @具体参照DDI0344K_cortex_a8_r3p2_trm.pdf文件,Auxiliary Control辅助控制
bic r0, r0, #(1<<1) @将bit1清零
mcr p15, 0, r0, c1, c0, 1 @L2 cache disabled
mov pc, lr
bl set_l2cache_auxctrl_cycle
.global set_l2cache_auxctrl_cycle
set_l2cache_auxctrl_cycle:
mrc p15, 1, r0, c9, c0, 2 @L2 Cache Auxiliary Control
bic r0, r0, #(0x1<<29) @two cycles, default
bic r0, r0, #(0x1<<21) @disables parity or ECC, default
bic r0, r0, #(0x7<<6) @tag RAM latency =4 cycles
bic r0, r0, #(0x7<<0) @Data RAM latency = 8 cycles
mcr p15, 1, r0, c9, c0, 2
mov pc,lr
bl enable_l2cache
.global enable_l2cache
enable_l2cache:
mrc p15, 0, r0, c1, c0, 1
orr r0, r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 @L2 cache enabled
mov pc, lr
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ Invalidate Inst-TLB and Data-TLB,无效指令TLB与数据TLB
mcr p15, 0, r0, c7, c5, 0 @ Invalidate all instruction caches to PoU. Also flushes branch target cache
@无效所有指令缓存,刷新分支目标缓存
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0 @ Control
bic r0, r0, #0x00002000 @ clear bits 13 (--V-),正常异常向量选择,复位值,向量基地址寄存器决定地址范围
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM),关闭数据缓存,禁止对其错误检查,关闭MMU
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align,打开对其错误检查
orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB,无效指令缓存
mcr p15, 0, r0, c1, c0, 0
/* Read booting information */
ldr r0, =PRO_ID_BASE @0xE0000000
ldr r1, [r0,#OMR_OFFSET] @R0+0x04;引导模式寄存器地址,此条命令为读寄存器状态
bic r2, r1, #0xffffffc1 @此条命令为读OM引脚配置状态,将OM[0]位清零,选择X-TAL
#ifdef CONFIG_TQ210_IIC_PM_CHIP
/* PS_HOLD(GPJ2_5) set to output high,电源管理芯片PS_HOLD引脚*/
ldr r0, =ELFIN_GPIO_BASE@ 0xE02000000
ldr r1, =0x00100000
str r1, [r0, #GPJ2CON_OFFSET]@ 0xE02000000+0X280;将R1寄存器值存入GPJ2CON,设置为输出.
ldr r1, =0x0400
str r1, [r0, #GPJ2PUD_OFFSET]@ 0xE02000000+0X288;将R1寄存器值存入GPJ2PUD,设置为上拉
ldr r1, =0x20
str r1, [r0, #GPJ2DAT_OFFSET]@ 0xE02000000+0X284;将R1寄存器值存入GPJ2DAT,设置为1
#endif /* CONFIG_TQ210_IIC_PM_CHIP */
/* NAND BOOT根据OM引脚配置状态来给R3寄存器赋予代表系统是从何种外部存储器启动的配置值,
确定从哪个介质中copy U-Boot到RAM ,识别各种启动方式,并将识别到的启动识别码写入R3中 */
cmp r2, #0x0 @ 512B 4-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x2 @ 2KB 5-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x8 @ OneNAND Mux
moveq r3, #BOOT_ONENAND
/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD
/* NOR BOOT */
cmp r2, #0x14
moveq r3, #BOOT_NOR
/* Uart BOOTONG failed */
cmp r2, #(0x1<<4)
moveq r3, #BOOT_SEC_DEV
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET]@ 将R3存入INFORM3(0xE010_F00C)中
/*
* Go setup Memory and board specific bits prior to relocation..重定位前初始化存储器和板特殊位
*/
ldr sp, =0xd0036000 /* end of sram dedicated to u-boot */
sub sp, sp, #12 /* set stack */
mov fp, #0
bl lowlevel_init /* lowlevel_init.S go setup pll,mux,memory,完成关看门狗,电源模块初始化,时钟初始化,
串口初始化,sdram初始化,NANDFLASH初始化 */
.globl lowlevel_init
lowlevel_init:
push {lr}
/* check reset status,检查复位状态 */
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)@将R0值设为0XE010A000,为复位状态寄存器,反映了各位复位条件的状态。
ldr r1, [r0]
bic r1, r1, #0xfff6ffff @保留bit16及bit19位,其他位清零
cmp r1, #0x10000 @ARM reset from DEEP-IDLE
beq wakeup_reset_pre
cmp r1, #0x80000 @Reset by SLEEP mode wake-up
beq wakeup_reset_from_didle
/* IO Retention release,不太明白 */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)@0xE010_E000,OTHERS
ldr r1, [r0]
ldr r2, =IO_RET_REL @((1 << 31) | (1 << 29) | (1 << 28))
orr r1, r1, r2
str r1, [r0]
/* Disable Watchdog,管看门狗 */
ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */
mov r1, #0
str r1, [r0] @关闭看门狗,关闭看门狗中断,关闭看门狗复位
/* SRAM(2MB) init for SMDKC110 */
/* GPJ1 SROM_ADDR_16to21, 配置sram引脚,16位数据宽度,SROM_ADDR_16to22[ ]为复用引脚,22位地址宽度*/
ldr r0, =ELFIN_GPIO_BASE
ldr r1, [r0, #GPJ1CON_OFFSET]
bic r1, r1, #0xFFFFFF
ldr r2, =0x444444
orr r1, r1, r2
str r1, [r0, #GPJ1CON_OFFSET] @引脚功能SROM_ADDR_16to22[ ]
ldr r1, [r0, #GPJ1PUD_OFFSET]
ldr r2, =0x3ff
bic r1, r1, r2
str r1, [r0, #GPJ1PUD_OFFSET] @禁止上拉下拉模式
/* GPJ4 SROM_ADDR_16to21 */
ldr r1, [r0, #GPJ4CON_OFFSET]
bic r1, r1, #(0xf<<16)
ldr r2, =(0x4<<16)
orr r1, r1, r2
str r1, [r0, #GPJ4CON_OFFSET] @引脚功能SROM_ADDR_16to22[ ]
ldr r1, [r0, #GPJ4PUD_OFFSET]
ldr r2, =(0x3<<8)
bic r1, r1, r2
str r1, [r0, #GPJ4PUD_OFFSET] @禁止上拉下拉模式
/* CS0 - 16bit sram, enable nBE, Byte base address */
ldr r0, =ELFIN_SROM_BASE /* 0xE8000000 */
mov r1, #0x1
str r1, [r0]
/* PS_HOLD pin(GPH0_0) set to high,不清楚到底什么作用*/
ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)@0xE010_E81C,PS_HOLD_CONTROL寄存器
ldr r1, [r0]
orr r1, r1, #0x300
orr r1, r1, #0x1
str r1, [r0] @将寄存器bit8,bit9,bit1置1;
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq 1f /* r0 == r1 then skip sdram init */
/* init PMIC chip */
#ifdef CONFIG_TQ210_IIC_PM_CHIP
bl PMIC_InitIp @电源管理单元初始化
#endif
/* init system clock,system_clock_init: Initialize core clock and bus clock. void system_clock_init(void)
系统时钟初始化后频率为:ARMCLK=1G; SCLKA2M=200M; HCLK_MSYS=200M; PCLK_MSYS=100M;HCLK_DSYS=166M;
PCLK_DSYS=83M;HCLK_PSYS=133M;PCLK_PSYS=66.5M
*/
bl system_clock_init @1)选择时钟源;2)设置锁定时间;3)设置APLL,MPLL,VPLL频率;4)配置各模块分频;5)开ACF;6)耗时等待稳定
system_clock_init:
ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000
/* Set Mux to FIN */
ldr r1, =0x0
str r1, [r0, #CLK_SRC0_OFFSET] @CLK_SRC0,时钟源选择
ldr r1, =APLL_LOCKTIME_VAL
str r1, [r0, #APLL_LOCK_OFFSET] @将APLL_LOCK,APLL锁定时间设置为0x2cf
/* Disable PLL */
ldr r1, =0x0
str r1, [r0, #APLL_CON0_OFFSET] @APLL_CON0 设置APLL使能锁存,锁定时间使能,APLL频率设置,此处将APLL禁止
ldr r1, =0x0
str r1, [r0, #MPLL_CON_OFFSET] @MPLL_CON0 设置APLL使能锁存,锁定时间使能,APLL频率设置,此处将MPLL禁止
ldr r1, [r0, #CLK_DIV0_OFFSET]
ldr r2, =CLK_DIV0_MASK
bic r1, r1, r2
ldr r2, =CLK_DIV0_VAL ldr r1, =APLL_VAL ldr r1, =MPLL_VAL ldr r1, =VPLL_VAL /* CLK_DIV6 */ #endif mov pc, lr ldr r0, =ELFIN_UART_CONSOLE_BASE @0xEC000000 mov r1, #0x3 ldr r1, =0x3c5 ldr r1, =UART_UBRDIV_VAL ldr r1, =UART_UDIVSLOT_VAL ldr r1, =0x4f4f4f4f mov pc, lr /* ABB disable */ /* Print 'K' */ pop {pc} /* get ready to call C functions */ /* when we already run in ram, we don't need to relocate U-Boot. #if defined(CONFIG_EVT1) nand_boot: @copy_from_nand onenand_boot: @onenand_bl2_copy mmcsd_boot: @movi_bl2_copy nor_boot: @read_hword #if defined(CONFIG_ENABLE_MMU) /* Set the TTB register */ // Not Allowed .set __base,0x200 .set __base,0xB00 .set __base,0xD00 /* Enable the MMU,开MMU*/ skip_hw_init: clear_bss: @清BSS clbss_l: ldr pc, _start_armboot @跳转到start_armboot处继续运行。 _start_armboot: 讨论加QQ:1735613836
orr r1, r1, r2
str r1, [r0, #CLK_DIV0_OFFSET] @时钟分频控制寄存器CLK _DIV0,(0<
str r1, [r0, #APLL_CON0_OFFSET] @APLL_CON0 ,使能APLL,设置APLL频率,即MDIV=7D;PDIV=3;SDIV=1;APLL频率为1G
str r1, [r0, #MPLL_CON_OFFSET] @MPLL_CON0 ,使能MPLL,设置MPLL频率,即MDIV=29B;PDIV=C;SDIV=1;MPLL频率为667M
str r1, [r0, #VPLL_CON_OFFSET] @VPLL_CON0 ,使能VPLL,设置VPLL频率,即MDIV=6C;PDIV=6;SDIV=3;MPLL频率为108M
#if defined(CONFIG_EVT1)
ldr r1, =AFC_ON
str r1, [r0, #APLL_CON1_OFFSET] @APLL_CON1 ,设置为0,开AFC,AFC是干什么用的?
#endif
mov r1, #0x10000 /*耗时等待稳定*/
1: subs r1, r1, #1
bne 1b
ldr r1, [r0, #CLK_SRC0_OFFSET]
ldr r2, =0x10001111
orr r1, r1, r2
str r1, [r0, #CLK_SRC0_OFFSET] @设置MUXVPLL,MUXEPLL,MUXMPLL,MUXAPLL为FOUTxPLL
#if defined(CONFIG_MCP_SINGLE)
ldr r1, [r0, #CLK_DIV6_OFFSET] @时钟分频寄存器CLK _DIV6,SCLK_ONENAND = MOUTFLASH / (ONENAND_RATIO + 1)
bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0
str r1, [r0, #CLK_DIV6_OFFSET]
bl mem_ctrl_asm_init @cpu_init.s SDRAM初始化
1:
/* for UART */
bl uart_asm_init
uart_asm_init:
/* set GPIO(GPA) to enable UART */
@ GPIO setting for UART
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x22222222
str r1, [r0, #GPA0CON_OFFSET]
ldr r1, =0x2222
str r1, [r0, #GPA1CON_OFFSET]
mov r1, #0x0
str r1, [r0, #UFCON_OFFSET] @USART FIFO控制寄存器,禁止FIFO
str r1, [r0, #UMCON_OFFSET] @USART MODEM控制寄存器,禁止MODEM及AFC
str r1, [r0, #ULCON_OFFSET] @ULCON0,设置为普通模式,无奇偶校验位,1位停止位,8位数据位
str r1, [r0, #UCON_OFFSET] @时钟源为PCLK,TX,RX中断类型为电平触发,接收错误状态中断使能,
@接收超时使能,RX与TX模式为中断请求或轮询
str r1, [r0, #UBRDIV_OFFSET] @设置模特率,设置波特率为115200,则UBRDIV=(66.7x10^5/115200/16)-1取整,
@此处求出的值为35,不太清楚为什么设置为34?
str r1, [r0, #UDIVSLOT_OFFSET] @UDIVSLOT=((66.7x10^5/115200/16)-1取余),此处求出为3,不明白为什么设置为0XDDDD?
str r1, [r0, #UTXH_OFFSET] @'O',@发送“0x4f4f4f4f”
bl tzpc_init @TrustZone Protection Controller,安全模式,取消存储保护区域,无安全区域
bl nand_asm_init @nand简单的初始化
/* check reset status */
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
ldr r1, [r0]
bic r1, r1, #0xfffeffff
cmp r1, #0x10000
beq wakeup_reset_pre
ldr r0, =0xE010C300
orr r1, r1, #(0x1<<23)
str r1, [r0]
ldr r0, =ELFIN_UART_CONSOLE_BASE
ldr r1, =0x4b4b4b4b
str r1, [r0, #UTXH_OFFSET]
/*不清楚作用,别的文档标注:PS_HOLD输出高电平,PS_HOLD使能。PMIC相关*/
ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldr r1, =0x00005301 /* PS_HOLD output high */
str r1, [r0]
ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer,0x23E0_0000 */
sub sp, sp, #12
mov fp, #0 /* no previous frame, so fp=0 */
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* _TEXT_BASE:0xC3E0_0000,r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq after_copy /* r0 == r1 then skip flash copy */
/* If BL1 was copied from SD/MMC CH2 */
ldr r0, =0xD0037488 @V210_SDMMC_BASE,Current boot channel
ldr r1, [r0]
ldr r2, =0xEB200000 @SDMA System Address
cmp r1, r2
beq mmcsd_boot
#endif
/*判断启动类型,根据启动方式不同,跳转不同执行*/
ldr r0, =INF_REG_BASE
ldr r1, [r0, #INF_REG3_OFFSET]
cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */
beq nand_boot
cmp r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */
beq onenand_boot
cmp r1, #BOOT_MMCSD
beq mmcsd_boot
cmp r1, #BOOT_NOR
beq nor_boot
cmp r1, #BOOT_SEC_DEV
beq mmcsd_boot
mov r0, #0x1000
bl copy_from_nand
b after_copy
bl onenand_bl2_copy
b after_copy
#if DELETE
ldr sp, _TEXT_PHY_BASE
sub sp, sp, #12
mov fp, #0
#endif
bl movi_bl2_copy
b after_copy
bl read_hword
b after_copy
after_copy:
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 @load domain access register,定义使能域的访问权限,Manager
ldr r0, _mmu_table_base @映射页表地址
/*定义一个名为 FL_SECTION_ENTRY 的宏,参数为 base,ap,d,c,b,内容为
(\base << 20) | (\ap << 10) | \ (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1),
根据控制参数建立一个字大小的描述符,以.endm结束*/
.macro FL_SECTION_ENTRY base,ap,d,c,b
.word (\base << 20) | (\ap << 10) | \
(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
/*将这一部分代码都编译进以.mmudata命名的段中(定义MMU数据段,在lds文件里面用到了,定义了
mmu_table放置的位置,“a”表示这是一个需要鉴权的段),权限为a,并确保14喂对齐*/
.section .mmudata, "a"
.align 14
.globl mmu_table
mmu_table:
.set __base,0 @__base设置为0,物理地址高12位
// Access for iRAM
.rept 0x100 @循环0x100次
FL_SECTION_ENTRY __base,3,0,0,0 @页表描述符
.set __base,__base+1
.endr
.rept 0x200 - 0x100
.word 0x00000000
.endr
// should be accessed
.rept 0x600 - 0x200
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
.rept 0x800 - 0x600
.word 0x00000000
.endr
.set __base,0x800
// should be accessed
.rept 0xb00 - 0x800
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
.rept 0xc00 - 0xb00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
.set __base,0x200
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
// 1:1 mapping for debugging with non-cacheable
.rept 0x1000 - 0xD00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
/*不太明白为什么这么求的*/
ldr r1, =CFG_PHY_UBOOT_BASE @0xc3e00000
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
/* Set up the stack */
stack_setup: @建立栈,栈的设置灵活性很大,只要将SP指向一段没有使用的内存即可
#if defined(CONFIG_MEMORY_UPPER_CODE)
ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)
#endif
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
.word start_armboot