Code re-location (NAND-> SDRAM) in initi6410_uboot)

Source: Internet
Author: User

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.

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.