BL1相当于u-boot的第一阶段代码,主要完成如下工作:1.初始化硬件:关看门狗、设置串口、SDRAM、初始化Flash;2.重定位,将代码重定位到SDRAM;3.引导u-boot第二阶段代码。其实如果它能引导内核,就相当于一个bootlaoder,这里先实现上面3个功能。代码有点多,我还是贴出来吧,懒得看,需要编译好的源码包留个邮箱我发你。
系统:ubuntu 10.04.4
单板:s5pc100(CES-C100)
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
一、编写代码
文件start.S:
.global
_start:
/*1. Disable Watchdog */
/*1.关看门狗*/
ldr r0, =0xEA200000
mov r1, #0
str r1, [r0]
bl clock_init
//bl test
bl mp1_x_drive_strength_init
bl mem_ctrl_asm_init
ldr sp, =0xD0038000
bl init_uart
bl nand_init
//bl test
ldr r0, =0x0
ldr r1, =0x21000000
ldr r2, =bss_start
sub r2, r2, r1
bl copy_code_to_sdram
//bl test
//b main
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr
on_ddr:
ldr sp, =0x21800000 /* ÖØгõÊŒ»¯Õ»£¬ÖžÏòÄÚŽæ */
//bl test
ldr pc, =main
文件clock.S
.globl clock_init
clock_init:
/* 1.设置LOCK_TIME */
ldr r0, =0xe0100000 //CLOCK_POWER_BASE
mov r1, #0xe00
orr r1, r1, #0x10
str r1, [r0, #0x0] /* APLL_LOCK */
str r1, [r0, #0x4] /* MPLL_LOCK */
str r1, [r0, #0x8] /* EPLL_LOCK */
str r1, [r0, #0x0c] //HPLL_LOCK
//#define OTHERS 0x7e00f900
// @ set async mode /* 当CPU时钟 != HCLK时,要设为异步模式 */
// ldr r0, =OTHERS
// ldr r1, [r0]
// bic r1, r1, #0xc0 /* 1100,0000 */
// str r1, [r0]
//loop1: /* 等待,直到CPU进入异步模式 */
// ldr r0, =OTHERS
// ldr r1, [r0]
// and r1, r1, #0xf00
// cmp r1, #0
// bne loop1
/* SYNC667 */
/* MISC_CON[19] = 0 */
//#define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */
//#define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
//#define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */
//#define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */
//#define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */
// ldr r0, =0x7E00F020 /* CLK_DIV0 */
// ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_//RATIO << 12)
// str r1, [r0]
/* CLK_DIV0 */
#define APLL_RATIO 0
#define ARM_RATIO 4
#define D0_BUS_RATIO 8
#define PCLKD0_RATIO 12
#define SECSS_RATIO 16
ldr r1, [r0, #0x300] //CLK_DIV0 Clock divider
ldr r2, =0x3fff
bic r1, r1, r2
ldr r2, =(1<<APLL_RATIO) | (0<<ARM_RATIO) | (4<<D0_BUS_RATIO) | (1<<PCLKD0_RATIO) | (1<<SECSS_RATIO)
orr r1, r1, r2
str r1, [r0, #0x300] //CLK_DIV0
ldr r2, =((1<<16) | (1<<12) | (1<<8) | (1<<4))
orr r1 ,r1, r2
str r1, [r0, #0x304] //CLD_DIV1
/* 2.配置时钟 */
/* 2.1 配置APLL */
/* 2.1.1 设置APLL
* 2.1.2 MUXAPLL
* 2.1.3 SYNC667
* 2.1.4 DIVAPLL
*/
//#define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
// ldr r0, =0x7E00F00C
// ldr r1, =APLL_CON_VAL
// str r1, [r0] /* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
#define APLL_VAL ((1<<31) | (417 << 16) | (3 << 8) | (0))
//ldr r0, =0xe0100100 //APLL_CON
ldr r1, =APLL_VAL
str r1, [r0, #0x100] /* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
/* 2.2 配置MPLL */
/* 2.2.1 设置MPLL
* 2.2.2 MUXMPLL
* 2.2.3 SYNCMUX
* 2.2.4 SYNC667
* 2.2.5 HCLKX2_RATIO
* 2.2.6 PCLK_RATIO
*/
//#define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
//CONFIG_CLK_833_166_66
#define MPLL_VAL ((1<<31) | (89 << 16) | (2 << 8) | (1))
#define EPLL_VAL ((1<<31) | (135 << 16) | (3 << 8) | (3))
#define HPLL_VAL ((1<<31) | (96 << 16) | (6 << 8) | (3))
ldr r1, =MPLL_VAL
str r1, [r0, #0x104]
ldr r1, =EPLL_VAL
str r1, [r0, #0x108]
ldr r1, =HPLL_VAL
str r1, [r0, #0x10c]
/* 3.选择PLL的输出作为时钟源 */
ldr r1, [r0, #0x200] //CLK_SRC0 0xe0100200
ldr r2, =0x1111
orr r1, r1, r2
str r1, [r0, #0x200] //FOUT: APLL MPLL EPLL HPLL
mov r1, #0x10000
1: subs r1, r1, #1
bne 1b
mov pc, lr
文件cpu_init.S
//#include "s5pc100.h"
/* Port Group MP1_X Drive Strength Control */
#define MP1_0DRV_OFFSET 0x03CC
#define MP1_1DRV_OFFSET 0x03EC
#define MP1_2DRV_OFFSET 0x040C
#define MP1_3DRV_OFFSET 0x042C
#define MP1_4DRV_OFFSET 0x044C
#define MP1_5DRV_OFFSET 0x046C
#define MP1_6DRV_OFFSET 0x048C
#define MP1_7DRV_OFFSET 0x04AC
#define MP1_8DRV_OFFSET 0x04CC
/*
* Bus Matrix
*/
#define ELFIN_MEM_SYS_CFG 0x7e00f120
/*
* Memory controller
*/
#define ELFIN_SROM_BASE 0xE7000000
#define SROM_BW_REG __REG(ELFIN_SROM_BASE+0x0)
#define SROM_BC0_REG __REG(ELFIN_SROM_BASE+0x4)
#define SROM_BC1_REG __REG(ELFIN_SROM_BASE+0x8)
#define SROM_BC2_REG __REG(ELFIN_SROM_BASE+0xC)
#define SROM_BC3_REG __REG(ELFIN_SROM_BASE+0x10)
#define SROM_BC4_REG __REG(ELFIN_SROM_BASE+0x14)
#define SROM_BC5_REG __REG(ELFIN_SROM_BASE+0x18)
/*
* SDRAM Controller
*/
#define APB_DMC_BASE 0xE6000000
#define DMC_CONCONTROL 0x00
#define DMC_MEMCONTROL 0x04
#define DMC_MEMCONFIG0 0x08
#define DMC_MEMCONFIG1 0x0C
#define DMC_DIRECTCMD 0x10
#define DMC_PRECHCONFIG 0x14
#define DMC_PHYCONTROL0 0x18
#define DMC_PHYCONTROL1 0x1C
#define DMC_PHYCONTROL2 0x20
#define DMC_PWRDNCONFIG 0x28
#define DMC_TIMINGAREF 0x30
#define DMC_TIMINGROW 0x34
#define DMC_TIMINGDATA 0x38
#define DMC_TIMINGPOWER 0x3C
#define DMC_PHYSTATUS0 0x40
#define DMC_PHYSTATUS1 0x44
#define DMC_CHIP0STATUS 0x48
#define DMC_CHIP1STATUS 0x4C
#define DMC_AREFSTATUS 0x50
#define DMC_MRSTATUS 0x54
#define DMC_PHYTEST0 0x58
#define DMC_PHYTEST1 0x5C
#define DMC_QOSCONTROL0 0x60
#define DMC_QOSCONFIG0 0x64
#define DMC_QOSCONTROL1 0x68
#define DMC_QOSCONFIG1 0x6C
#define DMC_QOSCONTROL2 0x70
#define DMC_QOSCONFIG2 0x74
#define DMC_DMC_QOSCONTROL3 0x78
#define DMC_QOSCONFIG3 0x7C
#define DMC_QOSCONTROL4 0x80
#define DMC_QOSCONFIG4 0x84
#define DMC_QOSCONTROL5 0x88
#define DMC_QOSCONFIG5 0x8C
#define DMC_QOSCONTROL6 0x90
#define DMC_QOSCONFIG6 0x94
#define DMC_QOSCONTROL7 0x98
#define DMC_QOSCONFIG7 0x9C
/*
* Memory Chip direct command
*/
#define PRO_ID_BASE 0xE0000000
#define PRO_ID_OFFSET 0x00
#define OMR_OFFSET 0x04
/*
* GPIO
*/
#define ELFIN_GPIO_BASE 0xE0300000
.globl mp1_x_drive_strength_init
/*
* Init MP1_X Driver Strength for SDRAM
* void mp1_x_drive_strength_init(void)
*/
mp1_x_drive_strength_init:
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0xaaaa
str r1, [r0, #MP1_0DRV_OFFSET]
str r1, [r0, #MP1_1DRV_OFFSET]
str r1, [r0, #MP1_2DRV_OFFSET]
str r1, [r0, #MP1_3DRV_OFFSET]
str r1, [r0, #MP1_4DRV_OFFSET]
str r1, [r0, #MP1_5DRV_OFFSET]
str r1, [r0, #MP1_6DRV_OFFSET]
str r1, [r0, #MP1_7DRV_OFFSET]
str r1, [r0, #MP1_8DRV_OFFSET]
mov pc, lr
.globl mem_ctrl_asm_init
mem_ctrl_asm_init:
ldr r0, =APB_DMC_BASE @APB_DMC_BASE 0xE6000000
ldr r1, =PRO_ID_BASE
ldr r2, [r1, #PRO_ID_OFFSET]
bic r2, #0xfffffdff
mov r2, r2, lsr #9
cmp r2, #0x1
beq onenand_pop
single:
/************ delay loop *************/
#if 0
ldr r1, =0x10000000
mov r2, #0
loop1:
cmp r2, r1
addne r2, r2, #0x1
bne loop1
#endif
/************ DLL initialization *************/
ldr r1, =0x6A101000 @ Phycontrol0 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x000084F4 @Phycontrol1 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL1]
ldr r1, =0x00000000 @Phycontrol2 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL2]
ldr r1, =0x6A101002 @DLL on
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x6A101003 @Dll start
str r1, [r0, #DMC_PHYCONTROL0]
ldr r2, = 0xE6000040 @DMC_PHYSTATUS0
loop1:
ldr r1, [r2] @Check DLL lock
ands r1, r1, #4
beq loop1
ldr r1, [r2]
mov r1, r1, LSR #(0x6)
and r1, r1, #(0xff)
mov r1, r1, LSL #(0x18)
ldr r2, = 0xE6000018 @DMC_PHYCONTROL0
ldr r3, [r2]
bic r3, r3, #(0xff000000)
orr r1, r3, r2
str r1, [r2]
ldr r1, =0x6A101003 @Force Value locking
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x6A101009 @Dll off
str r1, [r0, #DMC_PHYCONTROL0]
#if 0
ldr r1, =0x6A101000 @ Phycontrol0 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x00008484 @Phycontrol1 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL1]
ldr r1, =0x00000000 @Phycontrol2 DLL parameter setting
str r1, [r0, #DMC_PHYCONTROL2]
#endif
/************ DLL initialization - END *************/
ldr r1, =0x0FF01010 @auto refresh off
str r1, [r0, #DMC_CONCONTROL]
ldr r1, =0x00202400 @ BL=4 , 1 chip , DDR2
str r1, [r0, #DMC_MEMCONTROL]
#if 1 // add xxs 256MB enable
ldr r1, =0x20F01323
str r1, [r0, #DMC_MEMCONFIG0]
ldr r1, =0x40F00323
str r1, [r0, #DMC_MEMCONFIG1]
#else // 128MB enable
ldr r1, =0x20F81313
str r1, [r0, #DMC_MEMCONFIG0]
ldr r1, =0x40F80313
str r1, [r0, #DMC_MEMCONFIG1]
#endif
ldr r1, =0x20000000
str r1, [r0, #DMC_PRECHCONFIG]
ldr r1, =0x00100004 @ PwrdnConfig
str r1, [r0, #DMC_PWRDNCONFIG]
#ifdef CONFIG_HCLKD0_222
ldr r1, =0x000006c3 @7.8us*222MHz=0x6c3, 7.8us*166MHz=1294(0x50E)
str r1, [r0, #DMC_TIMINGAREF]
/* T-rfc 127.5nS/5ns 64 */
ldr r1, =0x202332C8 @TimingRow @222MHz
str r1, [r0, #DMC_TIMINGROW]
ldr r1, =0x24450304 @CL=5
str r1, [r0, #DMC_TIMINGDATA]
#else
ldr r1, =0x0000050E
str r1, [r0, #DMC_TIMINGAREF]
ldr r1, =0x16233297 @TimingRow @166MHz
str r1, [r0, #DMC_TIMINGROW]
@; ldr r1, =0x24250304 @CL=5
ldr r1, =0x23230000 @CL=3
str r1, [r0, #DMC_TIMINGDATA]
#endif
ldr r1, =0x07c80232 @ Timing Power
str r1, [r0, #DMC_TIMINGPOWER]
/* Direct Command for DDR2 */
ldr r1, =0x07000000 @chip0 Deselect
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01000000 @chip0 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00020000 @chip0 EMRS2
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00030000 @chip0 EMRS3
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010400 @chip0 EMRS1 (MEM DLL on = DQS# disable)
str r1, [r0, #DMC_DIRECTCMD]
@; ldr r1, =0x00000552 @chip0 MRS (MEM DLL reset) CL=5, Burst Length=4
ldr r1, =0x00000532 @chip0 MRS (MEM DLL reset) CL=3, Burst Length=4
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01000000