• ok6410下的uboot分析与实现


    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 don't disable watchdog,because you don't 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 语言,跳到第二阶段。

  • 相关阅读:
    ip地址和子网掩码
    Mysql 进阶查询 (select 语句的高级用法)
    MHA高可用配置及故障切换
    数据库的备份与恢复需要修改
    每天一分钟,了解mysql索引,事务与存储引擎
    mysql基础命令详解
    带你走进mysql数据库
    Spring XML无自动提示
    Spring环境搭建错误
    读书笔记_java设计模式深入研究 第十一章 装饰器模式 Decorator
  • 原文地址:https://www.cnblogs.com/youngvoice/p/4828923.html
Copyright © 2020-2023  润新知