该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文档