zoukankan      html  css  js  c++  java
  • mini2440移植uboot 2014.04(一)

    最新版的uboot添加了很多新功能,我决定在最新版代码基础上重新移植一遍加深理解。

    我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git

    参考文档: s3c2440手册(下载地址) mini2440电路图(下载地址

    参考我的两篇博文:

    mini2440移植uboot 2011.03(上)

    mini2440移植uboot 2011.03(下)

    还有其他几篇文章:

    u-boot2012.04.01移植到mini2440

    一步一步将uboot移植到mini2440(-)

    DM9000驱动在MINI2440上的移植学习笔记

    操作系统: debian 7.4

    uboot:   u-boot-2014.04(下载地址

    交叉编译器:arm-linux-gcc 4.4.3(下载地址

    在移植之前,最好对uboot的代码执行流程有基本的了解,可以参考我的三篇博文:

    uboot 2013.01 代码简析(1)开发板配置

    uboot 2013.01 代码简析(2)第一阶段初始化

    uboot 2013.01 代码简析(3)第二阶段初始化

    (一)将smdk2410的文件夹拷贝成mini2440,步骤如下:

    host@debian:~/soft/mini2440/u-boot-2014.04$ vim boards.cfg 
    添加一行:
    Active  arm         arm920t        s3c24x0     friendlyarm       -       mini2440         -         Qiao<qiaoyuguo2012@gmail.com>
    host@debian:~/soft/mini2440/u-boot-2014.04$ mkdir board/friendlyarm
    host@debian:~/soft/mini2440/u-boot-2014.04$ cp -r board/samsung/smdk2410/ board/friendlyarm/mini2440
    host@debian:~/soft/mini2440/u-boot-2014.04$ mv board/friendlyarm/mini2440/smdk2410.c  board/friendlyarm/mini2440/mini2440.c
    host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/Makefile
    将其中smdk2410.o替换成mini2440.o
    host@debian:~/soft/mini2440/u-boot-2014.04$ cp include/configs/smdk2410.h  include/configs/mini2440.h

    然后进行编译:

    host@debian:~/soft/mini2440/u-boot-2014.04$ make mini2440_config
    host@debian:~/soft/mini2440/u-boot-2014.04$ make  CROSS_COMPILE=arm-linux-

    编译过程中最后部分的输出信息:

      OBJCOPY u-boot.srec
      OBJCOPY u-boot.bin

    (二)添加SDRAM支持

    host@debian:~/soft/mini2440/u-boot-2014.04$ vim include/configs/mini2440.h 
    删除三行:
    #define CONFIG_S3C2410         /* specifically a SAMSUNG S3C2410 SoC */
    #define CONFIG_SMDK2410                /* on a SAMSUNG SMDK2410 Board */
    #define CONFIG_SYS_TEXT_BASE 0x0
    添加四行: #define CONFIG_S3C2440 /* specifically a SAMSUNG S3C2440 SoC */ #define CONFIG_MINI2440 /* on a FriendlyArm MINI2440 Board */ #define CONFIG_SKIP_LOWLEVEL_INIT
    #define CONFIG_SYS_TEXT_BASE 0x33f80000

    arch/arm/cpu/arm920t/start.S中的包含有看门狗、中断以及时钟的配置,而s3c2410和s3c2440的部分配置不一样,所以需要适当的进行修改

    首先需要禁止看门狗,根据s3c2440芯片手册(下载地址) ,看门狗寄存器地址如下:

    WTCON 0x53000000 Watchdog timer control
    WTDAT 0x53000004 Watchdog timer data WTCNT 0x53000008 Watchdog timer count

    我们只需要禁止看门狗,这样就只需要考虑WTCON寄存器就可以,从手册的462页中可以看到WTCON详细信息

    当前的uboot代码已经满足了禁止看门狗的功能,其代码如下(忽略无关的宏定义,仅列出我们所关心的代码,下同):

    define pWTCON    0x53000000
        ldr    r0, =pWTCON
        mov    r1, #0x0
        str    r1, [r0]

    这段代码将0加载到0x53000000处,从而禁止了看门狗(详细每位数据的含义可以查看手册)。

    接着是关于中断的配置,根据s3c2440芯片手册56页,中断相关寄存器地址如下:

    复制代码
    SRCPND 0X4A000000 R/W Interrupt request status
    INTMOD 0X4A000004 W Interrupt mode control
    INTMSK 0X4A000008 R/W Interrupt mask control
    PRIORITY 0X4A00000C W IRQ priority control 
    INTPND 0X4A000010 R/W Interrupt request status
    INTOFFSET 0X4A000014 R Interrupt request source offset
    SUBSRCPND 0X4A000018 R/W Sub source pending INTSUBMSK 0X4A00001C R/W Interrupt sub mask
    复制代码

    我们需要配置中断屏蔽寄存器(INTMSK,见手册388-389页)和子中断屏蔽寄存器(INTSUBMSK,见手册395页),可以看到当前代码如下:

    复制代码
    #  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
    #  define INTSUBMSK    0x4A00001C
            mov    r1, #0xffffffff
            ldr    r0, =INTMSK
            str    r1, [r0]
    # if defined(CONFIG_S3C2410)
          ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif
    复制代码

    该代码中断屏蔽寄存器的代码仍然使用于s3c2440,但是需要添加子中断屏蔽寄存器的代码,可以在s3c2410相关代码中添加elseif语句:

    #elseif defined(CONFIG_S3C2440)
           ldr     r1, =0x7fff
           ldr     r0, =INTSUBMSK
           str     r1, [r0]

    根据手册,s3c2440中子中断屏蔽寄存器有效位数是低15位,所以我们用0x7fff,使得低15位为1(1表示屏蔽该中断,0表示该中断可用).

    接着是时钟分频配置,现有代码如下:

    #  define CLKDIVN   0x4C000014  /* clock divisor register */

    /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0]

    上面代码中提到了FCLK、HCLK、PCLK(参见手册242页),FCLK用于arm920T,HCLK用于AHB,可以用于USB、DMA、LCD、中断和内存控制器等。

    PCLK用于APB,可以用于看门狗、IIS、I2C、SPI、ADC、UART、GPIO、RTC等。

    当前代码默认采用1:2:4的分频配置,但是mini2440我们要将cpu频率配置成400MHz。

    根据手册33页,FCLK最大只能是400MHz,HCLK最大只能是136MHz,PCLK最大只能是68MHz。

    要满足时钟频率的限制,可以将分频配置成1:4:8,那么FCLK=400MHz,HCLK等于100MHz,PCLK等于50MHz,都能满足要求。

    关于CLKDIVN寄存器的定义,可以查看手册258页,给出了下面的信息:

    CLKDIVN 0x4C000014 R/W Clock divider control register 

    HDIVN [2:1] 10 : HCLK = FCLK/4 when CAMDIVN[9] = 0,HCLK= FCLK/8 when CAMDIVN[9] = 1.
    PDIVN [0]  如果为0: PCLK has the clock same as the HCLK/1 如果为1: PCLK has the clock same as the HCLK/2.

    而CAMDIVN寄存器定义可以查看手册259页,能看到默认所有位等于0,这样只需要配置HDIVN为10,PDIVN为1既可。CLKDIVN的值应该是0x101=5

    手册243页中提到如果HDIVN不是0,那么需要将cpu总线模式从"fast bus mode"改成“asynchronous bus mode"

    然后需要对PLL进行配置,才能得到405MHz的输出频率,根据手册255页,可以得到PLL相关寄存器信息:

    复制代码
    MPLLCON 0x4C000004 R/W MPLL configuration register 0x00096030
    UPLLCON 0x4C000008 R/W UPLL configuration register 0x0004d030
    
    PLLCON Bit   Description
    MDIV [19:12] Main divider control 
    PDIV [9:4] Pre-divider control 
    SDIV [1:0] Post divider control
    input freq output freq  MDIV      PDIV   SDIV
    12.0000MHz 48.00 MHz   56(0x38)  2      2
    12.0000MHz 405.00 MHz   127(0x7f) 2      1
    复制代码

    此处MPLL和UPLL分别用于系统时钟和USB时钟,我们将MPLL输出设定成405MHz, UPLL输出设定成48MHz.

    手册255页中还提到,当写入UPLL和MPLL时,需要先写UPLL后写MPLL。

     我修改后的代码内容如下:

    复制代码
    #if defined(CONFIG_S3C2440)
        /* FCLK:HCLK:PCLK = 1:4:8 */
        ldr    r0, =CLKDIVN
        mov    r1, #5
        str    r1, [r0]
    
        /* change bus mode from "fast bus mode" to "asynchronous bus mode" */
        mrc p15, 0, r1, c1, c0, 0 /*read ctrl regester*/
        orr r1, r1, #0xc0000000 /*asynchronous*/
        mcr p15, 0, r1, c1, c0, 0 /*write ctrl register*/
    
    #define S3C2440_MPLL_400MHZ (0x7f<<12 | 0x2<<4 | 0x1) /* refer to s3c2440.pdf page 255 */
    #define S3C2440_UPLL_48MHZ  (0x38<<12 | 0x2<<4 | 0x2)
    #define MPLLCON 0x4c000004
    #define UPLLCON 0x4c000008
        ldr r0, =UPLLCON
        ldr r1, =S3C2440_UPLL_48MHZ 
        str r1, [r0]
    
        ldr r0, =MPLLCON
        ldr r1, =S3C2440_MPLL_400MHZ 
        str r1, [r0]
    #else
        /* FCLK:HCLK:PCLK = 1:2:4 */
        /* default FCLK is 120 MHz ! */
        ldr    r0, =CLKDIVN
        mov    r1, #3
        str    r1, [r0]
    #endif

    如果没有定义CONFIG_SKIP_LOWLEVEL_INIT, 在执行完这部分代码后会跳转到start.S中的cpu_init_crit,

    然后又跳转到board/friendlyarm/mini2440/lowlevel_init.S中的lowlevel_init函数,该函数中包含对sdram连接的BANK0-BANk7

    以及SDRAM刷新频率进行配置(可以参考2440手册203-210页)。

    但是我们当前代码中定义了CONFIG_SKIP_LOWLEVEL_INIT,所以cpu_init_crit不会执行,暂时也不需要考虑这部分代码。

    接着调用_main,_main位于arch/arm/lib/crt0.S文件中,它会依次调用board_init_f和relocate_code.

    在relocate_code中执行重定位代码,然后会根据其lr寄存器中的here地址跳转回arch/arm/lib/crt0.S,执行here标签下的内容(主要是board_init_r函数).

    修改mini2440.c中的时钟频率,跟上面的汇编代码保持一致:

    host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/mini2440.c 
    host@debian:~/soft/mini2440/u-boot-2011.03$ vim board/friendlyarm/mini2440/mini2440.c
    #define FCLK_SPEED 2

    #elif FCLK_SPEED==1 /* Fout = 202.8MHz */
    #define M_MDIV 0xA1
    #define M_PDIV 0x3
    #define M_SDIV 0x1
    #elif FCLK_SPEED==2 /* Fout = 405MHz */
    #define M_MDIV 0x7F
    #define M_PDIV 0x2
    #define M_SDIV 0x1
    #endif
     
    #define USB_CLOCK 2

    #elif USB_CLOCK==1
    #define U_M_MDIV 0x48
    #define U_M_PDIV 0x3
    #define U_M_SDIV 0x2
    #elif USB_CLOCK==2 /* Fout = 48MHz */
    #define U_M_MDIV 0x38
    #define U_M_PDIV 0x2
    #define U_M_SDIV 0x2
    #endif
     
    int board_init (void)
    {
         ......
         gd->bd->bi_arch_number = MACH_TYPE_MINI2440;
         ......
    }

    此时,执行编译命令:

    make CROSS_COMPILE=arm-linux-

    会出来很多编译错误:

    复制代码
    drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_hwcontrol':
    drivers/mtd/nand/s3c2410_nand.c:44: warning: implicit declaration of function 's3c2410_get_base_nand'
    drivers/mtd/nand/s3c2410_nand.c:44: warning: initialization makes pointer from integer without a cast
    drivers/mtd/nand/s3c2410_nand.c:59: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c:59: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c:62: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c:62: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_dev_ready':
    drivers/mtd/nand/s3c2410_nand.c:72: warning: initialization makes pointer from integer without a cast
    drivers/mtd/nand/s3c2410_nand.c:74: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c: In function 'board_nand_init':
    drivers/mtd/nand/s3c2410_nand.c:116: warning: initialization makes pointer from integer without a cast
    drivers/mtd/nand/s3c2410_nand.c:137: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c:140: error: dereferencing pointer to incomplete type
    drivers/mtd/nand/s3c2410_nand.c:141: error: dereferencing pointer to incomplete type
    make[1]: *** [drivers/mtd/nand/s3c2410_nand.o] 错误 1
    复制代码

    查看代码可以知道是因为从board_init_r->nand_init经过一长串的调用后调用s3c2410_hwcontrol。

    当前代码中在include/configs/mini2440.h中定义了CONFIG_NAND_S3C2410,所以使用了drivers/mtd/nand/s3c2410_nand.c中的代码。

    上面的错误是因为未定义s3c2410_get_base_nand引起的,而该函数定义位于arch/arm/include/asm/arch-s3c24x0/s3c2410.h中,

    在arch/arm/include/asm/arch-s3c24x0/s3c24x0_cpu.h中有下面内容:

      #elif defined CONFIG_S3C2440
         #include <asm/arch/s3c2440.h>

    实际上当前代码中包含的文件是arch/arm/include/asm/s3c24x0/s3c2440.h,该头文件中没有 s3c2410_get_base_nand函数的定义,由于s3c2410.h和s3c2440.h中代码基本一致,直接包含将代码中 s3c2440.h修改成s3c2410.h即可。

    另外几个错误是因为s3c2410_nand未定义引起的,可以在arch/arm/include/asm/arch-s3c24x0/s3c24x0.h中将s3c2440_nand修改成s3c2410_nand即可。

    然后重新编译:

    make CROSS_COMPILE=arm-linux-

    参考《openocd+jlink为mini2440调试u-boot》配置好openocd,然后打开串口:

    sudo minicom

    在另一个控制台执行下面命令:

    sudo openocd -f interface/jlink.cfg  -f board/mini2440.cfg
    telnet localhost 4444
    halt
    init_2440
    load_image /home/host/soft/mini2440/u-boot-2014.04/u-boot.bin 0x33f80000 bin 
    resume 0x33f80000

    其中/home/host/soft/mini2440/u-boot-2014.04/u-boot.bin是我的uboot存放路径,根据自己的需要改成自己电脑上的路径即可。

    得到下面的输出信息:

    U-Boot 2014.04-gf5f2cb1-dirty (Jun 04 2014 - 13:55:36)
    
    CPUID: 32440001
    FCLK:      405 MHz
    HCLK:  101.250 MHz
    PCLK:   50.625 MHz
    DRAM:  64 MiB

    之后没有进入uboot命令行就重启cpu了。

    虽然这里能检测到DRAM,这也说明了DRAM的配置是基本上正确的。从s3c2440手册194页和mini2440原理图第5页可以看到DRAM连接nGCS6,

    所以其对应基地址是0x30000000,与include/configs/mini2440.h中的PHYS_SDRAM_1的值一模一样。

    (三)调试bug(未进入uboot重启cpu)

    在include/configs/mini2440.h中添加一行:

    #define DEBUG

    然后按照上面的步骤将进行编译并将生成u-boot.bin加载到mini2440,从控制台可以得到输出:

    U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:22:23)
    
    U-Boot code: 33F80000 -> 33FF9F84  BSS: -> 340489D0
    CPUID: 32440001
    FCLK:      405 MHz
    HCLK:  101.250 MHz
    PCLK:   50.625 MHz
    monitor len: 000C89D0
    ramsize: 04000000
    TLB table from 33ff0000 to 33ff4000
    Top of RAM usable for U-Boot at: 33ff0000
    Reserving 802k for U-Boot at: 33f27000
    Reserving 4160k for malloc() at: 33b17000
    Reserving 32 Bytes for Board Info at: 33b16fe0
    Reserving 160 Bytes for Global Data at: 33b16f40
    New Stack Pointer is: 33b16f30
    RAM Configuration:
    Bank #0: 30000000 64 MiB
    relocation Offset is: fffa7000

    然后就冻结在这个地方,不再有任何输出。

    我在board_init_f函数中debug("relocation Offset is: %08lx ", gd->reloc_off)之前添加了一行代码:

    debug("addr=%08lx,_start=%08lx
    ", addr,(ulong)&_start);

    重新编译加载到mini2440后得到的输出信息如下:

    U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:35:37)
    
    U-Boot code: 33F80000 -> 33FF9FB4  BSS: -> 340489D0
    CPUID: 32440001
    FCLK:      405 MHz
    HCLK:  101.250 MHz
    PCLK:   50.625 MHz
    monitor len: 000C89D0
    ramsize: 04000000
    TLB table from 33ff0000 to 33ff4000
    Top of RAM usable for U-Boot at: 33ff0000
    Reserving 802k for U-Boot at: 33f27000
    Reserving 4160k for malloc() at: 33b17000
    Reserving 32 Bytes for Board Info at: 33b16fe0
    Reserving 160 Bytes for Global Data at: 33b16f40
    New Stack Pointer is: 33b16f30
    RAM Configuration:
    Bank #0: 30000000 64 MiB
    addr=33f27000,_start=33f80000
    relocation Offset is: fffa7000

    从调试信息可以看出addr < _start,但是gd_reloc_off=addr-(ulong)&_start,明显得到的结果溢出了。

    这是因为我们配置的CONFIG_SYS_TEXT_BASE的问题,将其值修改成0x33F00000。

    然后重新编译加载到mini2440(但命令中的0x33f80000都要替换成0x33f00000),得到下面的输出:

    U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:48:22)
    
    U-Boot code: 33F00000 -> 33F79FB4  BSS: -> 33FC89D0
    CPUID: 32440001
    FCLK:      405 MHz
    HCLK:  101.250 MHz
    PCLK:   50.625 MHz
    monitor len: 000C89D0
    ramsize: 04000000
    TLB table from 33ff0000 to 33ff4000
    Top of RAM usable for U-Boot at: 33ff0000
    Reserving 802k for U-Boot at: 33f27000
    Reserving 4160k for malloc() at: 33b17000
    Reserving 32 Bytes for Board Info at: 33b16fe0
    Reserving 160 Bytes for Global Data at: 33b16f40
    New Stack Pointer is: 33b16f30
    RAM Configuration:
    Bank #0: 30000000 64 MiB
    addr=33f27000,_start=33f00000
    relocation Offset is: 00027000

     虽然没有溢出,但是仍然是停留在这个位置不继续执行了。

    我将CONFIG_SYS_TEXT_BASE改成了0x33e80000,然后重新编译并加载到mini2440内存中(命令中的地址也相应修改为0x33e80000),得到下面的输出:

    U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 15:25:46)
    
    U-Boot code: 33E80000 -> 33EF9FA8  BSS: -> 33F489D0
    CPUID: 32440001
    FCLK:      405 MHz
    HCLK:  101.250 MHz
    PCLK:   50.625 MHz
    monitor len: 000C89D0
    ramsize: 04000000
    TLB table from 33ff0000 to 33ff4000
    Top of RAM usable for U-Boot at: 33ff0000
    Reserving 802k for U-Boot at: 33f27000
    Reserving 4160k for malloc() at: 33b17000
    Reserving 32 Bytes for Board Info at: 33b16fe0
    Reserving 160 Bytes for Global Data at: 33b16f40
    New Stack Pointer is: 33b16f30
    RAM Configuration:
    Bank #0: 30000000 64 MiB
    addr=33f27000,_start=33e80000
    relocation Offset is: 000a7000
    WARNING: Caches not enabled
    monitor flash len: 000847B0
    Now running in RAM - U-Boot at: 33f27000
    Flash: fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
    fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
    fwc addr 00005554 cmd 55 0055 16bit x 16 bit
    fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
    fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
    JEDEC PROBE: ID f0 ea00 0
    fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
    fwc addr 00000000 cmd 90 0090 16bit x 16 bit
    fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
    JEDEC PROBE: ID 90 ea00 0
    *** failed ***
    ### ERROR ### Please RESET the board ###

    从输出信息上看sdram已经通过了,但是flash中存在问题,接下来解决这个问题。

  • 相关阅读:
    3.04
    3.03
    3.02
    3.01
    2.27
    2.25小账本6
    2.24小账本5
    2.23小账本4
    2.22小账本3
    git常用命令
  • 原文地址:https://www.cnblogs.com/qiaoqiao2003/p/3767642.html
Copyright © 2011-2022 走看看