移植uboot2012.04.01到JZ2440(长文,详细记录)

1.下载uboot2012.04.01,并尝试编译smdk2410

    a.官网下载

    b.tar解压

    c.配置:make smdk2410_config

    d.编译:make

遇到问题:

    make: *** [u-boot] Error 139

    编译器版本低

故:换arm-linux-gcc-4.3.2

 

    e.再次编译:

 遇到问题:

    error trying to exec 'cc1': execvp: No such file or directory

    编译器位置的问题

故:将编译器解压到 /

    

    d.再次编译:编译成功,达到uboot.bin可执行文件

 

2.基于smdk2410创建单板目录和配置文件

    a.创建jz2440  board目录

    在u-boot-2012.04.01\board\samsung\  目录下创建jz2440目录,并将同目录下smdk2410中的文件全部拷贝到jz2440

    同时将smdk2410.c改成jz2440.c  ,并在同目录下将Makefile 中的 COBJS    := smdk2410.o    改为COBJS    := jz2440.

    b.创建jz2440.h配置文件

    在u-boot-2012.04.01\include\configs中copy smdk2410.h文件并重命名为jz2440.h粘贴到该目录下。

    c.在/board.cfg中添加:

    jz2440                     arm         arm920t     -                   samsung        s3c2440

    d./Makefile中:

    

    添加:arm-linux-

    

    目标:成功编译新board

                make jz2440_config

                make

                (成功)

3.创建SI-project,分析启动流程,了解内存布局,及各关键部位

    a.创建SI-project

    b.分析启动流程

        从arch/arm/cpu/arm920t/start.S开始:

        start_code:

                            set the cpu to SVC32 mode -> .....详情见移植过程......

    

    c.内存布局

    d.各关键部位

 

4.修改时钟和存储控制器,与board适配,并debugSDRAM是否可用

step1:修改时钟和存储控制器   

 set the cpu to SVC32 mode 

->#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)     //delete  这部分

->turn off the watchdog    //2410   2440看门狗继存器位置相同,不改动

->mask all IRQs by setting all bits in the INTMR - default   //屏蔽IRQs   INTSUBMSK  2440也有,将CONFIG_S3C2410换成                      CONFIG_S3C2440    并将CONFIG_S3C2440在jz2440中定义

->第一个重要post1:时钟配置(MPLL){

        MPLL和UPLL在board/sansung/jz2440.c中int board_early_init_f(void)有:

        

        将以上MPLL注释,UPLL保留;在post1处手动添加MPLL的配置,如下

        a.set FCLK 和 Fin的关系

        b.set FCLK、HCLK、PCLK三者关系

        c.改变总线模式,使cpu核时钟使用FCLK(默认使用HCLK)

        

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    }

->CONFIG_SKIP_LOWLEVEL_INIT jz2440不定义,bl    cpu_init_crit 

    flush v4 I/D caches  、 disable MMU stuff and caches、bl    lowlevel_init(执行存储控制器的配置)

->bl    lowlevel_init:在jz2440/lowlevel.S中:

首先检查BWSCON  存储控制器寄存器组的基址:0x48000000  没错

分析配置过程,没错

更改SMRDATA:的值(与jz2440适配,注意时钟的变化,修改刷新reg)

step2:验证SDRAM是否可用:

使用JTAG物理调试(类似于gdb),采用openOCD作为上位机应用程序:

    a.烧写一个移植好的uboot,采用dnw(win7) +  usb + uboot 下载自己的uboot到Nor / Nand

    b.在uboot启动过程中,q进入命名模式:

        usb 1 30000000                    //采用usb下载   1-一直等待至下载完成    30000000  下载目的地址

        对Nor Flash:

        protect  off  all            //解除写保护

        erase 0 7FFFF                //擦除Nor 512K的大小(从0x0地址到0x7FFFF)

        cp.b  30000000  0  80000            //从0x30000000处复制 0-0x80000内容到Nor

        对Nand Flash:

        nand  erase 0 80000            //擦除nand 从0x0  到 0x80000

        nand write 30000000 0 80000   //从0x30000000复制0-0x80000的内容写入nand

    c.win7安装OpenOCD(包括驱动) + OpenJTAG  + telent进行debug

    d.打开telent功能(控制面板 - 程序与功能 - ... )

    e.打开openocd,OPJTAG连接开发板和PC,启动开发板,connect,识别成功后telnet到cmd中:

        reset halt 

        halt

        step 0x0            //从0x0开始运行

        step                    //单步运行    pc += 4

        bp  0xb0   4  hw        //在0xb0处设置断点,使其完成存储 控制器的配置   

        resume         //继续运行到断点0xb0

        mdw   0x30000000        //查看0x30000000处原来的值

        mww  0x30000000   0x11112222        //向0x30000000写入0x11112222

        mdw   0x30000000        //查看0x30000000处现在的值,若= 0x11112222则读写入成功(SDRAM可用)

 

    小结:在start.S中配置MPLL,在lowlevel.S中配置存储控制器,并在jz2440.c中注释MPLL的配置,以及在s3c24x0.h中注释s3c2410的GPIO结构体,(下一步:在jz2440.h中添加CONFIG_S3C2440宏)

    目标:MPLL配置成功,SDRAM可用,串口有输出(不配置CONFIG_S3C2440则为乱码)

    

    (成功)

 

5.修改时钟获取函数(如get_PCLK()等),使baudrate正常,使串口能输出

->Set stackpointer in internal RAM to call board_init_f(在SDRAM中设置栈指针,并调用board_init_f 第一阶段的初始化工作)

->board_init_f:主要做一些第一阶段的初始化工作:

->serial_init源码追溯

int serial_init(void)

{

    return serial_init_dev(UART_NR);

}

 

static int serial_init_dev(const int dev_index)

{

    //获得UART控制器基址

    struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);  

#ifdef CONFIG_HWFLOW        //不管

    hwflow = 0;    /* turned off by default */

#endif

    /* FIFO enable, Tx/Rx FIFO clear */

    writel(0x07, &uart->ufcon);

    writel(0x0, &uart->umcon);

 

    /* Normal,No parity,1 stop,8 bit */                    //8N1

    writel(0x3, &uart->ulcon);

    /*

     * tx=level,rx=edge,disable timeout int.,enable rx error int.,

     * normal,interrupt or polling

     */

    writel(0x245, &uart->ucon);        //interrupt or polling

 

#ifdef CONFIG_HWFLOW

    writel(0x1, &uart->umcon);    /* rts up */

#endif

 

    /* FIXME: This is sooooooooooooooooooo ugly */

#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)

    /* we need auto hw flow control on the gsm and gps port */

    if (dev_index == 0 || dev_index == 1)

        writel(0x10, &uart->umcon);

#endif

    _serial_setbrg(dev_index);

 

    return (0);

}

 

 

void _serial_setbrg(const int dev_index)

{

    struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);

    unsigned int reg = 0;

    int i;

 

    /* value is calculated so : (int)(PCLK/16./baudrate) -1 */

    reg = get_PCLK() / (16 * gd->baudrate) - 1;

 

    writel(reg, &uart->ubrdiv);

    for (i = 0; i < 100; i++)

        /* Delay */ ;

}

 

/*划重点了*/

ulong get_PCLK(void)

{

    struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();

 

    return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK();

}

 

ulong get_HCLK(void)

{

    struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();

#ifdef CONFIG_S3C2440                    //需要定义这个宏,在include/configs/jz2440.h中

    switch (readl(&clk_power->clkdivn) & 0x6) {

    default:

    case 0:

        return get_FCLK();

    case 2:

        return get_FCLK() / 2;

    case 4:

        return (readl(&clk_power->camdivn) & (1 << 9)) ?

            get_FCLK() / 8 : get_FCLK() / 4;

    case 6:

        return (readl(&clk_power->camdivn) & (1 << 8)) ?

            get_FCLK() / 6 : get_FCLK() / 3;

    }

#else

    return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK();

#endif

}

串口的支持其实就是追溯到/arch/arm/cpu/arm920t/s3c24x0/speed.c中    影响get_PLLCLK函数和get_HCLK函数并在自己的配置文件中添加宏定义CONFIG_S3C2440,

去掉CONFIG_S3C2410

->编译:

q1.在s3c2410_nand.c  中出错:

对照源码:

可见是因为把CONFIG_S3C2410这个宏去掉了,导致条件编译时没有生成struct s3c2410_nand结构体,后续的所有配置也就是错误的。

故:

    暂时添加CONFIG_S3C2410这个宏,因为在speed.c中只要配置了CONFIG_S3C2440这个宏即可,其余问题后续再解决。

(解决)

q2:

大概是个结构体吧,对照源码:从cpu_info.c追溯到:s3c24x0_cpu.h

可以看出CONFIG_S3C2410  又在作怪了。。。

故:

    那就将以上源码的CONFIG_S3C2440与CONFIG_S3C2410位置对换,且同时修改.h文件

(未解决,到s3c24x0.h中看:)

可见二者不能同时存在

故:

    直接把2410的部分结构体成员注释把。

(解决)

q3:

以上未定义的函数,在s3c2410.h中定义。。。。。

故:

    

在/driver/mtd/nand/Makefile中修改如上,s3c2440.o备用

(解决)

q4:

故:暂时注释吧

终于:(编译成功)

    小结:其实可以直接在jz2440.h中注释CONFIG_NAND_S3C2410  使得在/drivers/mtd/nand/Makefile中不编译s3c2410.o;然后注释掉2410的nand结构体。

              也可以不注释CONFIG_S3C2410,直接添加CONFIG_S3C2440,并在s3c24x0.h中注释2410的GPIO结构体。因为串口获取时钟只要定义CONFIG_S3C2440即可。

->烧写、启动、观察串口输出:

这个结果其实很好得到,就是要注意MPLLCON的配置顺序!!!!

小结:

    MPLL的配置;ICache开启;添加CONFIG_S3C2440(使得获取总线时钟函数获取到2440的正确时钟)才能使波特率正常。

 

6.修改启动方式之  支持Nand Flash启动

    原本,uboot是默认Nor Flash启动,不管是*.lds中的链接地址还是重定位代码,都是针对Nor Flash;

    现在,要支持Nand Flash启动,必然涉及修改*.lds中的链接地址和修改重定位方式,并去掉针对Nor 启动的-pie选项(-pie会导致在*.lds中生成一些关于已初始化全局变量和静态变量的段,可在arch/arm/config.mk中修改)

    此外,要注意将重定位之前的代码和相关变量定位于前4K,/jz2440/Makefile中修改

 

    1.将原来的nand_drv.c复制到jz2440/下,并在jz2440/Makefile中做对应修改(主要是nand_init 和nand_read 用于nand初始化和重定位uboot)

    

    编译,烧写,测试:没问题

    

    在board.c中定义_DEBUG,查看输出:

    2.在进入第一阶段的初始前(调用board_init_f之前),进行nand_init 和 重定位代码

    如下:

    

其中CONFIG_SYS_TEXT_BASE是原本在jz2440.h中定义为0x0,表示自动生成的uboot.lds中指定链接地址为0;

现在,修改为:(更改链接地址了)

这样不好!!!因为还没有重定位,在jz2440.h中定义的值可能编译器输出在4K之外,所以将上面的r1修改:

关于_TEXT_BASE和_bss_start_ofs在start.S中:

4.去掉针对Nor 启动的-pie选项;去掉针对Nor 启动的重定位相关代码

在/arch/arm/config.mk中:

在arch/arm/lib/board.c中:

在arch/arm/cpu/arm920t/start.S:

以上直接去掉,直到清bss段。

 

3.清bss段

篇外:

    一个可执行程序有:text、data等段,bss段不在可执行文件里面。

    bss段里面存的是为初始化的全局变量和静态变量,是一个个值。当从定位代码的时候,只重定位了text开始。。。bss_start,另外的bss段可以不重定位,直接在重定位后clear(初始化为0)。

    所以,我们应该给程序留的最终大小应该是从text开始。。。bss_end。

uboot原本的:

是结合Nor 重定位的,直接自己写吧:

4.进入第二阶段的初始化工作(进入到board_init_r函数)

 

篇外:接clear_bss后的启动流程分析

经过以上,启动流程分析,走过了board_init_f,再经过一些Nor Flash的重定位和clear bss,进入到board_init_r第二阶段的初始化工作:

->board_init_r:这里面就超级重要了,主要是对外设的支持,比如Nand Flash、Nor Flash 、网卡、LCD等。

以及开启cache、设置parm参数地址 和 2410机器ID(需要修改)、环境变量重定位、设置栈等。

 

board_init_r有两个参数需要确定:

void board_init_r(gd_t *id, ulong dest_addr)

 

gd_t *id 在board_init_f中就确定了,直接使函数返回(返回值保存在r0中)   //在函数定义和声明处(/include/common.h)更改返回值类型

 

ulong dest_addr就是链接地址:_TEXT_BASE

所以:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

    bl    cpu_init_crit            //完成储存控制器的配置

#endif

 

    ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)

    bic    sp, sp, #7 /* 8-byte alignment for ABI compliance */

 

    bl nand_init_new        //Nand Flash 控制器初始化

 

    mov r0, #0x0

    ldr r1, _TEXT_BASE

    ldr r2, _bss_start_ofs

    bl copy_bootcode_to_sdram    //重定位nand中的uboot到SDRAM 0x33f00000

 

clear_bss:

    ldr    r0, _bss_start_ofs

    ldr    r1, _bss_end_ofs

    mov    r2, #0x00000000        /* clear                */

 

clbss_l:

    str    r2, [r0]        /* clear loop...            */

    add    r0, r0, #4

    cmp    r0, r1

    bne    clbss_l

 

    //bl coloured_LED_init

    //bl red_led_on

 

    ldr pc, = call_board_init_f            //到SDRAM去执行

 

 

/* Set stackpointer in internal RAM to call board_init_f */

call_board_init_f:

    ldr    r0,=0x00000000

    bl    board_init_f        //第一阶段的初始化,修改返回id参数,保存在r0

 

    ldr r1, =_TEXT_BASE

    bl board_init_r

 

/*

* We are done. Do not return, instead branch to second part of board

* initialization, now running from RAM.

*/

#if 0            //都是针对Nor启动的代码

#ifdef CONFIG_NAND_SPL

    ldr     r0, _nand_boot_ofs

    mov    pc, r0

 

_nand_boot_ofs:

    .word nand_boot

#else

    ldr    r0, _board_init_r_ofs

    adr    r1, _start

    add    lr, r0, r1

    add    lr, lr, r9

    /* setup parameters for board_init_r */

    mov    r0, r5        /* gd_t */

    mov    r1, r6        /* dest_addr */

    /* jump to it ... */

    mov    pc, lr

 

_board_init_r_ofs:

    .word board_init_r - _start

#endif

 

_rel_dyn_start_ofs:

    .word __rel_dyn_start - _start

_rel_dyn_end_ofs:

    .word __rel_dyn_end - _start

_dynsym_start_ofs:

    .word __dynsym_start - _start

#endif

 

5.修改jz2440/ 下的Makefile ,添加nand_drv.o

6.在arch/arm/cpu/在的uboot.lds中修改(将start.o、nand_drev.o、lowlevel.o等放到前4K的位置)

经编译后,在jz2440/下:没有对应的start.o、nand_drev.o、lowlevel.o,却有一个libjz2440.o,可见uboot将他们做成了一个库。

所以将arch/arm/cpu/下的uboot.lds:

修改为:

 

7.总结修改了哪些文件:

start.S   jz2440/  jz2440.h   /arch/arm/config.mk    arch/arm/lib/board.c   /include/common.h   arch/arm/cpu/下的uboot.lds  

 

8.编译:

q1:

(解决)

q2:

注意英文逗号。。。。。

(解决)

q3:

board前面没有/  

(解决)

(编译成功)

9.烧写结果:

!!!!!不断重启或者Nor Flash哪里没有输

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值