分享

移植u-boot2009.08到OK2440V3开发板

 rookie 2012-12-15

移植u-boot2009.08到OK2440V3开发板(1)---方向与方法


       开发板到了之后,用的是板子自带的bootloader、linux内核和文件系统,在上面跑了几个小程序知道流程和方法后,就想着用自已移植的这些东西了,因为既然要搞底层的东西,我想这些东西还是要学会的。

      刚开始踌躇满志,以为不会有什么困难,网上不都多得是文章吗。可实际上,下了N多资料,看了N多文章之后,下到flash中一运行,串口控制台中什么都没 有,当时真有点蒙了。其实不成功,倒还没什么,关键是你想继续努力的时候,却没有方向和方法,那真的才是又浪费时间,又郁闷。

     不过还得感谢网络,文章看多了,就知道哪些可以直接close,那些可以复制下来慢慢看(我通常都是一气狂搜,一气“另存为”,最后再集中在一起看)。三五天后,终于找到了方向和方法,而且在sdram中运行,成功地在串口输出里看到了u-boot启动信息。
 
     第一次学做u-boot移植,综合别人的方法,总结归纳如下:
     1. 先不去考虑nor/nand flash启动,先让u-boot在SDARM中成功运行。
     2. 把那个既经典又简单又very useful的调试方法用上,那就是在程序中需要的地方加上led灯指示。
      (有时串口没信息,一头雾水,连自己的程序是否在运行都不知道,这里在程序开头加led的代码,最合适不过了)
     3. u-boot能在SDRAM中运行后,先考虑nor flash中运行(如果有nor flash的话),因为支持nor flash比支持nand flash改动少,较容易一些。SMDK2410里也是支持nor flash的,那里用的是AMD公司的。
     4. 能在flash 中启动后,增加nand支持,看是否能检测到nand,并在u-boot中用些nand的命令验证驱动是否有问题。
     5. 增加代码,让u-boot从nand启动。
     6. u-boot可是从nand启动后,增加代码,让代码能自动识别跳线的设置,从相应的flash启动。

     以上6步完成之后,关于启动方面的就完成了,如果有需要,再增加这个u-boot的其它功能,比如:网络支持、USB支持等,这些部分如果自已的开发板和SMDK2410不同的话,也是要做移植的。

     这个过程我正在进行中,已进行到第三步,前两部的具体实现过程在后面的文章中写出来,只为了自已以后用到的时候,有资料可查,不然忘了又得花时间,相当于做笔记吧。

移植u-boot2009.08到OK2440V3开发板(2)---在SDRAM中运行

(2009-12-8 17:07)
     
    其实这篇日记早就该出炉了,只因为在进行下一步(nor flash驱动)的移植中,遇到了麻烦,很大的麻烦,所以也没时间来写这一篇日记。nor flash驱动还没有搞定,自己花了太多的时间,又没人指导,身心疲惫,想先放一放,或者先跳过。于是现在来整理一下移植过程的第一步---u-boot 在SDRAM中运行。
 
       前一篇移植日记之所以把移植过程分那么多步,是因为这样可以减少问题出现的范围,也可以让自己更清楚所有的移植是怎样一步步做起来的。这一步是移植中最简单的,也是最基本的,先这样做可以为以后的移植搭好一个平台和框架。
 
       1.拷贝/board/samsung/目录下smdk2410文件夹到/board/samsung/下,取名为ok2440v3;并修改ok2440v3目录下的smdk2410.c文件的文件名为ok2440v3.c。(建立自己的开发板目录)
 
        2.拷贝/include/configs目录下smdk2410.h,并重命名为ok2440v3.h(建立自己的开发板的配属文件);
           因为我们是在SDRAM中运行,所以在此文件中定义两个宏,不拷贝代码到ram中和不进行底层初始化:
           #define CONFIG_SKIP_LOWLEVEL_INIT         1   
           #define CONFIG_SKIP_RELOCATE_UBOOT    1    
 
        3.修改顶层Makefile文件,在smdk2410_config后面添加ok2440v3_config,如下所示:(设置自己的开发板的编译配置)
           # added by liweikui for supporting OK2440V3
           ok2440v3_config : unconfig                                                   
           @$(MKCONFIG) $(@:_config=) arm arm920t ok2440v3 samsung s3c24x0

        4.修改顶层Makefile文件,在CROSS_COMPILE ?=后面添加自己的交叉编译工具。(设置交叉编译工具)
         CROSS_COMPILE ?= /usr/local/arm_across/4.3.2/bin/arm-linux-

        5.修改/board/samsung/ok2440v3目录下的Makefile文件中的COBJS,如下所示:
          COBJS    := ok2440v3.o flash.o

        上面这几步是很通用的了,到这里,就可以用下面两条命令编译,测试一下是否可以生成最后的u-boot.bin文件:
           make ok2440v3_config
           make

       成功生成u-boot.bin文件后,对于CPU为s3c2410,控制台串口用的是串口0的开发板来说,应当就可以使用了。但对于s3c2440来说,运行这个bin文件是没有串口输出的!

************************************
       
       原来,2440与2410的一个重要的区别就是,在相同的外部时钟(12M)的情况下,默认得到的内部时钟FCLK/HCLK/PCLK是不一样的,而这些时钟会影响到口串口的波特率。具体修改如下:
        1.修改/cpu/arm920t/start.S中的相关部分:
(1)先在相应位置增加如下宏定义:
#  define LOCKTIME      0x4C000000
#  define MPLLCON        0x4C000004
#  define UPLLCON        0x4C000008
#  define CAMDIVN       0x4C000018

(2) 修改禁止中断部分,2440比2410的中断多了几位,相应部分,修改如下:
    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov    r1, #0xffffffff
    ldr    r0, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2410)   
    ldr    r1, =0x7fff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

(3)中断修改完后,新增下述两个寄存器的配置:
       //locktime用来在正常运行时更改时钟的时候保护时钟
       ldr r0,=LOCKTIME
       mov r1,#0xffffff
       str r1,[r0]

         //清除摄像头分频寄存器值,这个值会影响HCLK
       ldr r0,=CAMDIVN
       mov r1,#0
       str r1,[r0]

(4)关于时钟的初始化部分,把相应部分替换为:
    //初始化时钟,晶振为12MHz,主频为405MHz
    /* FCLK:HCLK:PCLK = 1:4:8 */
     ldr   r0, =CLKDIVN
     mov r1, #5
     str    r1, [r0]

       //在2440的手册中写着若HDIVN不为0,则需要下面几句
       mrc  p15, 0, r1, c1, c0, 0         //read ctrl register
       orr   r1, r1, #0xc0000000          //Asynchronous
       mcr  p15, 0, r1, c1, c0, 0         //write ctrl register

       //USB时钟48MHz       (56<<12)+(2<<4)+(2)
       ldr   r0, =UPLLCON
       ldr   r1, =0x00038022
       str    r1, [r0]

       //arm920t为5级流水线,延迟几个周期,使指令生效
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop

         //写MPLL使pll生效,405MHz,(127<<12)+(2<<4)+(1)
       ldr   r0, =MPLLCON
       ldr   r1, =0x0007f021
       str    r1, [r0]


   (注:上述的遇到CONFIG_S3C2410保持原样,如果要u-boot能分辩2410与2440的话,定义CONFIG_S3C2440后,改的地方很多,为了抓住移植的关键部分,我暂没有那样做)

         2.修改/board/samsung/ok2440v3目录下ok2440v3.C文件中关于时钟的部分,如下所示:
     #elif FCLK_SPEED==1        /* Fout = 405MHz FCLK:HCLK:PCLK = 1:4:8 */
     #define M_MDIV    0x7f
     #define M_PDIV    0x2
     #define M_SDIV    0x1

         3.因为2440与2410对FCLK的计算公式不一样,所以还要修改/cpu/arm920t/s3c24x0/speed.c文件中FCLK的计算:
把下面的部分:
    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
替换为:
    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
    if(pllreg == MPLL)
        return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
    else
            return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

          4.修改/cpu/arm920t/s3c24x0/speed.c中的 get_HCLK函数如下:
     /* return HCLK frequency */
     ulong get_HCLK(void)
     {
     S3C24X0_CLOCK_POWER * const clk_power =        S3C24X0_GetBase_CLOCK_POWER();

       //return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
       return (get_FCLK()/4);       //for s3c2440 1:4:8 !!!
}

        (注:这里的修改采取了一个简单的,但适应性不好的改法,只用于FCLK:HCLK:PCLK = 1:4:8的情况,如果要完整修改的话,按2440的数据手册,这里不能这么简单处理。如何做,网上很多,可以找到)

       到这里,关于串口的修改就结束了。说来不怕笑话,因为这个问题,我也被搞了两天,一直没串口输出,问题不难,却真的是一个时钟频率引发的血案啊,呵呵。。

       好了,做完上面所有修改后,执行make ok2440v3_config与make,生成u-boot.bin,下载到SDRAM中,就可以从串口看到信息了。

*************************************

       如果在实验中遇到了问题,可以用led灯来跟踪的方法,这里,我附上针对OK2440V3开发板的点亮led灯的汇编代码和C代码:

/* leds for testing and tracing ,GPF3-6 : LED0-3 */
#define GPFCON  0x56000050
#define GPFDAT  0x56000054
#define GPFUP   0x56000058

    ldr    r0,=GPFUP              // 0:enable pull up ; 1:disable pull up
    ldr    r1,=0xfffff87          //使能上拉F3-6
    str    r1,[r0]

    ldr    r0,=GPFCON
    ldr    r1,=0xd57f            //将F3-6设为输出口
    str    r1,[r0]

    ldr    r0,=GPFDAT
    ldr    r1,=0xf7             //点亮LED0 (不同的地方我们可以点亮不同的灯)
    str    r1,[r0]
/* end of leds testing */

/* leds test for ok2440v3 */
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
gpio->GPFCON = 0xd57f;         //将F3-6设为输出口
gpio->GPFUP  = 0xfffff87;      //使能上拉F3-6
gpio->GPFDAT = 0xe7;           //再点亮LED1

(注:若要使用上述C语言的led测试程序,需包含头文件 s3c2410.h)

*******************************

       这里再总结一下,在这一移植过程中,我们要关注的有哪些文件:
1.两个Makefile文件,顶层Makefile和自已的开发板下的Makefile;
2.自已的开发板下ok2440v3.c文件;
3.启动后执行的第一个文件,/cpu/arm920t/start.S;
4.C语言入口文件/lib_arm/board.c,start.S执行完后跳到此文件执行;
5.和时钟计算相关的文件/cpu/arm920t/s3c24x0/speed.c
6.板级初始化/board/samsung/ok2440v3/ok2440v3.C文件
7.板级配置文件/include/configs/ok2440v3.h

移植u-boot2009.08到OK2440V3开发板(3)---nor flash启动

(2009-12-10 19:43)

      前面一篇移植关键在于串口输出的部分,当时花了我2,3天时间,我叫它“一个时钟引发的惨案”,现在想起来,那还是小的,这篇日记要记录的,整整花了我一个星期的时间!真的可以叫做“一个驱动引发的血案”了,呵呵。

    本来如果只是支持从nor flash启动倒是不难,u-boot的启动过程中只用到了一个flash的初始化函数。如下所示:

#ifndef CONFIG_SYS_NO_FLASH
    /* configure available FLASH banks */
    display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */

       关键是,我没有在linux下烧写我这款nor flash的工具!我必须要切换到windows下才行,这太麻烦了,我就想在u-boot里把我这款nor flash的驱动搞定,包括保护、去保护、擦除、读写等,好让u-boot启动后能使用flash的命令,然后烧写nor flash。这一想不要紧,在u-boot里找到的驱动程序有问题。为了解决这个问题,自己又不想放弃,“血案”就这样发生了,呵呵。

       不过一个星期后的痛苦挣扎后,问题总算解决了。(虽然问题不大,但对我这样的新手来说,又没人指导,有时一个小问题真的会让人郁闷透顶!)

*************************************

       下面先看如何在u-boot中支持nor flash的烧写,我的开发板上的nor flash芯片是Intel的JS28F320(4MB)(1device=32blocks,1block=128MB)。为了缩小问题发生的范围,我们还是先让u-boot在SDRAM中运行(仍然要定义那两个宏定 义:不复制代码到SDARM和不进行底层初始化)。当然,在SDRAM中运行前,需要用别的初始化程序先初始化内存才行。
       下面的操作都是前一篇移植完成后的基础上进行的。

       1. 把开发板的配置文件ok2440v3.h(/include/configs/ok2440v3.h)中关于flash的配置部分都删掉,换成下面的配置:
/*-----------------------------------------------------------------------
 * Physical Memory Map
 */
#define CONFIG_NR_DRAM_BANKS    1                /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1              0x30000000       /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE    0x04000000        /* 64 MB */

#define PHYS_FLASH_1        0x00000000               /* Flash Bank #1 */
#define CONFIG_SYS_FLASH_BASE         PHYS_FLASH_1
#define CONFIG_SYS_MONITOR_BASE   TEXT_BASE
#define FLASH_BASE0_PRELIM                 PHYS_FLASH_1

/*------------------------------------------------------------
 * FLASH and environment organization
 */
#define CONFIG_SYS_FLASH_PROTECTION   1
#define CONFIG_SYS_MAX_FLASH_BANKS     1       /*max number of memory banks*/
#define CONFIG_SYS_FLASH_SIZE    0x00400000    /*4 MB*/
#define CONFIG_SYS_MAX_FLASH_SECT    32         /*max number of sectors on one chip*/

/*timeout values are in ticks*/
#define CONFIG_SYS_FLASH_ERASE_TOUT    (2*CONFIG_SYS_HZ) /*Timeout for Flash Erase*/
#define CONFIG_SYS_FLASH_WRITE_TOUT    (2*CONFIG_SYS_HZ) /*Timeout for Flash Write*/

#define CONFIG_ENV_IS_IN_FLASH    1
#define CONFIG_ENV_SIZE        0x20000       /*128KB*/
#define CONFIG_ENV_OFFSET  0x40000

      2.把开发板目录下flash.c文件替换成下面的/board/cmi/下面的flash.c文件,然后删除这个write_short函数的申明和定 义、删除write_buff函数。替换成下面的两个函数:(为了不占篇幅,我把这两个函数单独写在名为<<Intel JS28F320 nor flash 的write_buff函数>>这篇日记中。

      3. 修改flash.c文件中的一个宏定义:
把:
#define FLASH_BLOCK_SIZE        0x00010000
改为:
#define FLASH_BLOCK_SIZE        0x00020000
         
     上述3步完成后,生新编译,下载u-boot.bin文件到SDRAM中运行,便可看到u-boot检测到了我们的flash。用flinfo命令可以看 到具体的块信息,还可以用flash的各种命令对flash进行操作,从而实现这块nor flash驱动的完全支持。烧写当然也是没问题的了,把需要烧写的文件下载到SDRAM中后,用cp.b命令就可以了。

      下面大该分析一下这个驱动文件的函数调用,此flash.c文件中有如下几个函数:

static ulong  flash_get_size         (vu_short *addr, flash_info_t *info);
static void     flash_get_offsets     (ulong base, flash_info_t *info);
static int        write_word (flash_info_t *info, ulong dest, ushort data)

unsigned long flash_init (void)
void flash_print_info  (flash_info_t *info)
int flash_erase (flash_info_t *info, int s_first, int s_last)
int flash_real_protect(flash_info_t *info, long sector, int prot)
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)

      1.u-boot启动只会用到flash.c文件中的flash_init函数,正如上面所述;
      2.以static修饰的3个函数只在flash.c文件中被调用;
      3.最后面的4个函数会被/common/cmd_flash.c文件中的函数调用,以实现u-boot下的各种命令操作。

*************************************

    上面的操作做完之后,如果没有问题,我们就可以考虑让u-boot从nor flash启动了。为了实现这个目的,有下面几步操作:

      1.注释或删除掉下面的两个宏定义:
//#define CONFIG_SKIP_LOWLEVEL_INIT     1   
//#define CONFIG_SKIP_RELOCATE_UBOOT    1  

     2.修改开发板目录下的lowlevel_init.S文件中SDARM刷新参数为:
#define REFCNT    1258    /* period=7.8125us, HCLK=405/4 Mhz, (2048+1-7.8125*405/4) */

     重新编译,设置好开发板上的跳线,下载到nor flash中,重启开发板,串口控制台看到u-boot启动成功!

****************************************

      后记:
      也许,很多人觉得这篇文章的移植怎么会花了一个星期这么长时间,现在想来,我自己也不太相信,不过确是事实。那是哪里出错了呢,现特记录下来,以提醒自己:

      1. CONFIG_SYS_FLASH_ERASE_TOUT和 CONFIG_SYS_FLASH_WRITE_TOUT定义出错。首先我用的就是拷贝过来的参数,不行,我又把它增大了一倍,有改善,便还是不行。原 因:不要把time out直接定义为以ms为单位的值,要定义为以“ticks“为单位的值,即次数。因为在驱动中进行比较时,get_timer得到的值就是PWM4定时 器中的值经过一些计数后得到的。

     2.  FLASH_BLOCK_SIZE定义错,应当以字节为单位,是20000,而不是以半字为单位为10000。我之前一直以为,我的flash是16位位宽的,那就当以半字为单位,其实不是这样的。

     3.刷新参数没改正确,我之前都是用别人的值,因为别人的也是2440,后来不这样想了,自已计算!从而解决问题!因为这个还和时钟有关!

移植u-boot2009.08到OK2440V3开发板(4)---nand flash识别与操作

(2009-12-13 20:06)

    出了问题是痛苦的,但是解决了问题又是让人兴奋的。摸爬滚打三四天后,我的u-boo终于可以正确识别nand flash了!也许就是这一次次,哪怕是一瞬间的兴奋,才让自己坚持了下来。郁闷几天又如何,呵呵。

    正如此系列日记的第一篇所述,为了降低解决问题的难度,缩小问题问题出现的范围,我们先在这篇日记中完成nand驱动支持这个功能,能在u-boot中对nand进行各种命令操作,从nand启动u-boot的功能在下篇日记中完成。

**********************************************************************************************

     为了支持nand,我们必须知道nand是如何与u-boot作用的,我们先来看这个版本中nand驱动框架。

      网上看了很多的相关资料,都说nand驱动有两种不同的实现流程和框架,取决于是否定义CONFIG_NAND_LEGACY,其实这个现象在u- boot2009.08这个版本中已经不存在了。nand驱动现在用的就是和linux内核一样的MTD(内存技术设备)架构,这个在u-boot根目录 下有清楚的说明:

     The current NAND implementation is based on what is in recent
Linux kernels.  The old legacy implementation has been removed.

      If you have board code which used CONFIG_NAND_LEGACY, you'll need
to convert to the current NAND interface for it to continue to work.

     说来好笑,我为了弄清这个问题,尽然在网上到处确认,现在的nand驱动架构是什么样子,原来真的是舍近求远了,浪费了些时间。这也是引发我写<<自学嵌入式中的点点滴滴>>这篇日记的原因之一。

*****************************************************************************************

     我们先从u-boot启动过程中,以s3c2410为例,怎样调用到nand驱动这个角度来分析。还有另外一个角度,那就是在u-boot中执行某一nand命令时,从上到下到底发生了什么。

     u-boot启动到第二个阶段后,在/cpu/arm920t/board.c这个文件中start_armboot函数里,有下面的代码:
#if defined(CONFIG_CMD_NAND)
    puts ("NAND:  ");
    nand_init();        /* go init the NAND */
#endif

     所以,我们只要定交了CONFIG_CMD_NAND这个宏,就会开始nand初始化。通过用KScope(Linux下的一个不错的IDE,可用来做代码分析)来一步步地查看函数执行过程,得出下面的nand执行流程:

1./cpu/arm920t/board.c文件中的start_armboot函数调用/drivers/mtd/nand/nand.c文件中的nand_init函数;
2.nand_init调用同文件下的nand_init_chip函数;
3.nand_init_chip函数调用/drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函数,然后再调用/drivers/mtd/nand/nand_base.c函数中的nand_scan函数;
4.s3c2410_nand.c就是我们做移植需要实现的文件,是与具体的硬件密切相关的。
5.nand_scan函数会调用同文件下的nand_scan_ident等函数。

     从这里我们得知,我们要把nand移植到2440上,就要修改s3c2410_nand.c这个文件!因为对nand flash的操作,实际上就是对nand控制器的操作,而2440的nand控制器和2410相比,有很大的不同!我们的修改工作量主要也是在这里。 s3c2410与s3c2440具体有什么区别,请看我的另一篇日记<<s3c2410与s3c2440的全方位对比>>

*********************************************************************************

     下一步就是根据s3c2440的手册中nand控制器部分修改s3c2410_nand.c文件,我们在同目录下(/drivers/mtd/nand /)复制此文件,并重命名为s3c2440_nand.c,下面我们来对s3c2410_nand.c文件进行修改:
(这里我使用的是网上别人的函数,文末有说明)

  1.修改s3c2410_nand.c文件中NAND Flash控制器的相关定义:
  (针对S3C2440 NAND Flash控制器的不同来重新定义一些寄存器,把原文件中对s3c2410 nand寄存器的定义删除,重新定义如下)

#define    NF_BASE        0x4e000000
#define    NFCONF         __REGi(NF_BASE + 0x0)
#define     NFCONT        __REGi(NF_BASE + 0x4)
#define    NFCMD           __REGb(NF_BASE + 0x8)
#define    NFADDR         __REGb(NF_BASE + 0xc)
#define    NFDATA          __REGb(NF_BASE + 0x10)
#define     NFMECCD0    __REGi(NF_BASE + 0x14)
#define     NFMECCD1    __REGi(NF_BASE + 0x18)
#define     NFSECCD       __REGi(NF_BASE + 0x1C)
#define    NFSTAT           __REGb(NF_BASE + 0x20)
#define    NFSTAT0         __REGi(NF_BASE + 0x24)
#define    NFSTAT1         __REGi(NF_BASE + 0x28)
#define    NFMECC0        __REGi(NF_BASE + 0x2C)
#define    NFMECC1        __REGi(NF_BASE + 0x30)
#define    NFSECC           __REGi(NF_BASE + 0x34)
#define    NFSBLK           __REGi(NF_BASE + 0x38)
#define    NFEBLK           __REGi(NF_BASE + 0x3c)

#define S3C2440_NFCONT_nCE    (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08

    2.增加一个全局变量:ulong IO_ADDR_W = NF_BASE;

    3.修改s3c2410_nand.c文件的s3c2410_hwcontrol函数和board_nand_init函数:
      (为了不在这里占篇幅,具体修改的内容请看我的另一篇日记<<s3c2440的hwcontrol和board_nand_init函数>>)

    4.除了以上对3c2410_nand.c的文件进行修改之外,我们还要在开发板的配置文件中(ok2440v3.h)定义支持nand的相关的宏:

/* Command line configuration. */
......

#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING

#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif

/* NAND flash settings */

#if defined(CONFIG_CMD_NAND)
#define CONFIG_NAND_BASE 0x4E000000
#define CONFIG_MAX_NAND_DEVICE     1    
#define CONFIG_MTD_NAND_VERIFY_WRITE  1
#define NAND_SAMSUNG_LP_OPTIONS       1    /*注意,这个定义很重要,因为我们用的是大块nand!!我就是因为没定义这里卡了较长时间 */

#undef  CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_IS_IN_NAND     1      /* 环境变量的保存位置 */
#define CONFIG_ENV_SIZE    0x20000    
#define CONFIG_ENV_OFFSET  0x40000

#endif

    5.我们要把新建立的这个文件编译进去,所以要修改相同目录(/drivers/mtd/nand/)下的Makefile文件:

在相应位置加入:                
COBJS-y += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o   

    6.我们为了在SDRAM中调试,定义上下面的两个宏定义,下载到SDRAM中运行:
#define CONFIG_SKIP_LOWLEVEL_INIT     1  
#define CONFIG_SKIP_RELOCATE_UBOOT    1  

   7.编译,下载到SDRAM中运行,成功检测到nand:
                                     
U-Boot 2009.08 (12栽? 13 2009 - 18:03:40)      

DRAM:  64 MB
Flash:  4 MB
NAND:  128 MiB     
*** Warning - bad CRC, using default environment
In:    serial
Out:   serial
Err:   serial
OK2440V3 #
OK2440V3 # nand info
Device 0: NAND 128MiB 3,3V 8-bit, sector size 128 KiB                           
OK2440V3 #

    进行nand命令的基本操作,nand info、nand dump、nand read、nand write,都能够成功!

**********************************************************************************

    下面列一下,此篇移植中,我们需关注的文件:
/cpu/arm920t/board.c
/drivers/mtd/nand/nand.c
/drivers/mtd/nand/s3c2410_nand.c
/drivers/mtd/nand/nand_base.c
/driver/mtd/nand/Makefile
/include/configs/ok2440v3.h

移植u-boot2009.08到OK2440V3开发板(5)---nand flash启动

(2009-12-16 21:35)

    在完成前面的nand flash识别与操作后(在nor flash中运行,检测到nand外设并可对其用u-boot命令进行操作),让u-boot从nand中启动,就相对比较简单了。当然,这个简单的前提 是是,有开发板自带的bootloader中的nand启动代码可参考。

    移植的重要关键部分是是代码的拷贝,从nand拷贝到sdram。从编程的角度看,nor flash是存储设备,而nand是I/O外设,对它们的底层操作有本质的不同。u-boot中对ARM的支持部分,没有支持nand启动的代码,只有 nor flash的,拷贝u-boot的那部分代码只适用于nor flash,不适用于nand。

    1. 删除或注释掉原来的 relocate 部分,用飞凌公司提供的bootloader中的nand启动相关部分来替代。由于这个bootloader用的是汇编语言环境是armasm的,不是 GUN ARM的,所以要进行一些语法上的转换。转换之后的结果如下:

/**********************************************************/
//如果是从nand启动,到这里执行
//将程序从nandflash拷贝到sdram

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

#define NFCONF  0x4E000000

relocate_nand:                /* relocate U-Boot to RAM        */
    adr    r0, _start             /* r0 <- current position of code   */
    ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
    cmp     r0, r1                  /* don't reloc during debug         */
    beq     stack_setup

    mov    r5, #NFCONF
    //set timing value
    ldr    r0,    =(7<<12)|(7<<8)|(7<<4)
    str    r0,    [r5]
      //enable control
    ldr    r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
    str    r0, [r5, #4]

    bl    ReadNandID
    mov    r6, #0
    ldr    r0, =0xecF1
    cmp    r5,    r0
    beq    1f
    ldr    r0, =0xec76
    cmp    r5, r0
    beq    1f
    mov    r6, #1
1:     
    bl    ReadNandStatus
     
    mov    r8, #0
    ldr    r9, =_start
    mov   r10, #128          //u-boot 256k,128页    --这里原来是32!!
2:     
    ands    r0, r8, #0x3f    //如果是第一页,则检测坏块
    bne        3f
    mov        r0, r8
    bl        CheckBadBlk
    cmp        r0, #0
    addne    r8, r8, #64    //每块的页数  
    addne    r10,r10,#64 //+081010 feiling
    bne        4f
3:     
    mov    r0, r8
    mov    r1, r9
    bl    ReadNandPage
    add    r9, r9, #2048    //每页的字节数
    add    r8, r8, #1        //页数+1
4:     
    cmp    r8, r10   //要拷贝的页数 081010 pht:#32->r10 
    bcc    2b
     
    mov    r5, #NFCONF            //DsNandFlash
    ldr    r0, [r5, #4]
    bic r0, r0, #1
    str    r0, [r5, #4]

#endif

     (注意上面的mov   r10, #128 那一句,把拷贝的页数改大一些,原来是32。我之前,怎么都没调通,就是因为这里,因为u-boot编译出来比飞凌的bootloader大多了)

    2. 上述代码中用到的几个子函数ReadNandID、ReadNandStatu、 WaitNandBusy、CheckBadBlk、ReadNandPage也一同拷贝过来,并进行简单的一些语法修改。

    3. s3c2440的两种启动方式,nor 和 nand 启动在原理上不些不同,若从nor 启动,就是直接从nor flash的0地址开始执行(flash 映射到bank0),可以执行flash的内部的任意地址的内容。而从nand启动,是在运行之前,由CPU自动地拷贝nand的前4K的内容到内部的 4K RAM中,再从内部的这个RAM中的0地址开始执行。所以我们必须保证在跳到SDARM运行之前的所有代码,都在前4K范围之内。

     而通过查看编译后u-boot根目录下的u-boot.map文件可知,lowlevel_init.o并不在
前4K的范围:

 .text          0x33f948e0       0x9c board/samsung/ok2440v3/libok2440v3.a(lowlevel_init.o)
                0x33f948e4                lowlevel_init  // (u-boot的起始地址为0x33f80000)

    所以我们要修改/cpu/arm920t/u-boot.lds文件,使lowlevel_init.o在前4K范围:

    .text :
    {
        cpu/arm920t/start.o    (.text)
        board/samsung/ok2440v3/lowlevel_init.o (.text)
        *(.text)
    }

   修改后,重新编译,再次查看,已在前4K,如下:

 board/samsung/ok2440v3/lowlevel_init.o(.text)
 .text          0x33f80700       0x64 board/samsung/ok2440v3/lowlevel_init.o
                  0x33f80704                lowlevel_init

   把编译之后的u-boot.bin文件下载到nand 中,重新启动,串口控制台得出正确的启动信息,完成。

OK2440V3 # reset                                                               
resetting ...                                                                  
                                                                               
                                                                               
U-Boot 2009.08 (12栽? 16 2009 - 20:30:08)                                     
                                                                               
DRAM:  64 MB                                                                   
## Unknown FLASH on Bank 0: ID 0xffff, Size = 0x00000000 = 0 MB                
Flash:  0 kB                                                                   
NAND:  128 MiB                                                                 
*** Warning - bad CRC, using default environment                               
                                                                               
In:    serial                                                                  
Out:   serial                                                                  
Err:   serial                                                                  
OK2440V3 #

    后记:这篇移植就两个重点,一是修改复制u-boot时要复制nand的页数,一是lowlevel_init.o的连接位置保证在前4K。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多