Cubieboard开发环境、Uboot的SD启动卡制作、U-boot初步分析

拿到Cubieboard已经1周多了,平时上班比较忙,只能晚上玩一会,年关将近,周末都要加班呀....

拿到一个板,若只刷别人给的Image学不到太多东西,于是自己一点一点来

首先是Uboot 移植,所谓移植,其实别人都做好了,我只不过是做了一个启动卡

 

系统环境:电脑二台,台式机XP;笔记本RHEL5,平时就用这个,懒得整ubuntu

代码工具:XP上:          Source Insight 3.5

                    RHEL5上: Vim,编译工具链arm-2009q3,这个应该有更高版本;串口工具minicom,我的版本是2.1

资源:        支持Cubieboard的U-boot下载网址:https://github.com/linux-sunxi/u-boot-sunxi ,我直接从网页按zip格式下载到XP下

                    制作方法参考网站:https://github.com/linux-sunxi/u-boot-sunxi/wiki

硬件:        串口线,淘宝Cubieboard自带USB串口线,RHEL5下不用装驱动就能使用,XP下可以用驱动精灵自动安装

                    microSD卡一枚,2G,读卡器一只,华强北出品,居然比淘宝贵...

 

开工:

            首先观察Cubiebord预装的U-Boot,设置好minicom(具体方法请自己百度),连接串口(使用淘宝配的线),连线顺序如下图:

         

         黑色 ---- GND

         绿色 ---- RX

         白色 ---- TX

 

        将串口USB端插入笔记本,打开终端输入命令“minicom”,启动minicom之后,再将电源线插入笔记本USB,启动过程中按键盘任意键,进入U-boot,可以看到:

HELLO! BOOT0 is starting!                                                 
boot0 version : 1.5.1                                                     
dram size =1024                                                           
Succeed in opening nand flash.                                            
Succeed in reading Boot1 file head.
The size of Boot1 is 0x0003c000.
The file stored in 0X00000000 of block 2 is perfect.
Check is correct.
Ready to disable icache.
Succeed in loading Boot1.                                          //第1阶段bootloader
Jump to Boot1.
[       0.133] boot1 version : 1.4.0
[       0.133] pmu type = 3
[       0.135] bat vol = 0
[       0.161] axi:ahb:apb=3:2:2
[       0.161] set dcdc2=1400, clock=1008 successed
[       0.163] key
[       0.175] no key found
[       0.175] flash init start
[       0.227] flash init finish
[       0.228] fs init ok
[       0.229] fattype FAT16
[       0.229] fs mount ok
[       0.236] script finish
[       0.238] power finish
[       0.245] BootMain start
[       0.245] 0
[       0.264] key value = 0
[       0.264] recovery key high 6, low 4
[       0.265] unable to find fastboot_key key_max value
[       0.274] test for multi os boot with display
[       0.275] show pic finish
[       0.278] load kernel start
[       0.302] load kernel successed
[       0.302] start address = 0x4a00000

U-Boot 2011.09-rc1 (Nov 26 2012 - 14:01:52) Allwinner Technology     //第2阶段bootloader

CPU:   SUNXI Family
Board: A10-EVB
DRAM:  512 MiB
NAND:  3776 MiB
In:    serial
Out:   serial
Err:   serial
--------fastboot partitions--------
-total partitions:11-
-name-        -start-       -size-     
bootloader  : 1000000       1000000    
env         : 2000000       1000000    
boot        : 3000000       2000000    
system      : 5000000       14000000   
data        : 19000000      20000000   
misc        : 39000000      1000000    
recovery    : 3a000000      2000000    
cache       : 3c000000      8000000    
private     : 44000000      1000000    
sysrecovery : 45000000      14000000   
UDISK       : 59000000      93000000   
-----------------------------------
Hit any key to stop autoboot:  0
sunxi#

 

       输入命令 version,可以看到:

sunxi#version

U-Boot 2011.09-rc1 (Nov 26 2012 - 14:01:52) Allwinner Technology
arm-none-linux-gnueabi-gcc (Sourcery G++ Lite 2010.09-50) 4.5.1
GNU ld (Sourcery G++ Lite 2010.09-50) 2.20.51.20100809
sunxi#

      使用的编译器是arm-none-linux-gnueabi-gcc,版本4.5.1,但是俺的是4.3.2版本,为此我费了了老大劲,换成4.4.1时才编译成功

      有了上面的基本情况,开始编译制作,在XP下解压下载的u-boot-sunxi-sunxi.zip,删除board文件夹下除了allwinner文件的其他文件,board/allwinner文件夹内只需要保留common和Cubieboard两个文件夹,其他不需要;删除arch文件夹内除了arm文件的其他文件,arch/arm/cpu文件夹下只保留armv7和u-boot.lds,arch/arm/cpu/armv7内文件和sunxi文件夹保留,其他文件夹删除。这样做可以在Source Insight关联时减少关联项目,便于查阅,若还想更进一步,将include目录下与A10无关的头文件一并删除,关联时更加清晰。使用Source Insight 3.5建立一个工程,添加文件时选择u-boot解压文件夹,选择“add tree”,将全部文件加入工程,再选Project->Rebuilt Project...,如此一来,XP下的代码查阅工程就建立啦。

      linux下解压U-boot到自己工作目录,不需要删除操作。

      安装arm-2009q3.tar.bz2,在arm-2009q3.tar.bz2目录下输入命令:tar   -jxvf    arm-2009q3.tar.bz2   -C   /usr/local/arm/

     将编译器设置为默认arm编译器: vim   /etc/profile

                                在末尾增加一行: export=$PATH:/usr/local/arm/arm-2009q3/bin

                               保存退出之后执行:source    /etc/profile

      或者重启,或者logoout一下,使设置生效。以上设置适合RHEL5,其他linux系统请百度解决。

     

      编译U-boot:   make cubieboard CROSS_COMPILE=arm-none-linux-gnueabi-

      等待.........

      生成三个.bin文件,分别是u-boot.bin和spl目录下的sunxi-spl.bin、u-boot-spl.bin

     第1阶段bootloader:sunxi-spl.bin

     第2阶段bootloader:u-boot.bin

     u-boot-spl.bin我没试过,应该也是第一阶段的bootloader

 

     SD卡准备(我机器上是/dev/sdb),linux下操作:

     前面1M给bootloader使用(为什么?要仔细查查资料,目前我还不明白,望高人指点),先清零:

     dd   if=/dev/zero  of=/dev/sdb   bs=1M   count=1

     后面剩余的可以不管,也可分区,具体做法请百度

 

     将u-boot写入,只写入第1阶段bootloader,在u-boot目录操作:

                 dd  if=spl/sunxi-spl.bin  of=/dev/sdb   bs=1024    seek=8

     取下SD卡,插到板子上,上电,minicom有输出如下:

    

U-Boot SPL 2012.10 (Jan 23 2013 - 21:18:42)                               
DRAM: 1024MB                                                              
SUNXI SD/MMC : 0                                                

U-Boot SPL 2012.10 (Jan 23 2013 - 21:18:42)

      然后就死掉了,那是因为没有写入第2阶段,即u-boot.bin。

     从这一段输出,可以获得一些有用的信息,从打印信息入手,以便获取u-boot第一阶段代码运行轨迹。比较有特征的是“SUNXI SD/MMC”,在XP工程中搜索“SUNXI SD”(有斜杠就搜索不到,不知道为啥),可以定位到文件到..\drivers\mmc\sunxi_mmc.C的函数int sunxi_mmc_init(int sdc_no);
同样搜索“sunxi_mmc_init”.....最后得出调用关系如下,注意代码片段红色部分:
     

 文件..\u-boot-sunxi-sunxi\arch\arm\cpu\armv7\ start.S, 调用函数 board_init_f :         

     ......

 /* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
 ldr r0,=0x00000000
 bl board_init_f          //..\u-boot-sunxi-sunxi\arch\arm\lib\board.c

     ......

..\u-boot-sunxi-sunxi\arch\arm\lib\board.c文件的board_init_f对全局变量gd进行设置
void board_init_f(ulong bootflag)
{
    bd_t *bd;
    init_fnc_t **init_fnc_ptr;
    gd_t *id;
    ulong addr, addr_sp;
#ifdef CONFIG_PRAM
    ulong reg;
#endif    bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

/*

给gd分配一段空间,位置位于((CONFIG_SYS_INIT_SP_ADDR) & ~0x07),这一段内存位于片上32K的SDRAM内

结合CONFIG_SYS_INIT_SP_ADDR的定义../include/configs/sunxi-common.h:

#define CONFIG_SYS_INIT_RAM_ADDR    0x0             /*A10内部RAM起始地址*/

#define CONFIG_SYS_INIT_RAM_SIZE    0x8000       /*A10内部RAM,32K */

#define CONFIG_SYS_INIT_SP_OFFSET  (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR    (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

GENERATED_GBL_DATA_SIZE在编译时自动生成在文件../generated/generic-asm-offses.h内,值为128

最后计算的结果还是与CONFIG_SYS_INIT_SP_ADDR相等,为啥要& ~0x07,末尾按8字节对齐?

此时,gd位于片内的32K空间上

*/
    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");    memset((void *)gd, 0, sizeof(gd_t));    gd->mon_len = _bss_end_ofs;


#ifdef CONFIG_OF_EMBED  //没定义
        /* Get a pointer to the FDT */
        gd->fdt_blob = _binary_dt_dtb_start;
#elif defined CONFIG_OF_SEPARATE //没定义
       /* FDT is at end of image */
       gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
#endif
       /* Allow the early environment to override the fdt address */
       gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,  (uintptr_t)gd->fdt_blob );   

      for ( init_fnc_ptr = init_sequence;     *init_fnc_ptr;      ++init_fnc_ptr) {               

            if ((*init_fnc_ptr)() != 0) {
            hang ();
      }

/*

 init_sequence是一个函数表,for循环执行初始化,初始化定时器,串口,控制台等等

其中,gd->ram_size在列表最后一个函数中获得SDRAM的size,cubieboard是1G,确定内存有效的方法就是给等于2的次幂的地址写入一个数据,在读出比较

写入读出一致确认内存有效,只需要32次循环就可以检测4G空间,感兴趣的可以自行阅读代码内容,如果不看该列表内容,根本不知道原来这里面设置了gd->ram_size

因为下面条件汇编均不成立,没有设置gd->ram_size,最后又在使用这个值,莫名其妙

*/


 }#ifdef CONFIG_OF_CONTROL    //没定义
    /*For now, put this check after the console is ready */
    if (fdtdec_prepare_fdt()) {
        panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
              "doc/README.fdt-control");
    }
#endif    debug("monitor len: %08lX\n", gd->mon_len);
 /*
  * Ram is setup, size stored in gd !!
  */
    debug("ramsize: %08lX\n", gd->ram_size);
#if defined(CONFIG_SYS_MEM_TOP_HIDE)  //没定义
 /*
  * Subtract specified amount of memory to hide so that it won't
  * get "touched" at all by U-Boot. By fixing up gd->ram_size
  * the Linux kernel should now get passed the now "corrected"
  * memory size and won't touch it either. This should work
  * for arch/ppc and arch/powerpc. Only Linux board ports in
  * arch/powerpc with bootwrapper support, that recalculate the
  * memory size from the SDRAM controller setup will have to
  * get fixed.
  */
          gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
#endif   

         addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;    ////gd->ram_size就是上面设置的,addr=0x400000000 + 1G 即内存的最后一个地址0x80000000

#ifdef CONFIG_LOGBUFFER    //没定义
#ifndef CONFIG_ALT_LB_ADDR
    /* reserve kernel log buffer */
    addr -= (LOGBUFF_RESERVE);
    debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
          addr);
#endif


#endif#ifdef CONFIG_PRAM   //没定义
 /*
  * reserve protected RAM
  */
 reg = getenv_ulong("pram", 10, CONFIG_PRAM);
 addr -= (reg << 10);  /* size is in kB */
 debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
#endif /* CONFIG_PRAM */

 

#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))  //没定义
 /* reserve TLB table */
 addr -= (4096 * 4); /* round down to next 64 kB limit */
 addr &= ~(0x10000 - 1); gd->tlb_addr = addr;
 debug("TLB table at: %08lx\n", addr);
#endif

     /* round down to next 4 kB limit */
     addr &= ~(4096 - 1);    //4K空间给U-boot
     debug("Top of RAM usable for U-Boot at: %08lx\n", addr);

#ifdef CONFIG_LCD   //没定义 
#ifdef CONFIG_FB_ADDR
 gd->fb_base = CONFIG_FB_ADDR;
#else
 /* reserve memory for LCD display (always full pages) */
 addr = lcd_setmem(addr);
 gd->fb_base = addr;
#endif /* CONFIG_FB_ADDR */
#endif /* CONFIG_LCD */

/*
  * reserve memory for U-Boot code, data & bss
  * round down to next 4 kB limit
  */
      addr -= gd->mon_len;   //分配内存
      addr &= ~(4096 - 1);    //按4K对齐,gd->mon_len不到4K则分配4K

debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);#ifndef CONFIG_SPL_BUILD
 /*
  * reserve memory for malloc() arena
  */
       addr_sp = addr - TOTAL_MALLOC_LEN;  //设置sp的首地址,可见压栈地址向下递减,此时addr停留在距离sp长度为TOTAL_MALLOC_LEN的地方

                                                                    //TOTAL_MALLOC_LEN咋一看,应该是malloc的内存管理区域,是不是呢?往下看看      

       debug("Reserving %dk for malloc() at: %08lx\n",TOTAL_MALLOC_LEN >> 10, addr_sp);
 /*
  * (permanently) allocate a Board Info struct
  * and a permanent copy of the "global" data
  */
      addr_sp -= sizeof (bd_t);  //分配一段内存给全局变量gd的成员bd,sp指着往下移动

      bd = (bd_t *) addr_sp;
      gd->bd = bd;
      debug("Reserving %zu Bytes for Board Info at: %08lx\n",sizeof (bd_t), addr_sp);

#ifdef CONFIG_MACH_TYPE
 gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
#endif

      addr_sp -= sizeof (gd_t); //分配一段内存给全局变量gd(即id),sp指着继续往下移动
      id = (gd_t *) addr_sp;
      debug("Reserving %zu Bytes for Global Data at: %08lx\n",sizeof (gd_t), addr_sp);

     /* setup stackpointer for exeptions */
      gd->irq_sp = addr_sp;
#ifdef CONFIG_USE_IRQ
      addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
      debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
#endif
      /* leave 3 words for abort-stack    */
      addr_sp -= 12; /* 8-byte alignment for ABI compliance */
      addr_sp &= ~0x07;
#else
      addr_sp += 128; /* leave 32 words for abort-stack   */
      gd->irq_sp = addr_sp;
#endif

       debug("New Stack Pointer is: %08lx\n", addr_sp);  

/*      

执行到这里,内存基本分配已经出来了,从0x80000000往下,依次是:

       1、4K空间给U-boot ,干啥用的?
       2、gd->mon_len,按4K往上对齐,干啥用的?

       3、TOTAL_MALLOC_LEN,malloc内存池----堆空间

       4、gd的成员bd的空间

       5、gd的空间

       6、异常使用的栈

       7、栈-----SP开始的地方

*/

#ifdef CONFIG_POST   //没定义 
      post_bootmode_init();
      post_run(NULL, POST_ROM | post_bootmode_get(0));
#endif gd->bd->bi_baudrate = gd->baudrate;
 

/* Ram ist board specific, so move it to board code ... */
      dram_init_banksize();       //将ram的大小记录在gd内
      display_dram_config(); /* and display it */ gd->relocaddr = addr;   //显示内存大小,即minicom看到的打印内存大小那一行


      gd->start_addr_sp = addr_sp;   //将栈首地址记录在gd内
      gd->reloc_off = addr - _TEXT_BASE;   //记录U-boot代码段的偏移量,使用addr,由于拷贝时地址增加,因此代码紧邻malloc堆空间

      debug("relocation Offset is: %08lx\n", gd->reloc_off);
      memcpy(id, (void *)gd, sizeof(gd_t));   //将gd拷贝到id,即gd从片上32K空间转移到了外部SDRAM空间内了(id就在上面分配,地址是0x8xxxxxxx),为代码在内存上运行做准备

     relocate_code(addr_sp, id, addr);  

 /*

    重载relocate_code在start.S内部,是汇编代码,将参数传递过去,之后拷贝代码到addr开始的地方,

    将堆栈设置为addr_sp,为C语言代码运行准备栈,调用以后将不会再返回,进入内存运行。

    按照ARM编译时C函数传递规则,从第一个参数往后依次是r0,r1,r2.....

    可知:r0  <------ addr_sp

              r1  <------ id(即gd)

              r2  <------ addr

*/                                                      

     /* NOTREACHED - relocate_code() does not return */
}
 

再回到start.S,看看 重载relocate_code部分 :

/*------------------------------------------------------------------------------*/

#ifndef CONFIG_SPL_BUILD
/*
 * void relocate_code (addr_sp, gd, addr_moni)   //就是接上面而来的
 *
 * This "function" does not return, instead it continues in RAM
 * after relocating the monitor code.
 *
 */
ENTRY(relocate_code)
     mov r4, r0 /* save addr_sp */
     mov r5, r1 /* save addr of gd */
     mov r6, r2 /* save addr of destination */

    /* Set up the stack          */
stack_setup:
     mov sp, r4

     adr r0, _start
     cmp r0, r6            //r6现在指向SDRAM空间,r0指向的_start肯定不在外部SDRAM内(应该是在内部32K空间内),所以第1次这个比较是不相等的
     moveq r9, #0  /* no relocation. relocation offset(r9) = 0 */
     beq clear_bss  /* skip relocation */
     mov r1, r6   /* r1 <- scratch for copy_loop */          //将r6复制给r1,此时r1的值就是传递过来的addr,即是即将拷贝U-boot的起始地址
     ldr r3, _image_copy_end_ofs                               //需要拷贝的长度,这个需要看看lds文件的设置
     add r2, r0, r3  /* r2 <- source end address     */     //拷贝结束时的地址在若内

copy_loop:
     ldmia r0!, {r9-r10}  /* copy from source address [r0]    */   //从r0开始,即_start,拷贝一次4字节,r0自动+4
     stmia r1!, {r9-r10}  /* copy to   target address [r1]    */      //拷贝到r1开始的地方,即addr开始的地方,一次4字节,r1自动+4
     cmp r0, r2   /* until source end address [r2]    */              //检查是否到达最后一个地址,到了就结束拷贝
     blo  copy_loop

....................
 //接下一堆汇编,我承认没看懂
 ...................

直到下面,拷贝处理完成,跳到RAM中运行

/*
 * We are done. Do not return, instead branch to second part of board
 * initialization, now running from RAM.
 */
jump_2_ram:
/*
 * If I-cache is enabled invalidate it
 */
#ifndef CONFIG_SYS_ICACHE_OFF
     mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
     mcr     p15, 0, r0, c7, c10, 4 @ DSB
     mcr     p15, 0, r0, c7, c5, 4 @ ISB
#endif
/*
 * Move vector table
 */
#if !defined(CONFIG_TEGRA20)    //没定义
 /* Set vector address in CP15 VBAR register */
 ldr     r0, =_start
 add     r0, r0, r9
 mcr     p15, 0, r0, c12, c0, 0  @Set VBAR
#endif /* !Tegra20 */

 ldr r0, _board_init_r_ofs          //准备运行board_init_r函数
 adr r1, _start
 add lr, r0, r1     //计算通过偏移量计算出board_init_r的位置
 add lr, lr, r9      //这句是啥意思?是不是什么格式的偏移量?不懂
 /* setup parameters for board_init_r */   //看看函数原型void board_init_r(gd_t *id, ulong dest_addr),传递规则第一个参数r0,第二个参数r1.....
 mov r0, r5  /* gd_t */                
 mov r1, r6  /* dest_addr */
 /* jump to it ... */
 mov pc, lr   //调用RAM中的代码,从board_init_r开始,不在返回

 

接下来就是C代码了,依次调用往下,最后到搜索的地方,其实当初我是反过来从下面一个个往上找这个关系的

还用一堆问题,数据时怎么从SD卡读到内存的?????第一次读了多少?(只有start.o?),超过32k的内容是怎么拷贝进来的?

是不是上面那段我看不懂的汇编干的??诸多问题.....有待进一步研究 

..\u-boot-sunxi-sunxi\arch\arm\lib\board.c文件的board_init_r调用mmc_initialize
void board_init_r(gd_t *id, ulong dest_addr)
{

.....
#ifdef CONFIG_GENERIC_MMC
       puts("MMC:   ");  //这就是看到的打印信息的前一部分
       mmc_initialize(gd->bd);  //..\u-boot-sunxi-sunxi\drivers\mmc\mmc.c
#endif

.....
 /* main_loop() can return to retry autoboot, if so just run it again. */
 for (;;) {   //可见,若进入u-boot的命令模式,就在这个主循环工作,可以研究一下
  main_loop();
 }

 /* NOTREACHED - no way out of command loop except booting */
.....
}

..\u-boot-sunxi-sunxi\drivers\mmc\mmc.c文件的mmc_initialize调用board_mmc_init    
int mmc_initialize(bd_t *bis)
{
 INIT_LIST_HEAD (&mmc_devices);
 cur_dev_num = 0;

 if (board_mmc_init(bis) < 0)  //..\u-boot-sunxi-sunxi\board\allwinner\common\board.c
  cpu_mmc_init(bis);

 print_mmc_devices(',');

 return 0;
}

..\u-boot-sunxi-sunxi\board\allwinner\common\board.c文件的board_mmc_init调用sunxi_mmc_init
#ifdef CONFIG_GENERIC_MMC
int board_mmc_init(bd_t *bis) {

 sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);  //..\u-boot-sunxi-sunxi\drivers\mmc\sunxi_mmc.c
 return 0;
}
#endif

..\u-boot-sunxi-sunxi\drivers\mmc\sunxi_mmc.c文件的sunxi_mmc_init调用就是我们搜索的“SUNXI SD”
int sunxi_mmc_init(int sdc_no)
{
 struct mmc *mmc;

 memset(&mmc_dev[sdc_no], 0, sizeof(struct mmc));
 memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
 mmc = &mmc_dev[sdc_no];

 sprintf(mmc->name, "SUNXI SD/MMC");
 mmc->priv = &mmc_host[sdc_no];
 mmc->send_cmd = mmc_send_cmd;
 mmc->set_ios = mmc_set_ios;
 mmc->init = mmc_core_init;

 mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 mmc->host_caps = MMC_MODE_4BIT;
 mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;

 mmc->f_min = 400000;
 mmc->f_max = 52000000;

 mmc_host[sdc_no].pdes = (struct sunxi_mmc_des*)0x50000000;
 mmc_resource_init(sdc_no);
 mmc_clk_io_on(sdc_no);

 mmc_register(mmc);

 return 0;
}

 

 

     将u-boot写入,写入第2阶段bootloader,在u-boot目录操作:

                 dd  if=u-boot.bin  of=/dev/sdb   bs=1024    seek=32

     取下SD卡插到板子上,上电,minicom有输出如下:

U-Boot SPL 2012.10 (Jan 24 2013 - 21:42:50)                               
DRAM: 1024MB                                                              
SUNXI SD/MMC: 0                                                


U-Boot 2012.10 (Jan 24 2013 - 21:42:50) Allwinner Technology

CPU:   SUNXI Family
Board: Cubieboard
I2C:   ready
DRAM:  1 GiB
MMC:   SUNXI SD/MMC : 0
*** Warning - bad CRC, using default environment  //没做参数文件,使用默认参数

In:    serial
Out:   serial
Err:   serial
start main_loop...Hit any key to stop autoboot:  0
sun4i#

 

输入ersion命令:

sun4i#version

U-Boot 2012.10 (Jan 24 2013 - 21:42:50) Allwinner Technology
arm-none-linux-gnueabi-gcc (Sourcery G++ Lite 2009q3-67) 4.4.1
GNU ld (Sourcery G++ Lite 2009q3-67) 2.19.51.20090709
sun4i#

 

可以看到我使用的编译器是4.4.1版本的,低于原来板子自带u-boot编译器的版本

至此,U-boot的启动SD卡基本制作完成,接下来需要往里面增加新的功能,使其符合我的需求

1、练习,LED闪速.......这就是个毛病,拿到板子没看见LED在自己控制下闪烁就像程序没有运行一样....病的不轻

2、练习,增加一个测试命令

3、实战,增加Nand支持,实现读写,刷新,估计有现成模块可以使用,不会很难

4、增加网络支持,目前代码没有RTL8201CP的驱动,有rtl8139,rtl8169的驱动,可以参考,增加tftp功能,ping功能

5、将u-boot通过网络下载到内存,在写入nand,去掉SD卡,从nand启动,至此,u-boot移植可告一段落

以上每一步,若有所得,再来分享

                   

你可能感兴趣的:(u-boot学习)