您的位置:首页 > 其它

使用JLink间接烧写s3c6410 nand_flash的方法[转]

2012-06-07 22:29 661 查看
原文地址

使用JLink间接烧写s3c6410 nand_flash的方法[转]

2012-04-05 9:26
s3c6410对nand_flash的烧写功能,有些公司已经提供了SD卡的方法。但是我们也可以使用JLink把我们的uboot等程序以下面的方式烧写到我们的nand_flash上

硬件环境:JLink V8、三星s3c6410板
软件环境:xp3、JLink4.12驱动、ADS1.2

原理:针对s3c6410,nand flash启动时,系统会把nand flash前4KB的内容自动下载到0xc000000(steppingstone)中运行,我们可以利用
这个特性,来做一些事情,把大的程序烧写到nand flash的0x0地址,这样,在重新启动之后,就会自动运行我们的大程序了。但是这里我们
还忽略了一些细节。细心的读者发现,系统只会把nand flash的地址前4K下载到0xc000000运行,那么大程序如何完全放到内存中运行呢?
如果你玩过uboot的代码搬运的话,那就不是难事了。
s3c6410的0xc000000地址做为steppingstone在nand_flash启动的时候,这段空间是可读可写的。因此我们可以使用JLINK连接板子,并通过JLINK的下载功能,把PC机上的程序写到板子的内存中,通过JLINK的loadbin命令。
1.利用JLINK,烧写能够初始化s3c6410内存的代码到0xc000000,使得内存能够使用
2.利用JLINK,烧写对nand有读写能力并可提供命令处理的程序到内存(没有第一步的初始化内存,我们无法下载程序到内存)
3.烧写我们的第二步的代码到nand flash的0地址,这样在重新启动后,我们的第二步代码就会被下载到0xc000000地址,并运行,
我们可以利用第二步代码所提供的命令来烧写我们其他的程序。第二步的代码往往是引导程序,例如uboot。

学前预备:
1. 对arm体系结构有一定认识,看过s3c6410的datasheet,最起码看过memory map这一章节
2. 会使用ADS1.2 IDE开发工具
3. 会使用JLink工具

步骤:
1.JLink和你的板子连接(别告诉我不会,我截图能力有限


JLink一端通过JTAG口连接到板子上(具体连接方式还要看硬件连线,不过一般都是这样了,我用的转接板),另一端是USB口连接到你的主机上;

2.运行JLink


如果第一步连接正确,启动后将显示以下界面,如果没有检测到CPU,命令行使用usb命令连接板子,r命令识别CPU,正确识别如下所示:

















3.下载程序(nand_flash启动方式)
1)loadbin c:\init.bin 0xc000000
2)setpc 0xc000000
3)g
4)h
5)loadbin c:\boot.bin 0x57e00000
6)setpc 0x57e00000
7)g
解释:loadbin c:\sdram_init.bin 0xc000000,loadbin为JLink内置命令,命令的含义是加载二进制文件到板子的特定地址。c:\sdram_init.bin为二进制文件,0xc000000是地址,如有需要sdram_init程序及源码,请发送邮件。
setpc 0xc000000,setpc是把板子的pc值设置为后面的地址。
g让板子开始执行0xc000000处的代码。
h(halt),停止运行,并显示硬件信息。
loadbin c:\boot.bin 0x57e00000,boot.bin是我的uboot代码,具有nand_flash烧写、网络传输、串口IO等功能,0x57e00000是我的boot.bin代码的运行地址
上面操作的步骤如下图:



setpc 0x57e00000,然后g,打开终端便可以看到你的bootloader已经启动起来了,





4.以上的图片是通过串口读出的uboot程序界面,具有nand烧写功能。现在程序被我们放到了0x57e00000,我们把他烧写到nand flash中
使用uboot的命令 nand write.i 0x57e00000 0x0 0x80000。命令的含义为把内存地址0x57e00000地址处0x80000个字节的内容写到
nand flash的0x0地址中。
好了,下次重启时,nand flash前4KB的内容会被放到steppingstone中运行,这前4KB的内容在内存中运行起来之后,把nand flash中
的代码完全拷贝到内存中,便可以使用uboot的全部功能,也可以随便烧写其他程序了,比如说内核、根文件系统,哈哈。

5.上面提到过sdram_init.bin文件,是初始化内存的汇编代码。以下提供s3c6410的内存初始化代码。两个文件:sdram_init.S和sdram_init.inc。sdram_init.S是内存初始化源代码,sdram_init.inc为头文件。代码使用ADS1.2编写:
sdram_init.S内容如下:
GET sdram_init.inc

;====================

;main

;====================

area sdram_init, code, readonly

entry



;====================

;peri port setup

;====================

ldr r0, =0x70000000

orr r0, r0, #0x13

mcr p15,0,r0,c15,c2,4



;====================

;disable watchdog

;====================

ldr r0, =ELFIN_WATCHDOG_BASE

mov r1, #0x0

str r1, [r0]



;====================

;External interrupt pending clear

;====================

ldr r0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET) ;EINTPEND

ldr r1, [r0]

str r1, [r0]
ldr r0, =ELFIN_VIC0_BASE_ADDR ;0x71200000

ldr r1, =ELFIN_VIC1_BASE_ADDR ;0x71300000
;Disable all interrupts (VIC0 and VIC1)

mvn r3, #0x0

str r3, [r0, #oINTMSK]

str r3, [r1, #oINTMSK]
;Set all interrupts as IRQ

mov r3, #0x0

str r3, [r0, #oINTMOD]

str r3, [r1, #oINTMOD]
;Pending Interrupt Clear

mov r3, #0x0

str r3, [r0, #oVECTADDR]

str r3, [r1, #oVECTADDR]



;====================

;clock init

;====================

ldr r0, =ELFIN_CLOCK_POWER_BASE ;0x7e00f000
ldr r1, [r0, #OTHERS_OFFSET]

mov r2, #0x40

orr r1, r1, r2

str r1, [r0, #OTHERS_OFFSET]
nop

nop

nop

nop

nop
ldr r2, =0x80

orr r1, r1, r2

str r1, [r0, #OTHERS_OFFSET]
check_syncack

ldr r1, [r0, #OTHERS_OFFSET]

ldr r2, =0xf00

and r1, r1, r2

cmp r1, #0xf00

bne check_syncack
mov r1, #0xff00

orr r1, r1, #0xff

str r1, [r0, #APLL_LOCK_OFFSET]

str r1, [r0, #MPLL_LOCK_OFFSET]

str r1, [r0, #EPLL_LOCK_OFFSET]
ldr r1, [r0, #CLK_DIV2_OFFSET]

bic r1, r1, #0x70000

orr r1, r1, #0x30000

str r1, [r0, #CLK_DIV2_OFFSET]
ldr r1, [r0, #CLK_DIV0_OFFSET] ;Set Clock Divider

bic r1, r1, #0x30000

bic r1, r1, #0xff00

bic r1, r1, #0xff

ldr r2, =CLK_DIV_VAL

orr r1, r1, r2

str r1, [r0, #CLK_DIV0_OFFSET]
ldr r1, =APLL_VAL

str r1, [r0, #APLL_CON_OFFSET]

ldr r1, =MPLL_VAL

str r1, [r0, #MPLL_CON_OFFSET]
ldr r1, =0x80200203 ;FOUT of EPLL is 96MHz

str r1, [r0, #EPLL_CON0_OFFSET]

ldr r1, =0x0

str r1, [r0, #EPLL_CON1_OFFSET]
ldr r1, [r0, #CLK_SRC_OFFSET] ;APLL, MPLL, EPLL select to Fout
ldr r2, =0x2007

orr r1, r1, r2

str r1, [r0, #CLK_SRC_OFFSET]
;wait at least 200us to stablize all clock

mov r1, #0x10000

1 subs r1, r1, #1

bne %B1
;Synchronization for VIC port

ldr r1, [r0, #OTHERS_OFFSET]

orr r1, r1, #0x20

str r1, [r0, #OTHERS_OFFSET]



;====================

;memory init

;====================

ldr r0, =ELFIN_MEM_SYS_CFG ;Memory sussystem address 0x7e00f120

mov r1, #0xd ;Xm0CSn2 = NFCON CS0 设置NAND Flash为存储器

str r1, [r0]
ldr r0, =ELFIN_DMC1_BASE ;DMC1 base address 0x7e001000



; memc_cmd : 010 wake up

ldr r1, =0x04

str r1, [r0, #INDEX_DMC_MEMC_CMD]



; Refresh period = ((Startup_HCLK / 1000 * DDR_tREFRESH) - 1) / 1000000 -> DDR_tREFRESH 7800 ns

ldr r1, = 1308 ; DMC_DDR_REFRESH_PRD

str r1, [r0, #INDEX_DMC_REFRESH_PRD]



; CAS_Latency = DDR_CASL<<1 -> DDR_CASL 3

ldr r1, = 6 ; DMC_DDR_CAS_LATENCY

str r1, [r0, #INDEX_DMC_CAS_LATENCY]



; t_DQSS (clock cycles)

ldr r1, = 1 ; DMC_DDR_t_DQSS

str r1, [r0, #INDEX_DMC_T_DQSS]
; T_MRD (clock cycles)

ldr r1, = 2 ; DMC_DDR_t_MRD

str r1, [r0, #INDEX_DMC_T_MRD]
; T_RAS (clock cycles)

ldr r1, = 7 ; DMC_DDR_t_RAS

str r1, [r0, #INDEX_DMC_T_RAS]
; T_RC Active Bank x to Active Bank x delay(clock cycles)

ldr r1, = 10 ; DMC_DDR_t_RC

str r1, [r0, #INDEX_DMC_T_RC]
; T_RCD RAS to CAD delay(clock cycles)

ldr r1, = 4 ; DMC_DDR_t_RCD

ldr r2, = 8 ; DMC_DDR_schedule_RCD

orr r1, r1, r2

str r1, [r0, #INDEX_DMC_T_RCD]
; T_RFC AutoRefresh(clock cycles)

ldr r1, = 11 ; DMC_DDR_t_RFC

ldr r2, = 256 ; DMC_DDR_schedule_RFC

orr r1, r1, r2

str r1, [r0, #INDEX_DMC_T_RFC]
; T_RP Precharge to RAS delay(clock cycles)

ldr r1, = 4 ; DMC_DDR_t_RP

ldr r2, = 8 ; DMC_DDR_schedule_RP

orr r1, r1, r2

str r1, [r0, #INDEX_DMC_T_RP]
; T_RRD Active Bank x to Active Bank y delay(clock cycles)

ldr r1, = 3 ; DMC_DDR_t_RRD

str r1, [r0, #INDEX_DMC_T_RRD]
; T_WR Write to precharge delay(clock cycles)

ldr r1, =3 ; DMC_DDR_t_WR

str r1, [r0, #INDEX_DMC_T_WR]
; T_WTR Write to Read delay(clock cycles)

ldr r1, = 2 ;DMC_DDR_t_WTR

str r1, [r0, #INDEX_DMC_T_WTR]
; T_XP Exit Power down(clock cycles)

ldr r1, = 2 ; DMC_DDR_t_XP

str r1, [r0, #INDEX_DMC_T_XP]
; T_XSR Exit self refresh(clock cycles)

ldr r1, = 17 ; DMC_DDR_t_XSR

str r1, [r0, #INDEX_DMC_T_XSR]
; T_ESR SelfRefresh(clock cycles)

ldr r1, = 17 ; DMC_DDR_t_ESR

str r1, [r0, #INDEX_DMC_T_ESR]
; Memory Configuration Register

ldr r1, = 0x40010012 ; DMC1_MEM_CFG

str r1, [r0, #INDEX_DMC_MEMORY_CFG]
ldr r1, = 0xb41 ; DMC1_MEM_CFG2

str r1, [r0, #INDEX_DMC_MEMORY_CFG2]
ldr r1, = 0x150f8 ; DMC1_CHIP0_CFG

str r1, [r0, #INDEX_DMC_CHIP_0_CFG]
ldr r1, = 0 ; DMC_DDR_32_CFG

str r1, [r0, #INDEX_DMC_USER_CONFIG]
; The follows is according to the Datasheet initialization sequence

;DMC0 DDR Chip 0 configuration direct command reg

ldr r1, = 0x0c0000 ; DMC_NOP0

str r1, [r0, #INDEX_DMC_DIRECT_CMD]
;Precharge All

ldr r1, = 0 ; DMC_PA0

str r1, [r0, #INDEX_DMC_DIRECT_CMD]
;Auto Refresh 2 time

ldr r1, = 0x40000 ; DMC_AR0

str r1, [r0, #INDEX_DMC_DIRECT_CMD]

str r1, [r0, #INDEX_DMC_DIRECT_CMD]
;MRS

ldr r1, = 0xa0000 ; DMC_mDDR_EMR0

str r1, [r0, #INDEX_DMC_DIRECT_CMD]
;Mode Reg

ldr r1, = 0x80032 ; DMC_mDDR_MR0

str r1, [r0, #INDEX_DMC_DIRECT_CMD]
;Enable DMC1

mov r1, #0x0

str r1, [r0, #INDEX_DMC_MEMC_CMD]
check_dmc1_ready

ldr r1, [r0, #INDEX_DMC_MEMC_STATUS]

mov r2, #0x3

and r1, r1, r2

cmp r1, #0x1

bne check_dmc1_ready

nop
loop

b loop

end

sdram_init.inc内容如下:

;====================

;interrupt defined

;====================

ELFIN_GPIO_BASE EQU 0x7f008000

EINTPEND_OFFSET EQU 0x924

ELFIN_VIC0_BASE_ADDR EQU 0x71200000

ELFIN_VIC1_BASE_ADDR EQU 0x71300000

oINTMSK EQU 0x14

oINTMOD EQU 0x0c

oVECTADDR EQU 0xf00
;====================

;clock init defined

;====================

ELFIN_WATCHDOG_BASE EQU 0x7e004000

ELFIN_CLOCK_POWER_BASE EQU 0x7e00f000

OTHERS_OFFSET EQU 0x900

APLL_LOCK_OFFSET EQU 0x00

MPLL_LOCK_OFFSET EQU 0x04

EPLL_LOCK_OFFSET EQU 0x08

CLK_DIV2_OFFSET EQU 0x28

CLK_DIV0_OFFSET EQU 0x20

Startup_PCLKdiv EQU 3

Startup_HCLKx2div EQU 1

Startup_HCLKdiv EQU 1

Startup_MPLLdiv EQU 1

Startup_APLLdiv EQU 1

CLK_DIV_VAL EQU ((Startup_PCLKdiv<<12)|(Startup_HCLKx2div<<9)|(Startup_HCLKdiv<<8)|(Startup_MPLLdiv<<4)|Startup_APLLdiv)

APLL_MDIV EQU 266

APLL_PDIV EQU 3

APLL_SDIV EQU 1

APLL_VAL EQU ((1<<31 | APLL_MDIV<<16 | APLL_PDIV<<8 | APLL_SDIV))

APLL_CON_OFFSET EQU 0x0c

MPLL_CON_OFFSET EQU 0x10

EPLL_CON0_OFFSET EQU 0x14

EPLL_CON1_OFFSET EQU 0x18

CLK_SRC_OFFSET EQU 0x1c

MPLL_MDIV EQU 266

MPLL_PDIV EQU 3

MPLL_SDIV EQU 1

MPLL_VAL EQU ((1<<31 | MPLL_MDIV<<16 | MPLL_PDIV<<8 | MPLL_SDIV))
;====================

;mem init defined

;====================

CONFIG_SYS_CLK_FREQ EQU 12000000

Startup_APLL EQU (CONFIG_SYS_CLK_FREQ/(APLL_PDIV<<APLL_SDIV)*APLL_MDIV)

Startup_HCLK EQU (Startup_APLL/(Startup_HCLKx2div+1)/(Startup_HCLKdiv+1))

ELFIN_MEM_SYS_CFG EQU 0x7e00f120

ELFIN_DMC1_BASE EQU 0x7e001000

INDEX_DMC_MEMC_CMD EQU 0x04

DDR_tREFRESH EQU 7800

DMC_DDR_REFRESH_PRD EQU (((Startup_HCLK / 1000 * DDR_tREFRESH) - 1) / 1000000)

INDEX_DMC_REFRESH_PRD EQU 0x10

DDR_CASL EQU 3

DMC_DDR_CAS_LATENCY EQU (DDR_CASL<<1)

INDEX_DMC_CAS_LATENCY EQU 0x14

DMC_DDR_t_DQSS EQU 1

INDEX_DMC_T_DQSS EQU 0x18

DMC_DDR_t_MRD EQU 2

INDEX_DMC_T_MRD EQU 0x1c

DDR_tRAS EQU 45

DMC_DDR_t_RAS EQU (((Startup_HCLK / 1000 * DDR_tRAS) - 1) / 1000000 + 1)

INDEX_DMC_T_RAS EQU 0x20

DDR_tRC EQU 68

DMC_DDR_t_RC EQU (((Startup_HCLK / 1000 * DDR_tRC) - 1) / 1000000 + 1)

INDEX_DMC_T_RC EQU 0x24

DDR_tRCD EQU 23

DMC_DDR_t_RCD EQU (((Startup_HCLK / 1000 * DDR_tRCD) - 1) / 1000000 + 1)

DMC_DDR_schedule_RCD EQU ((DMC_DDR_t_RCD - 3) << 3)

INDEX_DMC_T_RCD EQU 0x28

DDR_tRFC EQU 80

DMC_DDR_t_RFC EQU (((Startup_HCLK / 1000 * DDR_tRFC) - 1) / 1000000 + 1)

DMC_DDR_schedule_RFC EQU ((DMC_DDR_t_RFC - 3) << 5)

INDEX_DMC_T_RFC EQU 0x2c

DDR_tRP EQU 23

DMC_DDR_t_RP EQU (((Startup_HCLK / 1000 * DDR_tRP) - 1) / 1000000 + 1)

DMC_DDR_schedule_RP EQU ((DMC_DDR_t_RP - 3) << 3)

INDEX_DMC_T_RP EQU 0x30

DDR_tRRD EQU 15

DMC_DDR_t_RRD EQU (((Startup_HCLK / 1000 * DDR_tRRD) - 1) / 1000000 + 1)

INDEX_DMC_T_RRD EQU 0x34

DDR_tWR EQU 15

DMC_DDR_t_WR EQU (((Startup_HCLK / 1000 * DDR_tWR) - 1) / 1000000 + 1)

INDEX_DMC_T_WR EQU 0x38

DMC_DDR_t_WTR EQU 2

INDEX_DMC_T_WTR EQU 0x3c

DMC_DDR_t_XP EQU 2

INDEX_DMC_T_XP EQU 0x40

DDR_tXSR EQU 120

DMC_DDR_t_XSR EQU (((Startup_HCLK / 1000 * DDR_tXSR) - 1) / 1000000 + 1)

INDEX_DMC_T_XSR EQU 0x44

DMC_DDR_t_ESR EQU DMC_DDR_t_XSR

INDEX_DMC_T_ESR EQU 0x48

DMC1_MEM_CFG EQU ((1<<30) | (2<<15) | (3<<3) | (2<<0)) ;((1<<30) | (2<<15) | (2<<3) | (2<<0))

INDEX_DMC_MEMORY_CFG EQU 0x0c

DMC1_MEM_CFG2 EQU 0xB41

INDEX_DMC_MEMORY_CFG2 EQU 0x4c

DMC1_CHIP0_CFG EQU 0x150f8 ;128M=0x150f0

INDEX_DMC_CHIP_0_CFG EQU 0x200

DMC_DDR_32_CFG EQU 0x0

INDEX_DMC_USER_CONFIG EQU 0x304

DMC_NOP0 EQU 0x0c0000

DMC_PA0 EQU 0x000000

INDEX_DMC_DIRECT_CMD EQU 0x08

DMC_mDDR_EMR0 EQU 0x0a0000

INDEX_DMC_MEMC_STATUS EQU 0x00

DMC_AR0 EQU 0x040000

DMC_mDDR_MR0 EQU 0x080032

END

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐