zoukankan      html  css  js  c++  java
  • 2.移植uboot-添加2440单板,并实现NOR、NAND启动

    • 上章分析了uboot启动流程后,接下来便来配置新的单板,实现nor、nand启动

    1.首先在uboot里新建单板2440

    1.1将2410的单板文件夹拷贝成2440:

    cd board/samsung/
    cp smdk2410 smdk2440 -rf                //拷贝文件夹,

    然后将smdk2440下的smdk2410.c改为smdk2440.c,以及修改更改好的Makefile 

    1.2 将2410的头文件拷贝成2440:

    cd ../../include/configs/
    cp smdk2410.h smdk2440.h

    2.新建后,还需要修改boards.cfg,使uboot支持2440单板:

    仿照

    smdk2410                     arm         arm920t     -                   samsung        s3c24x0

    添加:

    smdk2440                     arm         arm920t     -                   samsung        s3c24x0

    添加后,就能够使用make smdk2440_config命令.

    (该命令便会调用include/configs/smdk2440.h和board/samsung/smdk2440里的文件来配置uboot)

     

    3.修改uboot系统时钟

    在start.S里,uboot只设置了CLKDIVN寄存器

    而2440的系统时钟需要设置两个寄存器:MPLLDIVN(设置FCLK频率)、CLKDIVN(设置分频比例),且还要设为异步模式

    所以将:

          ldr   r0, =CLKDIVN
          mov r1, #3
          str   r1, [r0] 

    改为:

    #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))   //设置FCLK=400MHZ
    #define MPLLCON                          0x4C000004            //设置FCLK频率
    ldr r0,=0x4C000014 mov r1,#5 /*FCLK:HCLK:PCLK=1:4:8 (400M:100M:50M)*/ str r1,[r0] mrc p15, 0, r1, c1, c0 /* 读出控制寄存器 */ orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */ mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */ ldr r0,=MPLLCON ldr r1,=S3C2440_MPLL_400MHZ str r1,[r0]

     并修改boardsamsungsmdk2440Smdk2440.c里的board_early_init_f()函数,屏蔽对MPLLDIVN, LOCKTIME寄存器的设置(该函数被start.S->board_init_f()调用,这些寄存器在前面已被设置)

    4.烧写到NOR上,测试

    烧写测试时,由于新的uboot较大,可以使用nor上的旧uboot,通过DNW烧写新的uboot到nor上面.

    步骤:

    usb 1 30000000            //使用usb下载到SDRAM上,1表示一直下载,直到完成
                             //然后打开DNW,传输新的uboot.bin给usb
    
    protect off all           //关闭nor的写保护
    
    erase  0   +7FFFF      //擦除nor上的 0~7FFFF地址内容, +7FFF=擦除长度=512kb,要大于新的uboot.bin才行
    
    cp.b  30000000  0  80000         //将SDRAM上的新的uboot.bin,拷贝到nor上

    烧写完成后,重启,通过JTAG调试的读地址命令, 判断是否与新uboot文件一致

    使用JTAG调试时,发现向0x30000000地址上写值出错

     

    5.接下来便修改bank寄存器

    将boardsamsungsmdk2440lowlevel_init.S里SMRDATA符号下:

    SMRDATA:
        .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
        .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
        .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
        .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
        .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
        .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
        .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
        .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
        .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
        .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
        .word 0x32
        .word 0x30
        .word 0x30

    改为:

    SMRDATA:
           .long 0x22011110    //BWSCON
           .long 0x00000700    //BANKCON0
           .long 0x00000700    //BANKCON1
           .long 0x00000700    //BANKCON2
           .long 0x00000700    //BANKCON3 
           .long 0x00000700    //BANKCON4
           .long 0x00000700    //BANKCON5
           .long 0x00018005    //BANKCON6
           .long 0x00018005    //BANKCON7
           .long 0x008C04F4    //REFRESH
           .long 0x000000B1    //BANKSIZE
           .long 0x00000030    //MRSRB6
           .long 0x00000030    //MRSRB7

    6.重新编译烧写uboot,发现串口已有数据,但是乱码:

     

    6.1进入archarmcpuarm920ts3c24x0Speed.c下的get_HCLK ()函数:

     

    由于我们没有配置CONFIG_S3C2440宏,所以uboot获取HCLK时钟设置波特率时,用的是CONFIG_S3C2410宏的方法

    搜索CONFIG_S3C2410宏,找到位于smdk2440.h:

     

    然后将smdk2440.h的CONFIG_S3C2410宏 改为: CONFIG_S3C2440宏

     

    6.2编译测试

    make时,发现以下几个error:

     

    进入drivers/mtd/nand/s3c2410_nand.c 的72行:

     

    其中nand是一个s3c2410_nand结构体:

     

    该结构体如下所示:

     

    从上图可以看出,只有定义了CONFIG_S3C2410宏,才能得到该结构体,而我们6.1小节里,使用的是CONFIG_S3C2440宏。

    且上面的s3c2410_nand结构体和s3c2440_nand结构体的差别也很大,修改s3c2410_nand.c会很麻烦

    6.3所以就直接去掉该文件,不让编译器编译即可,步骤如下所示:

    1)直接进入s3c2410_nand.c的目录,打开Makefile:

     

    如上图所示,需要去掉CONFIG_NAND_S3C2410宏定义才行

    2)搜索CONFIG_NAND_S3C2410宏,位于include/configs/smdk2440.h:

     

    如上图所示,我们直接来屏蔽CONFIG_CMD_NAND宏即可,因为该宏下的#ifdef,都是与2410相关

    3)屏蔽include/configs/smdk2440.h下的CONFIG_CMD_NAND宏定义

     

    重新烧写进norflash,打印如下图所示:

     

    发现无乱码了,表示nor启动成功,其中Flash: *** failed ***表示不支持norflash,因为我们只实现了重定位,并没有对nor实现写擦除等命令。

    7.接下来便修改uboot,实现NAND启动

    新的uboot链接地址位于0,且在arm-linux-ld时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)",从而程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K).

    所以接下来修改代码,并取消"-pie"选项.

    7.1去掉 "-pie"选项

    使用grep "-pie" * -nR找到:

    arch/arm/config.mk:75:LDFLAGS_u-boot += -pie             // LDFLAGS: arm-linux-ld的参数

    所以屏蔽arch/arm/config.mk文件的"LDFLAGS_u-boot += -pie"这行即可

    7.2参考之前自制uboot使用的start.S, init.c来修改uboot代码

    1)将以前写uboot里的init.c放入board/samsung/smdk2440目录, 并检查是否有同名函数名,若函数只在同文件使用,则添加static.并修改Makefile 

    2)修改include/configs/smdk2440.h文件

    将CONFIG_SYS_TEXT_BASE宏改为0x33f00000,也就是uboot重定位后的位置, 这里留了1MB空间供给uboot重定位(在反汇编中看到,代码真正总大小为700多KB(包括了bss段))

     

    3)修改arch/arm/cpu/arm920t/start.S,更改重定位代码

    由于nand启动时,2440未初始化之前只有前4K可读写,所以将重定位代码放在start.S的cpu_init_crit(初始化SDRAM)段后面

    添加以下带红色的字段:

    #ifndef CONFIG_SKIP_LOWLEVEL_INIT

           bl    cpu_init_crit

    #endif

           /*重定位                          */

           ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR)          //等于0x30000f80

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

        

           mov r0,#0                         //r0->src

           ldr r1,_TEXT_BASE          //_TEXT_BASE : 0x33f00000

           ldr r2,_bss_start_ofs       // _bss_start_ofs:  __bss_start - _start   (有效代码大小)

           bl copy_code_to_sdram     //该函数首先会初始化nand控制器,然后复制代码到SDRAM连接地址dest上

           bl clear_bss                         //清除bss段(参考自制uboot章节)

     

           ldr pc,=call_board_init_f                 //绝对跳转,跳到SDRAM上执行

    call_board_init_f:

           ldr   r0,=0x00000000

           bl    board_init_f

    上面的_TEXT_BASE,在start.S靠前处定义:

    由于它位于靠前处,保证了_TEXT_BASE存在前4k空间里,若直接使用ldr r1,=CONFIG_SYS_TEXT_BASE,编译器可能会将这个宏定义放在SDRAM上,则会出错

    4)重定位写在前面了,所以我们还要删除start.S后面的relocate_code重定位段,清除BSS段

    board_init_r位置处的代码,改为如下所示:

    /* void relocate_code (addr_sp, gd, addr_moni)*/
    .globl      relocate_code
    relocate_code:
    
           mov r4, r0      /* save addr_sp */       
           mov    sp, r4
           mov r0, r1      /* save addr of gd */
           mov r1, r2      /* save addr of destination */
           bl   board_init_r        //进入uboot第二阶段代码

    7.3修改board_init_f()函数(位于arch/arm/lib/board.c)

    本节添加的uboot重定位是直接以基地址0x33F00000开始的, 在上一章分析出,board_init_f()函数划分uboot重定位所在区域时,是通过动态划分的.

    所以修改board_init_f()函数的第113行:

           /*
            * reserve memory for U-Boot code, data & bss
            * round down to next 4 kB limit
            */
    
           //addr -= gd->mon_len;                     //屏蔽该行
           //addr &= ~(4096 - 1);                     //屏蔽该行
    
         addr=CONFIG_SYS_TEXT_BASE;           //0x33f00000,添加该行     

    7.4修改链接脚本

    把start.S, init.c(实现重定位), lowlevel.S(实现初始化SDRAM)等文件放在最前面

    vi arch/arm/cpu/u-boot.lds

    添加以下带红色的字段:

         . = ALIGN(4);

            .text :

            {

                    __image_copy_start = .;

                    CPUDIR/start.o (.text)              //CPUDIR为arch/arm/cpu/arm920t目录

                    board/samsung/smdk2440/libsmdk2440.o (.text)  

                    *(.text)

            }

    libsmdk2440.o是将smdk2440单板目录下的所有*.c,*S文件编译后,连接成一个库文件.

    8.然后通过旧的uboot,将新的uboot烧写到nand

    usb 1 30000000                             //先下载到SDRAM上
    
    nand erase 0  0x80000                      //擦除512kb,必须大于新的uboot
    
    nand write 30000000   0  0x80000           //将SDRAM上的新uboot写入nand中

    烧写后,如下图所示:

     

    nand启动便实现完成了,上面的Flash: *** failed *** 是属于uboot第二阶段函数board_init_r()里的代码,表示不支持nor flash,不能实现读,写,擦除等命令

    下一章便来让uboot支持nor flash、nand flash.

     

     

  • 相关阅读:
    Js获取当前日期时间及其它操作
    OpenResty
    Nginx开发从入门到精通
    TengineWeb服务器项目
    VS2012的SVN插件VISUALSVN
    VS项目如何运用svn的忽略列表
    SVN 中trunk、branches、tags都什么意思?
    SVN服务器搭建和使用(一)
    逗号分隔字符串转换为一张表--解决查询in(逗号分隔字符串)出错问题
    判断函数是否存在、判断函数是否存在并执行
  • 原文地址:https://www.cnblogs.com/lifexy/p/8185509.html
Copyright © 2011-2022 走看看