Code relocation (nand-& gt; sdram-

Source: Internet
Author: User

Code relocation (nand-> sdram) and-

This article only discusses the code re-location process for starting u-boot from nand flash

Refer:

1) "USER's MANUAL-S3C6410X" Chapter 2 memory map Chapter 8 NAND FLASH CONTROLLER

2) u-boot source code:

U-boot-x.x.x/board/samsumg/smdk6410/lowlevel_init.S

U-boot-x.x.x/cpu/89c64xx/start. S

U-boot-x.x.x/cpu/89c64xx/nand_cp.c

Brief description of code relocation process

Since Code cannot be run in nand flash, when the Development Board starts from nand flash, we need to move the u-boot Code stored in the peripheral nand flash to the sdram for running, how can we complete the handling? This requires the use of a stepping stone, that is, "stepping stone", which is a piece of built-in sram of the initi6410. When the Development Board is powered on, the nand flash Controller automatically copies the first 8 K content of the nand flash to the sram and executes the Code. In addition to initializing the hardware, one of the most important tasks is to copy (I .e. relocate) All the u-boot code in nand flash to the specified address of the sdram, and then jump to the sdram for execution.

Relocation code parsing:

1) nand interface Initialization

When u-boot is started, lowlevel_init is called in start. S and start. S of the corresponding hardware platform to initialize the underlying hardware such as clock, uart, nand, and mmu.

Start. S:

...bl    lowlevel_init    /* go setup pll,mux,memory */...

Lowlevel_init.S:

...
/* * Nand Interface Init for SMDK6400 */nand_asm_init: ldr r0, =ELFIN_NAND_BASE ldr r1, [r0, #NFCONF_OFFSET] orr r1, r1, #0x70 orr r1, r1, #0x7700 str r1, [r0, #NFCONF_OFFSET] ldr r1, [r0, #NFCONT_OFFSET] orr r1, r1, #0x03 str r1, [r0, #NFCONT_OFFSET] mov pc, lr
...

2) code relocation

When starting from nand flash, the relocation code is as follows:

Start. S:

/* 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     after_copy        /* r0 == r1 then skip flash copy   */#ifdef CONFIG_BOOT_NAND    mov    r0, #0x1000    bl    copy_from_nand#endif

R1 stores the starting address of the current Code, r2 stores the address where u-boot is about to run in sdram. If the two addresses are equal, u-boot is already running in sdram, you do not need to copy data from nand to sdram; otherwise, u-boot is still executed in its temporary residence sram, which cannot be kept for a long time, run copy_from_nand to completely copy the u-boot code to the sdram, and then jump to the sdram to execute the remaining code.

/* * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND) * r0: size to be compared * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size */    .globl copy_from_nandcopy_from_nand:    mov    r10, lr        /* save return address */    mov    r9, r0    /* get ready to call C functions */    ldr    sp, _TEXT_PHY_BASE    /* setup temp stack pointer */    sub    sp, sp, #12    mov    fp, #0            /* no previous frame, so fp=0 */    mov    r9, #0x1000    bl    copy_uboot_to_ram3:    tst     r0, #0x0    bne    copy_failed    ldr    r0, =0x0c000000    ldr    r1, _TEXT_PHY_BASE1:    ldr    r3, [r0], #4    ldr    r4, [r1], #4    teq    r3, r4    bne    compare_failed    /* not matched */    subs    r9, r9, #4    bne    1b4:    mov    lr, r10        /* all is OK */    mov    pc, lrcopy_failed:    nop            /* copy from nand failed */    b    copy_failedcompare_failed:    nop            /* compare failed */    b    compare_failed

The copy_uboot_to_ram function is used to really execute the copy action, which is defined in the u-boot-x.x.x/cpu/s364xx/nand_cp.c,

int copy_uboot_to_ram (void){    int large_block = 0;    int i;    vu_char id;            NAND_ENABLE_CE();        NFCMD_REG = NAND_CMD_READID;        NFADDR_REG =  0x00;    /* wait for a while */        for (i=0; i<200; i++);    id = NFDATA8_REG;    id = NFDATA8_REG;    if (id > 0x80)        large_block = 1;    /* read NAND Block.     * 128KB ->240KB because of U-Boot size increase. by scsuh     * So, read 0x3c000 bytes not 0x20000(128KB).     */    return nandll_read_blocks(CFG_PHY_UBOOT_BASE, 0x3c000, large_block);}

Nand flash supports two page sizes: 512B and 2KB. When large_block is 0, the page size is 512 bytes. When large_block is 1, the page size is 2 K bytes. Nandll_read_blocks: copy the data in 0x3c00 (0th K) size starting from page 1 of nand flash to the mongo_phy_uboot_base address of sdram.

/* * Read data from NAND. */static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block){        uchar *buf = (uchar *)dst_addr;        int i;    uint page_shift = 9;    if (large_block)        page_shift = 11;        /* Read pages */        for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {                nandll_read_page(buf, i, large_block);        }        return 0;}

First, determine the size of a page in nand flash based on large_block, and then calculate the number of pages to be copied, that is, pages to be copied (0x3c000> page_shift, nandll_read_page copies data of only one page at a time.

/* * address format *              17 16         9 8            0 * -------------------------------------------- * | block(12bit) | page(5bit) | offset(9bit) | * -------------------------------------------- */static int nandll_read_page (uchar *buf, ulong addr, int large_block){        int i;    int page_size = 512;    if (large_block)        page_size = 2048;        NAND_ENABLE_CE();        NFCMD_REG = NAND_CMD_READ0;        /* Write Address */        NFADDR_REG = 0;    if (large_block)            NFADDR_REG = 0;    NFADDR_REG = (addr) & 0xff;    NFADDR_REG = (addr >> 8) & 0xff;    NFADDR_REG = (addr >> 16) & 0xff;    if (large_block)        NFCMD_REG = NAND_CMD_READSTART;        NF_TRANSRnB();    /* for compatibility(2460). u32 cannot be used. by scsuh */    for(i=0; i < page_size; i++) {                *buf++ = NFDATA8_REG;        }        NAND_DISABLE_CE();        return 0;}

The process for reading data from nand flash is to select (NAND_ENABLE_CE)-> send READ command (nf1__reg)-> send address (NFADDR_REG)-> send READ command (nf1__reg) -> Read data (NF_TRANSRnB)-> Read data (NFDATA8_REG ). Since only one byte of data can be read from NFDATA8_REG each time, you need to read 512 or 2048 times to copy a page.

 

After copy_uboot_to_ram is executed and return to start. S, code relocation in nand flash is completed. After that, the program jumps to sdram for execution, and stepping stone's responsibility ends.


The program that helps the s3c2410 to move the program in nandflash to the sdram and run

You can write an assembly program on your own to move the program in Nand Flash to SDRAM. Since there are two boot modes for the S3C2410 Flash Nor and Nand Flash, the migration process is slightly different. If you start with Nand Flash, you can use the following code. It is relatively simple to start Nor Flash. You can study it yourself.
File 1. head. s
@ File head. s
@ Function: Disable the initialization settings of the watchdog and SDRAM, and move the Nand Flash 4 K later.
@ Code to the specified location of the SDRAM and execute the code in the SDRAM
. Text
. Global _ start
_ Start:
Ldr r0, = 0x53000000 @ Close Watch Dog Timer
Mov r1, #0x0
Str r1, [r0]

Bl memory_setup @ Initialize memory setting
Bl flash_to_sdram @ Copy code to sdram

Ldr sp, = 0x34000000 @ Set stack pointer
Ldr pc, = main @ execute the code in SDRAM

File 2: flash. s
@ File flash. s
@ Role: Set the control register of Nand Flash and read the Nand Flash
@
. Equ NFCONF, 0x4e000000
. Equ NFCMD, 0x4e000004
. Equ NFADDR, 0x4e000008
. Equ NFDATA, 0x4e00000c
. Equ NFSTAT, 0x4e000010
. Equ NFECC, 0x4e000014
. Global flash_to_sdram
Flash_to_sdram:
@ Save return addr
Mov r10, lr

@ Initialize Nand Flash
Mov r0, # NFCONF
Ldr r1, = 0xf830
Str r1, [r0]

@ First reset and enable Nand Flash
Ldr r1, [r0]
Bic r1, r1, #0x800
Str r1, [r0]

Ldr r2, = NFCMD
Mov r3, # 0xff
Str r3, [r2]

@ For delay
Mov r3, # 0x0a
1:
Subs r3, r3, #1
Bne 1b

@ Wait until Nand Flash bit0 is 1
Wait_nfstat:
Ldr r2, = NFSTAT
Ldr r3, [r2]
Tst r3, #0x01
Beq wait_nfstat

@ Disable Nand Flash
Ldr r0, = NFCONF
L ...... remaining full text>

I wrote a uboot program based on into nandflash. It started but didn't respond. Why? Which one would you advise?

The disassembly is definitely not a zero address. In the first stage, uboot needs to copy the code to the sdram and relocate it. The disassembly shows the relocated address, that is, the actual address of your sdram.
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.