码迷,mamicode.com
首页 > 其他好文 > 详细

ok6410下的uboot分析与实现

时间:2015-09-22 16:02:55      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:

uboot 由两阶段代码组成:

•第一阶段主要步骤:

1.将cpu设置为svc模式

2.关闭mmu

3.设置外设端口地址

4.关闭watchdog

5.关闭中断

6.初始化时钟

7.初始化内存DRAM

8.把 nandflash 中的代码搬移到链接地址处

9.初始化堆栈

10.清bss段

11.使用与地址相关的跳转指令,跳转到 c 入口处。

 

OK6410上的启动代码如下:

技术分享
@start.S
.text
.global _start
_start:
/*set the cpu to svc32 mode*/
    mrs r0,cpsr
    bic r0,r0,#0x1f
    orr r0,r0,#0xd3
    msr cpsr,r0

/*disable_mmu*/
    mcr p15,0,r0,c7,c7,0
    mrc p15,0,r0,c1,c0,0
    bic r0,r0,#0x00000007
    mcr p15,0,r0,c1,c0,0
/*peri port setup*/
    ldr r0,=0x70000000
    orr r0,r0,#0x13
    mcr p15,0,r0,c15,c2,4
/*Disable Watchdog
 *if you dont disable watchdog,because you dont to feed dog,so the CPU will conti *nue reboot.
*/
    ldr r0,=0x7e000000
    orr r0,r0,#0x4000
    mov r1,#0
    str r1,[r0]
/*Disable interrupt*/
    mvn r1,#0
    ldr r0,=0x71200014
    str r1,[r0]

    ldr r0,=0x71300014
    str r1,[r0]
    
/*Init clock*/
#define APLL_LOCK    0x7e00f000
#define MPLL_LOCK    0x7e00f004
#define EPLL_LOCK    0x7e00f008
#define LOCK_TIME    0xffff

#define OTHERS        0x7e00f900

#define CLK_DIV0    0x7e00f020

#define CLK_SRC        0x7e00f01c

@ set the lock time to max
    ldr r0, =LOCK_TIME
    ldr r1, =APLL_LOCK
    str r0, [r1]
    ldr r1, =MPLL_LOCK
    str r0, [r1]
    ldr r1, =EPLL_LOCK
    str r0, [r1]    
                    
    @ set async mode
    ldr r0, =OTHERS
    ldr r1, [r0]
    bic r1, #0xc0            
    str r1, [r0]

    loop1:
    ldr r0, =OTHERS
    ldr r1, [r0]
    and r1, #0xf00                    
    cmp r1, #0
    bne loop1        

    @ set the divider

    #define DIV_VAL    ( (0)|(1<<4)|(1<<8)|(1<<9)|(3<<12) )
    ldr r0, =CLK_DIV0
    ldr r1, =DIV_VAL
    str r1, [r0]    
            
    @ set APLL, MPLL, EPLL        
    #define SDIV    1
    #define PDIV    3
    #define MDIV    266    
    #define PLL_ENABLE    ( 1 << 31 )
    #define APLL_VAL    ( (SDIV<<0)|(PDIV<<8)|(MDIV<<16)|(PLL_ENABLE) )
    #define MPLL_VAL    APLL_VAL
    #define EPLL0_VAL    ( (2<<0)|(1<<8)|(32<<16)|PLL_ENABLE)
    #define EPLL1_VAL    ( 0 )
                                
    #define APLL_CON    0x7e00f00c
    #define MPLL_CON    0x7e00f010
    #define EPLL_CON0    0x7e00f014
    #define EPLL_CON1    0x7e00f018

    ldr r0, =APLL_CON
    ldr r1, =APLL_VAL
    str r1, [r0]

    ldr r0, =MPLL_CON
    ldr r1, =MPLL_VAL
    str r1, [r0]
    
    ldr r0, =EPLL_CON0
    ldr r1, =EPLL0_VAL
    str r1, [r0]

    ldr r0, =EPLL_CON1
    ldr r1, =EPLL1_VAL
    str r1, [r0]

    @ select the source                     
    ldr r0, =CLK_SRC
    mov r1, #7
    str r1, [r0]
    
init_mem:
    ldr r0,=0x7e00f120
        mov r1, #0x8
       str r1, [r0]

        ldr r0, =0x7e001004     
        mov r1, #0x4         
        str r1, [r0]

        ldr r0, =0x7e001010  
        ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      
        str r1, [r0]

        ldr r0, =0x7e001014  
        mov r1, #(3 << 1)
        str r1, [r0]

        ldr r0, =0x7e001018      
        mov r1, #0x1
        str r1, [r0]

        ldr r0, =0x7e00101c      
        mov r1, #0x2
        str r1, [r0]

        ldr r0, =0x7e001020       
        ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001024       
        ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001028       
        ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e00102c       
        ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001030       
        ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001034       
        ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001038       
        ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e00103c       
        mov r1, #0x07
        str r1, [r0]

        ldr r0, =0x7e001040       
        mov r1, #0x02
        str r1, [r0]

        ldr r0, =0x7e001044      
        ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e001048       
        ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]

        ldr r0, =0x7e00100c       
        ldr r1, =0x00010012       
        str r1, [r0]
 
        ldr r0, =0x7e00104c      
        ldr r1, =0x0b45
        str r1, [r0]

        ldr r0, =0x7e001200   
        ldr r1, =0x150f8
        str r1, [r0]

        ldr r0, =0x7e001304       
        mov r1, #0x0
        str r1, [r0]
 
        ldr r0, =0x7e001008
        ldr r1, =0x000c0000
        str r1, [r0]

        ldr r1, =0x00000000
        str r1, [r0]

        ldr r1, =0x00040000
        str r1, [r0]

        ldr r1, =0x000a0000
        str r1, [r0]

        ldr r1, =0x00080032
        str r1, [r0]

        ldr r0, =0x7e001004
        mov r1, #0x0
        str r1, [r0]

check_dmc1_ready:
    
        ldr r0, =0x7e001000 
        ldr r1, [r0]
        mov r2, #0x3
        and r1, r1, r2
        cmp r1, #0x1
        bne check_dmc1_ready
        nop

    
    
/*prepare C language environment*/


/*
*copy_to_ram:
*    ldr r0,=0x0c000000
*    ldr r1,=0x50000000
*    add r3,r0,#1024*4
*copy_loop:
*    ldr r2,[r0],#4
*    str r2,[r1],#4
*    cmp r0,r3
*    bne copy_loop
*/

    
init_stack:
    ldr sp,=0x54000000

copy_to_ram:
    adr r0, _start   /* »ñµÃ_startÖ¸ÁǰËùÔڵĵØÖ· : 0*/
    ldr r1, =_start  /* _startµÄÁ´½ÓµØÖ· 0x51000000 */
    
    ldr r2, =bss_start      /* bss¶ÎµÄÆðʼÁ´½ÓµØÖ· */
    
    sub r2, r2, r1
    
    cmp r0,r1
    beq clean_bss
    
    bl copy2ddr
    cmp r0, #0
    bne halt    
clean_bss:
    ldr r0,=bss_start
    ldr r1,=bss_end
    cmp r0,r1
    beq to_ddr
clean_loop:
    mov r2,#0
    str r2,[r0],#4
    cmp r0,r1
    bne clean_loop
            

    


to_ddr:
    bl light_led
    ldr pc,=main

light_led:
    ldr r1, =0x7F008820
    ldr r0, =0x1111
    str r0, [r1]
    
    ldr r1, =0x7F008824
    mov r0,#0xe
    str r0,[r1]
    mov pc, lr    
    
halt:
    b halt
View Code
技术分享
//nand.c

#define MEM_SYS_CFG     (*((volatile unsigned long *)0x7E00F120))
#define NFCONF          (*((volatile unsigned long *)0x70200000))
#define NFCONT          (*((volatile unsigned long *)0x70200004))
#define NFCMMD          (*((volatile unsigned long *)0x70200008))
#define NFADDR          (*((volatile unsigned long *)0x7020000C))
#define NFDATA          (*((volatile unsigned char *)0x70200010))
#define NFSTAT          (*((volatile unsigned long *)0x70200028))

#define NAND_DISABLE_CE()    (NFCONT |= (1 << 1))
#define NAND_ENABLE_CE()    (NFCONT &= ~(1 << 1))
#define NF_TRANSRnB()        do { while(!(NFSTAT & (1 << 0))); } while(0)

#define NAND_CMD_RESET        0xff
#define NAND_CMD_READID        0x90
#define NAND_CMD_READ0        0
#define NAND_CMD_READSTART    0x30

void nand_select(void)
{
    NFCONT &= ~(1<<1);
}

void nand_deselect(void)
{
    NFCONT |= (1<<1);
}


void nand_cmd(unsigned char cmd)
{
    NFCMMD = cmd;
}

void nand_addr(unsigned char addr)
{
    NFADDR = addr;
}

unsigned char nand_get_data(void)
{
    return NFDATA;
}

void wait_ready(void)
{
    while ((NFSTAT & 0x1) == 0);
}

void nand_reset(void)
{
    /* Ñ¡ÖÐ */
    nand_select();
    
    /* ·¢³ö0xffÃüÁî */
    nand_cmd(0xff);

    /* µÈ´ý¾ÍÐ÷ */
    wait_ready();
    
    /* È¡ÏûÑ¡ÖÐ */
    nand_deselect();
}


void nand_init(void)
{
    /* ÈÃxm0csn2ÓÃ×÷nand flash cs0 ƬѡÒý½Å */
    MEM_SYS_CFG &= ~(1<<1);

    /* ÉèÖÃʱ¼ä²ÎÊý:hclk = 7.5ns */
#define TACLS     0
#define TWRPH0    3
#define TWRPH1    1
    NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
    NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));

    /* ʹÄÜnand flash controller */
    NFCONT |= 1;

    nand_reset();
}


void nand_send_addr(unsigned int addr)
{
#if 0    
    unsigned int page   = addr / 2048;
    unsigned int colunm = addr & (2048 - 1);

    /* ÕâÁ½¸öµØÖ·±íʾ´ÓÒ³ÄÚÄÄÀ↑ʼ */
    nand_addr(colunm & 0xff);
    nand_addr((colunm >> 8) & 0xff);

    /* ÏÂÃæÈý¸öµØÖ·±íʾÄÄÒ»Ò³ */
    nand_addr(page & 0xff);
    nand_addr((page >> 8) & 0xff);
    nand_addr((page >> 16) & 0xff);
#else
    nand_addr(addr & 0xff);         /* a0~a7 */
    nand_addr((addr >> 8) & 0x7);   /* ³ÌÐòµÄ½Ç¶È: a8~a10 */

    nand_addr((addr >> 11) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a11~a18 */
    nand_addr((addr >> 19) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a19~a26 */
    nand_addr((addr >> 27) & 0xff); /* ³ÌÐòµÄ½Ç¶È: a27   ~ */
    
#endif
}


int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
    unsigned int addr = nand_start;
    int i, count = 0;
    unsigned char *dest = (unsigned char *)ddr_start;
    
    /* Ñ¡ÖÐоƬ */
    nand_select();

    while (count < len)
    {
        /* ·¢³öÃüÁî0x00 */
        nand_cmd(0x00);

        /* ·¢³öµØÖ· */
        nand_send_addr(addr);

        /* ·¢³öÃüÁî0x30 */
        nand_cmd(0x30);

        /* µÈ´ý¾ÍÐ÷ */
        wait_ready();

        /* ¶ÁÊý¾Ý */
        for (i = 0; i < 2048 && count < len; i++)
        {
            dest[count++] = nand_get_data();
        }

        addr += 2048;            
    }

    /* È¡ÏûƬѡ */
    nand_deselect();
    return 0;
}

static int nandll_read_page (unsigned char *buf, unsigned long addr, int large_block)
{
    int i;
    int page_size = 512;

    if (large_block==2)
        page_size = 4096;

    NAND_ENABLE_CE();  // Ñ¡ÖÐnand

    NFCMMD = NAND_CMD_READ0;

    /* Write Address */
    NFADDR = 0;

    if (large_block)
        NFADDR = 0;

    NFADDR = (addr) & 0xff;
    NFADDR = (addr >> 8) & 0xff;
    NFADDR = (addr >> 16) & 0xff;

    if (large_block)
        NFCMMD = NAND_CMD_READSTART;

    NF_TRANSRnB();

    for(i=0; i < page_size; i++) {
        *buf++ = NFDATA;
    }

    NAND_DISABLE_CE();

    return 0;
}

int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
    unsigned char *dest = (unsigned char *)ddr_start;
    int i;

    /* ³õʼ»¯nand flash controller */
    nand_init();
    
    /* ¶Ánand flash */
    /* Read pages */
    for (i = 0; i < 4; i++, dest+=2048){
        nandll_read_page(dest, i, 2);
    }

    /* Read pages */
    for (i = 4; i < ((len+4096)>>13); i++, dest+=8192) {
        nandll_read_page(dest, i, 2);
    }
    
    return 0;
}
View Code
技术分享
//main.c

#define rGPMCON        (*(volatile unsigned *)(0x7F008820))
#define rGPMDAT        (*(volatile unsigned *)(0x7F008824))
#define rGPMPUD        (*(volatile unsigned *)(0x7F008828))

void msDelay(int time)
{
    volatile unsigned int i,j;
    for (i=0;i<20000;i++)
        for(j=0;j<time;j++);    
}

void GPIO_Init(void)
{
    rGPMCON = 0x11111;
    rGPMPUD = 0x00;
    rGPMDAT = 0x1F;    
}

void LedTest(void)
{
    volatile unsigned int i;
    while(1)
    {
        for(i=0;i<4;i++)
        {
            rGPMDAT =~(1<<i);
            msDelay(10);    
        }    
    }    
}
int main()
{
    GPIO_Init();
    LedTest();

    return 0;
}
View Code

总结如下:

第一阶段启动代码主要完成此阶段所需硬件的初始化。初始化 c 语言运行环境,即初始化堆栈。进入 c 语言,跳到第二阶段。

 

ok6410下的uboot分析与实现

标签:

原文地址:http://www.cnblogs.com/youngvoice/p/4828923.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!