免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1679 | 回复: 0

[BootLoader] u-boot2012移植笔记分享 [复制链接]

论坛徽章:
0
发表于 2015-05-04 19:11 |显示全部楼层

该u-boot是移植在JZ2440V2开发板上的,但移植过程跟其他板子移植是一样的,我是在看韦东山老师视频做的笔记,每一步都很详细,有兴趣的可以看看。有错误的地方请指出,谢谢
移植u-boot到jz2440开发板
第一:u-boot移植

首先配置
make smdk2410_config
编译一下u-boot
make
发现编译不通过,要切换编译工具,现在使用arm-linux-gcc 4.3.2
再make 完成编译,把u-boot.bin烧写到板子上看看状况
发现串口没有输出。
所以要分析原因,分析Makefile
分析编译过程来知道u-boot的构成
删掉刚才编译的u-boot,重新编译,只关心最后一条链接命令
arm-linux-ld  -pie -T u-boot.lds -Bstatic -Ttext 0x0 arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o common/libcommon.o
从链接命令看到链接文件u-boot.lds 那么,去看看里面的内容
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;                //链接地址是0,那么说明该u-boot是NorFash启动
. = ALIGN(4);
.text :
{
  __image_copy_start = .;
  arch/arm/cpu/arm920t/start.o (.text)  //从start.o开始运行,那么我们就从start.o开始分析
  *(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
  *(.data)
}
. = ALIGN(4);
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__image_copy_end = .;
.rel.dyn : {
  __rel_dyn_start = .;
  *(.rel*)
  __rel_dyn_end = .;
}
.dynsym : {
  __dynsym_start = .;
  *(.dynsym)
}
_end = .;
. = ALIGN(4096);
.mmutable : {
  *(.mmutable)
}
.bss __rel_dyn_start (OVERLAY) : {
  __bss_start = .;
  *(.bss)
   . = ALIGN(4);
  __bss_end__ = .;
}
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
}

分析start.S
u-boot的启动过程
1.set the cpu to SVC32 mode
2.turn off the watchdog
3.mask all IRQs by setting all bits in the INTMR
4.default FCLK is 120 MHz  /* 设置分频比例 */
5.cpu_init_crit  //设置SDRAM
6.Set stackpointer in internal RAM to call board_init_f  //设置栈,调用board_init_f
7.board_init_f
                memset((void *)gd, 0, sizeof(gd_t));//将gd_t结构体清0
                调用init_sequence函数数组执行
                        arch_cpu_init
                        board_early_init_f
                        timer_init
                                定时器的初始化get_PCLK()
                                        get_HCLK()
                                                #ifdef CONFIG_S3C2440                //发现该u-boot也支持2440,到时可以配置这个宏
                        init_baudrate
                        serial_init
8.relocate_code(addr_sp, id, addr); //重定位代码
relocate_code:
        mov        r4, r0        /* save addr_sp */
        mov        r5, r1        /* save addr of gd */
        mov        r6, r2        /* save addr of destination */
这段代码也说明该u-boot只支持NORfash

、分析relocate_code(addr_sp, id, addr);的参数[ 在board.c/board_init_f函数中]
addr_sp存在r0 id存在r1 addr存在r2


gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
addr -= gd->mon_len;                /* 保留一块内存给bss等 */
gd->mon_len = _bss_end_ofs;
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end__ - _start  /* 程序的大小 */

addr_sp = addr - TOTAL_MALLOC_LEN;
addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;        /* 0x3000,0000+64M 初始值*/
addr=0x3400,0000
addr -= (4096 * 4);
执行上一句后,addr=33ff0001
addr &= ~(0x10000 - 1);                /* 清低16位 */
那么addr=33ff0000
addr_sp = addr - TOTAL_MALLOC_LEN;
addr_sp -= sizeof (bd_t);
bd = (bd_t *) addr_sp;                                /* bd指向 addr_sp */
gd->bd = bd;                /* gd中的某个成员指向bd */
addr_sp -= sizeof (gd_t);
id = (gd_t *) addr_sp;
gd->irq_sp = addr_sp;
addr_sp -= 12;
综上所述:
addr -= (4096 * 4);
addr &= ~(0x10000 - 1);
addr -= gd->mon_len;
留给data,bss,code
Uboot就是拷到这里

addr_sp = addr - TOTAL_MALLOC_LEN;



addr_sp -= sizeof (bd_t);

addr_sp -= sizeof (gd_t);

addr_sp -= 12;

栈:往下增长

SP






gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);




了解过程后,我们要修改代码,

在include目录下
把configs目录下的smdk2410.h复制为smdk2440.h
在board目录下
把samsung目下的smdk2410目录复制为smdk2440

修改之后,配置,编译,看能不能通过

make smdk2440_config

发现不能通过配置,那么查看Makefile

在Makefile中没有找到smdk2410

那么在源代码中搜索一下 grep  " smdk2410" * -nR

arch/arm/include/asm/mach-types.h:1644:# define machine_is_smdk2410()        (machine_arch_type == MACH_TYPE_SMDK2410)
arch/arm/include/asm/mach-types.h:1646:# define machine_is_smdk2410()        (0)
board/samsung/smdk2410/Makefile:28:COBJS        := smdk2410.o
board/samsung/smdk2440/Makefile:28:COBJS        := smdk2410.o
boards.cfg:65:smdk2410                     arm         arm920t     -                   samsung        s3c24x0
MAINTAINERS:750:        smdk2410        ARM920T

vim borads.cgf

复制smdk2410为smd2440

再make smdk2440_config

配置成功

编译
make

编译通过,烧写,但绝对是不能通过的

所以,要调试程序

根据步骤,分析启动过程
该u-boot的不足:
1.时钟没设置只设置了分频比例
2.内存的设置也不对,我们是基于smdk2410的板子修改,所以该sdram的配置是没有用的

那么可以确定修改的地方:1是时钟设置 2是SDRAM的初始化
根据我们之前自己写bootloader事已经有了设置,可以挪用过来使用
处理措施:把MPLL的设置放到start.S中设置,取消

烧写进去的u-boot有反应了,但是出现乱码
继续分析:
1.查看代码发现get_HCLK中#ifdef CONFIG_S3C2440没有被配置
措施:include/smdk2440.h中定义#ifdef CONFIG_S3C2440注释掉#ifdef CONFIG_S3C2410

发现编译出错,从第一个错误开始修改

简单的解决办法,修改makefile让这个文件不要编译进来
在smdk2440.h中去掉#define CONFIG_NAND_S3C2410
去掉#define CONFIG_CMD_NAND

解决掉错误,编译烧写进去看看效果,乱码没有了

U-Boot 2012.04.01 (Apr 25 2015 - 19:51:22)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###

2.支持NANDFLASH启动
根据提示Flash不可用
将上次自己写u-boot的代码拷贝到板子目录

2.1 修改UBOOT支持NAND启动
    原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)"
    使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)
2.2 去掉 "-pie"选项
      arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
      
2.3 参考"毕业班第1课"的start.S, init.c来修改代码
      把init.c放入board/samsung/smdk2440目录, 修改Makefile
      修改CONFIG_SYS_TEXT_BASE为0x33f00000
      修改start.S
bl nand_init_ll
mov r0, #0
ldr r1, _TEXT_BASE
        ldr r2, _bss_start_ofs
       
        bl copy_code_to_sdram
        bl clear_bss
        ldr pc, =call_board_init_f

ldr r1, _TEXT_BASE  //33f00000
        bl board_init_r

2.4 修改board_init_f, 把relocate_code去掉
将board_init_f 修改为unsigned int board_init_f 注释掉relocate_code  最后面返回return (unsigned int)id作为board_init_r的参数
去掉addr -= gd->mon_len;
        addr &= ~(4096 - 1);
addr=_TEXT_BASE

void board_init_r(gd_t *id, ulong dest_addr)
dest_addr就是程序的链接地址,也就是33f000000   /*  这是定死的值 */
2.5 修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
      ./arch/arm/cpu/u-boot.lds:
      
      board/samsung/smdk2440/libsmdk2440.o



3.支持Nor FLASH
CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###

根据上面的的提示作为参考,然后修改代码
搜索Flash

cfi_flash_bank_addr 在Linux下搜索
drivers/mtd/cfi_flash.c:104:phys_addr_t cfi_flash_bank_addr(int i)
确定了cfi_flash_bank_addr在smdk2440.h中定义为0x00000000也就是NorFlash的地址
CONFIG_FLASH_CFI_LEGACY在配置文件中有定义
flash_detect_legacy旧的方法
flash_get_size新的方法获取NorFlash
1.在board.c中注释掉
//puts(failed);
//hang();
添加调试信息
怎么添加?
#define _DEBUG        1
#define DEBUG 1

编译烧写进板子,查看调试信息

Flash: fwc addr (null) 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 (null) cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
fwc addr (null) cmd ff 00ff 16bit x 16 bit
fwc addr (null) cmd 90 0090 16bit x 16 bit
fwc addr (null) cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 13 ea00 0
0 KB
*** Warning - bad CRC, using default environment

根据这些调试信息进行代码修改

1.JEDEC PROBE搜索一下,查看到
debug("JEDEC PROBE: ID %x %x %x\n",
                                                info->manufacturer_id,
                                                info->device_id,
                                                info->device_id2);

2.jedec_flash_match,该函数做的内容就将info传入跟里面的某个数组比较,看是否匹配
如果不匹配,那么就认为没有找到
那么,我们需要查看数据手册知道该芯片的info
阅读norflash芯片手册

如果想读Manifacture ID的话
填入AA,55,读x00就得到C2
Device ID是
芯片手册有说明
这两个值正好对应串口打印出来的信息,但是为什么还是失败呢,很显然,jedec_flash_match函数在里面没有找到匹配的数组.所以,我们需要添加
进入jedec_flash_match函数
                        jedec_table
添加数组就行了
{
                .mfr_id                = (u16)MX_MANUFACT,     /* 厂家ID。从芯片手册中得到 */
                .dev_id                = 0x2249,                                /* 芯片手册中得到的设别ID */
                .name                = "MXIC MT29LV160DB",
                .uaddr                = {                /*         解锁地址 */
                        [1] = MTD_UADDR_0x0555_0x02AA /* x16  0表示8位,1表示16位、*/
                },
                .DevSize        = SIZE_2MiB,                /* 总大小 */
                .CmdSet                = P_ID_AMD_STD,                        /* 命令集 */
                .NumEraseRegions= 4,                                /* 几种模式 */


                .regions        ={
                        ERASEINFO(16*1024,1),
                        ERASEINFO(8*1024,2),
                        ERASEINFO(32*1024,1),
                        ERASEINFO(64*1024,31),
                }
        },

NOR FLASH读取跟内存差不多,只需要确定他的基地址跟位宽就行了

修改后,编译烧写进板子查看状况

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: fwc addr (null) 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 (null) cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
ERROR: too many flash sectors
2 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0

那么,该u-boot识别了板子使用的芯片,现在可以去掉调试信息了
还需要重新设置栈,在start.S中,定义一个全局变量
.global base_sp
base_sp:
.long base_sp

在第二阶段的时候也就是board_init_r时,读sp
ldr sp,         base_sp
在board.c中的board_init_f函数中声明一下
extern ulong base_sp

在最后一次调用addr_sp的时候,将addr_sp赋给base_sp

用这个u-boot来更新自己,用loady命令
用loady下载
Loady 32000000
下载完成,输入命令
protect off all
erase 0 7ffff
cp.b 32000000 0 80000
reset

再次测试
protect off all
erase 80000 8ffff
cp.b 30000000 80000 10000
cmp.b 30000000 80000 10000

发现没有问题了

4.支持Nnad FLASH


在第一节的时候我们为了解决问题把#define CONFIG_NAND_S3C2410
#define CONFIG_CMD_NAND给注释掉了,但现在我们要支持NAND FLASH的读写,
得把他回复过来
重新编译,发现出现一大堆的错误
s3c2410_nand.c:57: warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c: In function 's3c2410_dev_ready':
s3c2410_nand.c:85: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:87: error: dereferencing pointer to incomplete type
s3c2410_nand.c: In function 'board_nand_init':
s3c2410_nand.c:129: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:150: error: dereferencing pointer to incomplete type
s3c2410_nand.c:153: error: dereferencing pointer to incomplete type
s3c2410_nand.c:154: error: dereferencing pointer to incomplete type

这些错误可以从第一个错误开始修改
为何会出现以上错误,因为我们把CONFIG_S3C2410给注释掉了,只有定义了这个宏,s3c2410_nand结构体才有效

NANDFLASH
从芯片手册上看到,ALE为高电平时,传输的是地址,CLE为高电平时,传输的命令。ALE CLE为低时,传输的
是数据,NANDFLASH只有8条数据线,如果要读写擦除NANDFLASH,需要先发出命令,发出地址才可以


把drivers\mtd\nand\s3c2410_nand.c复制为s3c2440_nand.c
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
修改smdk2440.h

#ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif
NADN FLASH需要的函数
1.选中、取消选中
2、发命令
3.发地址
4.判断状态
5.读写

分析u-boot之NAND FLASH

        nand_init();
                nand_init_chip(i);
                        board_nand_init(nand)                //设置nand_chip结构体,设置时序,初始化。提供底层的函数
                       
                        nand_scan(mtd, maxchips)        //这个函数扫描,肯定会用到board_nand_init提供的底层函数
                        那么就要分析nand_scan(mtd, maxchips),看看board_nand_init有哪些底层函数还没有提供
                                nand_scan_ident
                                        nand_set_defaults                //设置默认函数
                                                chip->select_chip = nand_select_chip;
                                                chip->cmdfunc = nand_command;
                                        nand_get_flash_type
                                                select_chip                        //调用默认函数
                                                chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);                //发出复位命令
                                                                nand_command                //既可以用来发命令,也可以发地址那会调用谁来做
                                                                        cmd_ctrl                        //调用该函数来做
                                                                        nand->cmd_ctrl = s3c2440_hwcontrol;
                                                                        那么就是调用了s3c2440_hwcontrol
                                                                        分析s3c2440_hwcontrol的参数
                                                                        1.ctrl:表示做什么。使能片选,取消片选,发命令还是发地址
                                                                        2.cmd:命令值
                                                                        那怎么判断ctrl是做什么的呢,需要看nand_command函数
                                                                        在nand_command函数中int ctrl = NAND_CTRL_CLE |                                                                                                                               NAND_CTRL_CHANGE;会这样设置,
                                                                static void nand_command(struct mtd_info *mtd, unsigned int command,
                         int column, int page_addr)
                                                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);        //发出读ID的命令
                                                *maf_id = chip->read_byte(mtd);                        //读厂家ID
                                                *dev_id = chip->read_byte(mtd);                        //读设备ID
                                nand_scan_tail
分析完成后,修改s3c2440_hwcontrol函数,让他只做发命令发地址的操作
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
        struct nand_chip *chip = mtd->priv;
        struct s3c2440_nand *nand = s3c2440_get_base_nand();

        if(ctrl&NAND_CLE)
                {
                        /* 发命令 */
                        writeb(cmd,&nand->nfcmd);
                }
        else(ctrl&NAND_ALE)
                {
                        /* 发地址 */
                        writeb(cmd,&nand->nfaddr);
                }

}

自己添加一个片选函数
static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
       
        struct s3c2440_nand *nand = s3c2440_get_base_nand();

        switch (chipnr) {
        case -1:        /* 取消片选 */
                nand->nfcont |=(1<<1);
                break;
        case 0:                        /* 使能片选 */
                nand->nfcont &=~(1<<1);
                break;

        default:
                BUG();
        }
                               
完成修改,编译烧写实验。成识别nand
                       
4.支持DM9000网卡                       
在drivers/net目录下的makefile中搜索一下DM9000,看到

从这得出,我们需要配置CONFIG_DRIVER_DM9000宏才能使用


①修改smdk2440.h使它支持网卡DM9000
#if 0
#define CONFIG_CS8900  /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#endif

然后编译出错:dm9000x.c:156: error: 'DM9000_DATA' undeclared (first use in this function)

查找原因:
book@book-desktop:/work/system/u-boot-2012.04.01$ grep "DM9000_DATA" * -Nr

参考别人的代码:进入vim include/configs/davinci_dm355evm.h

那我们也把这些东西放进去

#define CONFIG_DM9000_BASE              0x04014000
#define DM9000_IO                       CONFIG_DM9000_BASE
#define DM9000_DATA                     (CONFIG_DM9000_BASE + 2)
CONFIG_DM9000_BASE怎么得来的?
看板子原理图,看2440A芯片手册

板子上CPU发出的片选信号nGcs4,看2440手册得到基址
以上定义的这些值是怎么得来的?
网卡类似于内存的借口,怎么做?
A¡        设置内存控制器[有时序、位宽]
B¡        确定访问地址
C¡        板子的最终设置值为
D¡        #define CONFIG_DM9000_BASE              0x20000000
E¡        #define DM9000_IO                       CONFIG_DM9000_BASE
F¡        #define DM9000_DATA                     (CONFIG_DM9000_BASE  +4)()
G¡        为什么是加4(因为地址线为addr2)所以等于4        //二进制的1 0 0
H¡       
更改smdk2440.h和lowlevel_init.S里面的时序
还是有错误:看一下调用过程
eth_initialize
  board_eth_init
   cs8900_initialize
搜索一下Net:找到一些函数追查下去,看到貌似没有DM9000的初始化
看下DM9000X.C中有没有初始化函数
看到

这样可以在代码中搜索看别人怎么用的
grep "dm9000_initialize" * -nR

那我们就知道怎么用了

#ifdef CONFIG_DRIVER_DM9000
        rc = dm9000_initialize(bis);
#endif


现在可以用tftp下载代码了:
SMDK2410 # set ipaddr 192.168.1.17
SMDK2410 # set ethaddr 00:0C:29:67:65:5A


5.易用性修改及u-boot裁剪       

环境参数
环境参数会存在FLAH的某个地方,当u-boot启动的时候就去读这些参数,并判断是否有效,有效则用
无效就使用默认的参数

默认参数:默认参数是在代码中写死的
#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"

裁剪:
在配置文件中去掉不必要的宏。编译,如果出现一些错误,可以先make distclean 后再编译

规划分区:
可以参照内核的分区信息修改
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"

#define  CONFIG_ENV_IS_IN_NAND
#define  CONFIG_ENV_OFFSET                0x00040000        /* 偏移地址 */
#define  CONFIG_ENV_SIZE                0x20000                /* 这个值必须要以块的大小来定义比如128*2 128*3 */
#define  CONFIG_ENV_RANGE                CONFIG_ENV_SIZE  /* 擦除多大 */
#define  CONFIG_CMD_MTDPARTS
#define  CONFIG_MTD_DEVICE



1.在u-boot敲入save ? 查看一下,这个保存命令
显示是调用saveenv,那么我们在si工程中搜索一下,发现需要env_nand.c文件
那么env_nand.c在common目录下,我们去看看这个文件编译需要什么宏
打开它的Makfile就知道了
需要CONFIG_ENV_IS_IN_NAND 那么,我们就在配置文件中定义
2.查看saveenv函数发现还需要
CONFIG_ENV_RANGE       
CONFIG_ENV_OFFSET
CONFIG_ENV_SIZE
那么我们就定义呗
做好这些修改之后,编译烧写看看
U-Boot 2012.04.01 (Apr 27 2015 - 18:59:54)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
NAND:  256 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   dm9000
Hit any key to stop autoboot:  0

当设置了CONFIG_BOOTCOMMAND这个宏之后,就会有倒数的命令,这里还有个警告提示,是因为我们没有保存
环境参数,执行一下save命令重启就不会有了

移植到这里这个u-boot就算完整了,但是烧写还是很麻烦
比如,下载内核到内存 然后烧到nand flash
需要如下命令
tftp 30000000 uImage
nand erase 60000 200000  //擦除,从60000开始,擦除多大.擦除200000
nand write 30000000 60000 200000   /从30000000写到60000这里,写多大,写200000
这样烧写需要记住这些数字,很麻烦,那么我们为了简便,得修改代码用某些名字代替

输入mtd命令,或者mtdpart命令,发现没有这些命令。那么到源代码中搜索一下
grep "mtdpart" *-nR
发现有mtdpart命令,我们需要配置上去。因为我们命令中没有mtdpart,而源代码中是有的,
那么我们去看下Makefile,应该是需要宏
vim common/Makefile 搜下part
COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
发现需要这个宏才能把cmd_mtdparts编译进去,那我们在配置文件中定义
定义之后怎么划分区呢?
看看mtdparts_init函数,看看它在哪里会使用没找到,那么就在Bosard.c中初始化一下看看,错了再改
看看别人怎么用mtdparts ,然后随便找个,仿照着别人用
#define MTDIDS_DEFAULT                "nand0=jZ2440-0"                /* 哪一个设备 */
/* default mtd partition table */
#define MTDPARTS_DEFAULT        "mtdparts=jZ2440-0:256k(u-boot),128k(params)," \
                                                "2m(kernel)," \
                                                "-(rootfs);" \

修改后编译,出错,还需要CONFIG_MTD_DEVICE   //这个可以在参照代码中看到
如果tftp下载不了,那么修改一下MAC地址,但MAC地址不能多次修改,需要多次修改则在
配置文件中

修改好后编译烧写,但发现每次使用分区部分的命令时都需要mtdparts default,在bootcmd命令行中设置的
nand read 300000000 kernel;bootm 30000000 执行不了
那么,我可以在代码中修改,让它一开始就执行一次mtdparts default。在board.c中的board_init_r函数的
卡死函数上面设置一下,也就是main_loop。用命令函数来执行一次。run_command("mtdparts default",0);
这样就可以搞定了

再编译烧写,尝试烧写文件系统

一:
烧写JFFS2
tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 5b89a8
set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

完全没问题

二:
烧写YAFFS
tftp 30000000 fs_mini_mdev.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 260000 889bc0

发现在nand write.yaffs时没有这个命令
在si里搜索一下,发现CONFIG_CMD_NAND_YAFFS没有定义,那么在配置文件里定义编译看看

编译成功后再烧写 发现,挂载是挂载上去了,但是启动不了文件系统,在nand write.yaffs时发现一瞬间就写完了
这不符合常理。绝对是有问题的

VFS: Mounted root (yaffs filesystem).
Freeing init memory: 140K
Warning: unable to open an initial console.
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.

用nand dump 260000 查看数据

在nand_until文件中yaffs的oob错误
#ifdef CONFIG_CMD_NAND_YAFFS
                if (flags & WITH_YAFFS_OOB) {
                        int page, pages;
                        size_t pagesize = nand->writesize;
                        size_t pagesize_oob = pagesize + nand->oobsize;
                        struct mtd_oob_ops ops;

                        ops.len = pagesize;
                        ops.ooblen = nand->oobsize;
                        ops.mode = MTD_OOB_RAW;                        /* 修改为MTD_OOB_RAW 原值是MTD_OOB_AUTO*/
                        ops.ooboffs = 0;

                        pages = write_size / pagesize_oob;
                        for (page = 0; page < pages; page++) {
                                WATCHDOG_RESET();

                                ops.datbuf = p_buffer;
                                ops.oobbuf = ops.datbuf + pagesize;

                                rval = nand->write_oob(nand, offset, &ops);
                                if (rval)                /* 如果返回一个非0则跳出,显然是错误的 原值是 if(!rval)*/
                                        break;

                                offset += pagesize;
                                p_buffer += pagesize_oob;
                        }
                }
                else
#endif

修改后烧写启动文件系统成功,那么该U-boot已经完全移植成功了


6.制作补丁       


1.在u-boot目录中make distclean 退出目录,把目录名称修改为跟之前不同的就行,再解压U-boot

2.diff -urN 源文件 新文件 > 补丁名字

3.怎么使用补丁 在u-boot目录下 patch -p1  <  ../补丁文件

7.移植内核之框架介绍

参考移植内核3.4.20文档




您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP