zoukankan      html  css  js  c++  java
  • 使用JLink间接烧写s3c6410 nand_flash的方法

    原文:使用JLink间接烧写s3c6410 nand_flash的方法

    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:oot.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:oot.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

  • 相关阅读:
    强化学习
    详解a标签中href=""的几种用法 锚点
    使用Django自带的登录访问限制login_required
    ValueError: invalid literal for int() with base 10: ''
    Django 中创建Model时报以下错误: TypeError: init() missing 1 required positional argument: ‘on_delete’
    bootstrp实现同一界面多个模态框
    第十二章 Django框架开发
    Python format 格式化函数
    Python3.x在django中如何设置Content-Disposition,才能让浏览器正确保存中文命名的文件?
    python中的*和**参数传递机制
  • 原文地址:https://www.cnblogs.com/ganrui/p/3737812.html
Copyright © 2011-2022 走看看