/***************************************************
*u-boot版本:u-boot2012.04.01
*gcc版本:arm-linux-gcc-4.3.2
*服务器:ubuntu12.04
***************************************************/
一、建立单板
在board/复制smdk2410文件夹为smdk2440文件夹
在include/configs/将smdk2410.h - >smdk2440.h
二、修改时钟
1.进入smdk2440文件夹,修改函数board_early_init_f
注释掉:
//writel(0xFFFFFF, &clk_power->locktime);
/* configure MPLL */
//writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
// &clk_power->mpllcon);
2.在start.S里面:
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 400 MHz ! */
/*2. 设置时钟 */
ldr r0, =0x4c000014
// mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0]
/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
/* MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 启动ICACHE */
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 @ write it back
#endif /* CONFIG_S3C24X0 */
3. ③把lowlevel_init.S里面的lowlevel_init函数里面
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
4.$ vi boards.cfg
在boards.cfg文件下复制65行,修改boards.cfg:
仿照
smdk2410 arm arm920t - samsung s3c24x0
添加:
smdk2440 arm arm920t - samsung s3c24x0
5.完成以上三步,编译通过
6.乱码,查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440
7.处理措施:include/configs/smdk2440.h:
去掉CONFIG_S3C2410
添加#define CONFIG_S3C2440
编译,出现错误:
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
8. 处理措施:舍弃nand,使用我们自己的代码init.c
$ vi drivers/mtd/nand/Makefile //从makefile看出依赖于哪个宏,而不是在makefile里面注释掉
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
得知依赖的宏是CONFIG_NAND_S3C2410
进入:include/configs/smdk2440.h -->
有: /*
* NAND configuration
*/
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
所以我们屏蔽掉CONFIG_CMD_NAND宏即可
9.烧写
下面是uboot输出:
U-Boot 2012.04.01 (Jul 29 2013 - 20:26:01)
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 ### 串口输出正确
此时支持nor启动,但是不支持nand启动
/*##############################################################华丽分界线########################################################*/
修改UBOOT支持NAND启动
1.1 去掉 "-pie"选项,减少代码大小
grep "-pie" * -nR
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
如下:
ifndef CONFIG_NAND_SPL
#LDFLAGS_u-boot += -pie
endif
1.2 把init.c放入board/samsung/smdk2440目录,修改init.c文件主要是加上static , 修改Makefile
修改CONFIG_SYS_TEXT_BASE为0x33f80000 //0x34000000-33f80000 =512k,对于uboot足够
1.3 修改start.S
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
bl nand_init_ll
mov r0, #0 //src_addr
//ldr r1, =_start
ldr r1,_TEXT_BASE //地址固定 dest_addr
//ldr r2, =__bss_start //CONFIG_SYS_TEXT_BASE
//sub r2, r2, r1
//以上两条在这里是
ldr r2,_bss_start_ofs //len
bl copy_code_to_sdram
bl clear_bss
ldr pc,= call_board_init_f
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f //会调用重定位
=============================================================
//第一个参数由board_init_f传回来,存在r0里面 < ------------------------ -
ldr r1,_TEXT_BASE |
bl board_init_r //调用第二阶段 |
|
修改init.c |
|
__bss_end__名字有点差别 |
|
1.4 修改board_init_f, 把relocate_code去掉 |
//relocate_code(addr_sp, id, addr); |
删掉start.S里面相关代码,然后下面就执行第二阶段代码,实质上调用board_init_r |
1.5 修改board_init_r ,函数原型是void board_init_r(gd_t *id, ulong dest_addr) |
参数:r0 = 链接地址 |
r1 = id (可以使用board_init_f返回得到) -----------------------------------
相应的在board_init_f,把void变为snsigned int
并在最后加上:
return (unsigned int*)id;
1.6 修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
find -name "u-boot.lds"
./arch/arm/cpu/u-boot.lds:
board/samsung/smdk2440/libsmdk2440.o (.text)
1.7 编译报错
board.c:259: error: conflicting types for 'board_init_f'
previous declaration of 'board_init_f' was here
/work/tmp/u-boot-2012.04.01/include/common.h:276: error:
1.8 修改:/include/Common.h
/* arch/$(ARCH)/lib/board.c */
unsigned int board_init_f (ulong);
void board_init_r (gd_t *, ulong);
1.9 编译
#make distclean
#make smdk2440_config
#make
1.10 结果 ok。
注意:期间可能会发生各种乱七八糟的错误,尽量多执行make distclean然后再重新编译
2.0 地址映射不对
修改board_init_f函数:
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = CONFIG_SYS_TEXT_BASE; //or addr = _TEXT_BASE
此时发现u-boot.bin有40多k,包括bss段有70多k,那么我们设定的CONFIG_SYS_TEXT_BASE为0x33f80000到34000000有512k
所以这里还是不够的,那么我们在这里把CONFIG_SYS_TEXT_BASE设定为0x33f00000,预留1M,足够
.globl _bss_end_ofs //start.S 是程序本身的大小,可以在反汇编里面查看到大小
_bss_end_ofs:
.word __bss_end__ - _start
乱码:
因为CONFIG_CMD_NAND没有屏蔽掉
报错:/work/tmp/u-boot-2012.04.01/fs/yaffs2/yaffscfg.c:210: undefined reference to `nand_info'
处理:去掉#define CONFIG_YAFFS2 -- 》 在smdk2440.h里面
打印信息:说明支持NAND FLASH
U-Boot 2012.04.01 (Jul 26 2015 - 16:02:34)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
以上支持nand启动,但是并不是支持nand读写操作
/*######################################################华丽分界线####################################################*/
修改UBOOT支持NOR FLASH
此时,uboot会打印如下内容:
Flash: *** failed ***
### ERROR ### Please RESET the board ### 串口输出正确
搜索“Flash”看源码知:
board_init_r函数里面有: //arch/arm/lib/board.c
# ifdef CONFIG_SYS_FLASH_CHECKSUM
。。。
else {
puts(failed);
hang();
}而
hang()
void hang(void)
{
puts("### ERROR ### Please RESET the board ###
");
for (;;);
}
说明,由于没有定义CONFIG_SYS_FLASH_CHECKSUM,导致,在hang()里面死循环
修改为:
else {
puts("0 KB
"); //屏蔽掉hang()函数
//puts(failed);
//hang();
}
怎么样可以让nand里面识别出 nor flash ?
flash_init()里面有:
if (!flash_detect_legacy(cfi_flash_bank_addr(i), i)) //先使用flash_detect_legacy老版本来检测
//#ifdef CONFIG_FLASH_CFI_LEGACY使用这个宏来决定使用哪一个
flash_get_size(cfi_flash_bank_addr(i), i); //新方法
flash_detect_legacy里面调用
flash_read_jedec_ids(info);得到ID信息
jedec_flash_match //匹配ID信息
遍历jedec_table数组,找到对应芯片
我们使用的芯片是MX29LV160DB,但是uboot里面没有,而有相近的AM29LV040B,这是需要借助数据手册仿写一个
MX29LV160DB特性有:
大小:2M
位数:16位
扇区数目:4个
已经有的配置:
{
.mfr_id = (u16)MX_MANUFACT,
.dev_id = MX29LV040,
.name = "MXIC MX29LV040",
.uaddr = {
[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
},
.DevSize = SIZE_512KiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 1,
.regions = {
ERASEINFO(0x10000, 8),
}
},
以上各种参数说明:
struct amd_flash_info {
const __u16 mfr_id;
const __u16 dev_id;
const char *name;
const int DevSize;
const int NumEraseRegions;
const int CmdSet;
const __u8 uaddr[4]; /* unlock addrs for 8, 16, 32, 64 */
const ulong regions[6];
};
在上面 flash_get_size()函数里面有一句:
if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {
printf("ERROR: too many flash sectors
");
break;
}
。。。
for (i = 0; i < num_erase_regions; i++) { //搜索num_erase_regions可知扇区最多有4种
if (i > NUM_ERASE_REGIONS) {
printf ("%d erase regions found, only %d used
",
num_erase_regions, NUM_ERASE_REGIONS);
break;
}
搜索CONFIG_SYS_MAX_FLASH_SECT可以知道:
#define CONFIG_SYS_MAX_FLASH_SECT (19) 扇区数量最大19个
在目录drivers/mtd/jedec_flash.c
最终修改为:
{
.mfr_id = (u16)MX_MANUFACT, //厂家ID
.dev_id = 0x2249, //设备ID
.name = "MXIC MX29LV160DB", //名字
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */ //unlock addr
},
.DevSize = SIZE_2MiB, //size
.CmdSet = P_ID_AMD_STD, //命令类型
.NumEraseRegions= 4, //可擦除扇区数目,这里是4个
.regions = {
ERASEINFO(16*1024,1), //下面是具体的扇区列表
ERASEINFO(8*1024,2),
ERASEINFO(32*1024,1),
ERASEINFO(64*1024,31)
}
}
注意上面信息应该加载endif后面,即宏开关的控制
打印信息:
U-Boot 2012.04.01 (Aug 01 2015 - 20:48:21)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
搜索CPUID,发现,程序只执行到board_init_f里面init_sequence的print_cpuinfo/* display cpu info (and speed) */
添加打印信息board.c里面
#define _DEBUG 1 //add by hulig
#define DEBUG 1
最终ok
修改栈:
在start.S里面添加宏:
.globl base_sp //定义
base_sp:
.long 0
在board.c里面加上 //声明
extern ulong base_sp;
然后board_init_f 最后调用 //使用
base_sp = addr_sp;
在start.S里面调用board_init_r之前重新设置栈
ldr sp,base_sp
编译通过。
打印信息:
U-Boot 2012.04.01 (Aug 03 2015 - 21:24:22)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
SMDK2410 #
/*#################################################我是分界线###############################################*/
修改UBOOT支持NAND FLASH
修改:include/configs/smdk2440.h: #define CONFIG_CMD_NAND
报错:
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
原因: writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
寄存器指向的是s3c2410的寄存器,所以要使用nand,还需要重新设置寄存器
把driversmtd
ands3c2410_nand.c复制为s3c2440_nand.c ,把2410都替换成2440并修改Makefile
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o ==>
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
同时需要修改配置文件smdk2440.h
/*
* NAND configuration
*/
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410 == >#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2410_NAND_HWECC ==>#define CONFIG_SYS_S3C2440_NAND_HWECC
分析过程:
nand_init
nand_init_chip
board_nand_init
设置nand_chip结构体, 提供底层的操作函数
nand_scan
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip; //上面chip->select_chip为空,就使用这里默认的函数,但是这里选中后没做任何事
chip->cmdfunc = nand_command; //
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_command() // 即可以用来发命令,也可以用来发列地址(页内地址)、行地址(哪一页) nand_base.c
chip->cmd_ctrl
s3c2440_hwcontrol
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
分析:
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
/*ctrl : 表示做什么,选中/取消片选还是发命令或者发地址
*cmd :命令值或地址值
*
修改:
1. ./drivers/mtd/nand/s3c2440_nand.c
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
debug("board_nand_init()
");
writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);
/* initialize hardware */
#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
tacls = CONFIG_S3C24XX_TACLS;
twrph0 = CONFIG_S3C24XX_TWRPH0;
twrph1 = CONFIG_S3C24XX_TWRPH1;
#else
tacls = 4;
twrph0 = 8;
twrph1 = 8;
#endif
#if 0 // 屏蔽掉
cfg = S3C2440_NFCONF_EN;
cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
#endif
cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4); //使用这个参数
writel(cfg, &nand_reg->nfconf);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
nand->IO_ADDR_W = (void *)&nand_reg->nfdata;
nand->select_chip = NULL; //这里我们不用,s3c2440_hwcontrol这个里面设置片选
//这里需要我们自己来写
...
}
2. 修改片选函数drivers/mtd/nand/s3c2440_nand.c 里面s3c2440_hwcontrol函数
/*add by fanlin*/
if (ctrl & NAND_NCE)
writel(readl(&nand->nfcont) & ~(1<<1), //以前拷贝的是2410里面的,这里的片选控制有区别
&nand->nfcont);
else
writel(readl(&nand->nfcont) | (1<<1),
&nand->nfcont);
这个函数我们都不用,片选重新写
//ctrl : 表示做什么,选中/取消片选还是发命令或者发地址
//dat :命令值或地址值 根据nand_command重写
static void s3c2440_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
if(ctrl & NAND_CLE)
{
/*发命令*/
writeb(dat,&nand->nfcmd);
}
else if(ctrl & NAND_ALE)
{
/*发地址*/
writeb(dat,&nand->nfaddr);
}
}
3. 使能函数还有
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
NFCONT = (1<<4)|(1<<1)|(1<<0);
写成:
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
writel((1<<4)|(1<<1)|(1<<0),&nand_reg->nfcont);
放在:
cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4); //使用这个参数
writel(cfg, &nand_reg->nfconf);
这两句后面
4. 选中函数nand->select_chip = s3c2440_nand_select;
参考nand_set_defaults 在nand_base.c里面
chip->select_chip = nand_select_chip;
static void nand_select_chip(struct mtd_info *mtd, int chipnr)
{
struct nand_chip *chip = mtd->priv;
switch (chipnr) {
case -1: //不选
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
break;
case 0: //选中
break;
default:
BUG();
}
}
我们的代码写成:放在s3c2440_nand.c里面,修改函数名字
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();
}
}
打印信息如下:
U-Boot 2012.04.01 (Aug 06 2015 - 22:00:36)
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: CS8900-0
SMDK2410 #
说明nand flash已经识别了
/****************************************我是分界线*****************************************/
修改u-boot支持DM9000网卡
搜索dm9000,发现在/drivers/net里面,查看Makefile有:
COBJS-$(CONFIG_CS8900) += cs8900.o
COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
所以需要定义CONFIG_DRIVER_DM9000这个宏,而应该去掉cs9000,在smdk2440.h里面
#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)
查找DM9000_DATA,发现其他用这个不仅仅是定义CONFIG_DRIVER_DM9000
如:
/* Hardware drivers */
/* DM9000 */
#define CONFIG_NET_RETRY_COUNT 20
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x2c000000 //这个值一定不会适合我们的开发板
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 0x400)
#define CONFIG_DM9000_USE_16BIT 1
#define CONFIG_DM9000_NO_SROM 1
#undef CONFIG_DM9000_DEBUG
以上参数应该只是定义了,但是值都不适用,怎么修改呢?
1.设置内存控制器(时序,位宽) 这个在设置sdram里面说明
2.确定访问地址
根据三星手册,知道,网卡在内存地址范围是0x20000000 ~ 0x28000000
最终修改为:
#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
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#endif
编译通过,烧写后打印信息如下:
Net: No ethernet found.
调用过程:
board.c
eth_initialize
board_eth_init
cs8900_initialize //这里是cs8900的初始化函数,在smdk2410.c里面
修改:
参看别的单板怎么使用:
grep "dm9000_initialize" * -nR
其中格式为;
board/vpac270/vpac270.c:141: return dm9000_initialize(bis);
所以:
修改smdk2410.c 里面board_eth_init函数:
#ifdef CONFIG_CS8900
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef CONFIG_DRIVER_DM9000
rc = dm9000_initialize(bis);
#endif
烧写识别了dm9000
输入print,输出ip信息,要ping通,需要先设置ip地址
set ipaddr 192.168.1.9
set serverip 192.168.1.17
注意:不要使用save命令
现在可以ping通服务器了
以上移植支持网卡,也支持烧写,还可以启动内核:
/***************************************分界线*****************************************/
修改默认参数:
搜索default environment
在Env_common.c函数里面:
default_environment结构体
default_environment结构体定义在env_common.c里面
其中有:
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS " "
#endif
这里CONFIG_BOOTARGS没有定义,bootargs是传给内核的环境变量,在smdk2440.h里面定义CONFIG_BOOTARGS
#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
此外设置bootcmd参数:
#define CONFIG_BOOTCOMMAND "nand read 30000000 0x30008000 0x200000;bootm 30000000"
假设从0x30008000读2M到30000000
设置ip
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.10
#define CONFIG_SERVERIP 192.168.1.17
#define CONFIG_ETHADDR 00:0c:29:45:c4:c3
裁剪:
在配置文件smdk2440.h里面屏蔽掉不用的项;
1.USB support (currently only works with D-cache off)
2.RTC
3.Boottp
4.文件系统
修改默认分区:
打印出来的分区信息:
0x00000000-0x00040000 : "bootloader" //256k
0x00040000-0x00060000 : "params" //
0x00060000-0x00260000 : "kernel" //
0x00260000-0x10000000 : "root"
原来的环境变量的配置:
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
上面说过不要用save命令保存环境变量设置,目的是防止flash被破坏:
查看save命令帮助信息,知道saveenv,搜索saveenv
或者在SI里面搜索可得,在common目录下看Makefile,知道依赖上面宏
Env_nand.c (common):int saveenv(void)
makefile里面有:
COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
可知需要CONFIG_ENV_IS_IN_NAND
不光如此,还需要知道起始地址和大小
打开env_nand.c,里面有CONFIG_ENV_SIZE和CONFIG_ENV_OFFSET
上面的还不够,还需要擦除长度
nand_erase_options.length = CONFIG_ENV_RANGE;
即需要定义CONFIG_ENV_RANGE,设为CONFIG_ENV_SIZE
综上所知设置为:
#if 0
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00040000
#define CONFIG_ENV_SIZE 0x20000
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE
分区: ※uboot里面的分区不会作为参数传到内核里面,而是作为一些字符串代替一些数字方便操作uboot而已
这里使用mtdpart命令不被识别,搜索common/下的makefile后发现需要定义
COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
所以需要定义CONFIG_CMD_MTDPARTS
看看别人怎么做:搜索mtdpart_init()
在board.c里面调用mtdpart_init()
参考别的单板
#define MTDIDS_DEFAULT "nor0=TQM8xxL-0" 哪一个设备
#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot),"
"128k(dtb),"
"1664k(kernel),"
"2m(rootfs),"
"4m(data)"
改写如下:
#define CONFIG_CMD_MTDPARTS
#define MTDIDS_DEFAULT "nand0=jz2440-0"
#define MTDPARTS_DEFAULT "mtdparts=jz2440-0:256k(u-boot),"
"128k(params),"
"2m(kernel),"
"-(rootfs)"
以上编译出错:
/common/cmd_mtdparts.c:306: undefined reference to `get_mtd_device_nm'
查看代码发现get_mtd_device_nm在drivers/mtd里面的mtdcore.c里面实现了
再查看drivers/mtd下makefile:
COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o
也就是要定义CONFIG_MTD_DEVICE宏,在smdk2440里面定义这个宏,重新编译
烧写打印信息如下:
mtdparts variable not set, see 'help mtdparts'
no partitions defined
defaults:
mtdids : nand0=jz2440-0
mtdparts: mtdparts=jz2440-0:256k(u-boot),128k(params),2m(kernel),-(rootfs)
执行help mtdparts
Usage:
mtdparts
- list partition table //列出所有分区
mtdparts delall 删除所有分区
- delete all partitions
mtdparts del part-id //删除分区
- delete partition (e.g. part-id = nand0,1)
mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]
- add partition //添加分区
mtdparts default //默认分区
- reset partition table to defaults
从上面看出,可能是mtdparts default 没有被执行,看看有没有参考的
在common/cmd_mtdparts.c有mtdparts default如下:
U_BOOT_CMD(
mtdparts, 6, 0, do_mtdparts,
"define flash/nand partitions",
"
"
可知执行命令是
do_mtdparts
setenv("mtdparts", (char *)mtdparts_default);
其中mtdparts_default
#if defined(MTDPARTS_DEFAULT)
static const char *const mtdparts_default = MTDPARTS_DEFAULT;
#else
static const char *const mtdparts_default = NULL;
#endif
那么我们定义MTDPARTS_DEFAULT这个宏试试看
正确的办法是:
在cmd_mtdparts里面,函数do_mtdparts有:
if (argc == 2) {
if (strcmp(argv[1], "default") == 0) { //如果有参数default,比较,我们使用mtdpart命令不带参数,所以下面mtdparts_init()不会被执行
setenv("mtdids", (char *)mtdids_default); //写入默认参数
setenv("mtdparts", (char *)mtdparts_default);
setenv("partition", NULL);
mtdparts_init(); //执行初始化函数
return 0;
} else if (strcmp(argv[1], "delall") == 0) {
把default下面函数放在判断意外,无条件执行:
setenv("mtdids", (char *)mtdids_default); //写入默认参数
setenv("mtdparts", (char *)mtdparts_default);
setenv("partition", NULL);
mtdparts_init();
if (argc == 2) {
if (strcmp(argv[1], "default") == 0) { //如果有参数default,比较,我们使用mtdpart命令不带参数,所以下面mtdparts_init()不会被执行
//setenv("mtdids", (char *)mtdids_default); //写入默认参数
//setenv("mtdparts", (char *)mtdparts_default);
//setenv("partition", NULL);
//mtdparts_init(); //执行初始化函数
return 0;
} else if (strcmp(argv[1], "delall") == 0) {
这样就可以了。
注意:这个办法有缺点,就是每次都要先执行mtdpart命令,然后才能使用分区。
另一个办法是在mian_loop里面先执行:
run_command("mtdparts default",0); //这个办法很凑巧
参看100ask的u-boot-1.1.6里面关于这个的做法:
在main.c里面的main_loop有:
#ifdef CONFIG_JFFS2_CMDLINE
extern int mtdparts_init(void);
if (!getenv("mtdparts"))
{
run_command("mtdparts default", 0);
}
else
{
mtdparts_init();
}
#endif
我们使用:
#ifdef CONFIG_CMD_MTDPARTS
extern int mtdparts_init(void);
if (!getenv("mtdparts"))
{
run_command("mtdparts default", 0);
}
else
{
mtdparts_init();
}
#endif
//可以不用每次都输入mtdpart命令后才可以使用分区信息
修改struct mtd_device *current_mtd_dev = NULL; ==1的时候
mtdparts variable not set, see 'help mtdparts'
no partitions defined
data abort
pc : [<33f0578c>] lr : [<33f071ac>]
sp : 33affdc8 ip : 0000000f fp : 00000000
r10: 33f35510 r9 : 33b03060 r8 : 33afff64
r7 : 33b03100 r6 : 33b03100 r5 : 33f350f8 r4 : 33f32e28
r3 : 33f350f8 r2 : 50000010 r1 : 00000000 r0 : 00000001
Flags: nzCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
resetting ...
U-Boot 2012.04.01 (Aug 08 2015 - 22:43:07)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
NAND: 256 MiB
NAND read from offset 40000 failed -74
*** Warning - readenv() failed, using default environment
In: serial
Out: serial
Err: serial
Net: dm9000
Hit any key to stop autoboot: 0
/***************************************分界线********************************************/
支持yaffs2文件的烧写
tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 xx
set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2
烧写yaffs
tftp 30000000 fs_mini_mdev.yaffs2 //fs_qtopia.yaffs2
nand erase.part root
nand write.yaffs 30000000 260000 2f76b40
烧写内核:
tftp 30000000 uImage_4.3
nand erase.part kernel
nand write.jffs2 30000000 kernel 1c359c
更新uboot:
tftp 30000000 u_boot_new.bin;protect off all;erase 0 3ffff;cp.b 30000000 0 40000
1.在cmd_nand.c里面,要用yaffs选项,需要定义CONFIG_CMD_NAND_YAFFS
重新烧写发现只烧写了一页,最终问题点出现在nand_write_skip_bad这个函数里面
ops.len = pagesize;
ops.ooblen = nand->oobsize;
ops.mode = MTD_OOB_AUTO; //这里应该改成MTD_OOB_RAW
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) //fanlin 非0 才会错误
break;
去掉“!”即可。
补丁制作过程:
1.make distclean
2.rm u-boot.lds
3.cd ..
4.rm u-boot-2012.xx u-boot-2012.xx_ok
5.解压原来下载的源码tar xjf u-boot-2012.xx.tar
6.制作补丁:
diff -urN u-boot-2012.04.01 u-boot-2012.04.01_ok > u-boot-2012.04.01.patch
补丁制作ok。
重要:
1、
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
##############T T *** ERROR: Cannot umount
解决:
修改NFS.C里面的#define NFS_TIMEOUT (10*2000UL) 延时设长一点就可以了。
2、
挂接成功,但是Kernel panic - not syncing: No init found. Try passing init= option to kernel.
可能原因是uboot对yaffs不好,可以换成1.1.6实验,u-boot-1.1.6可以启动当前内核,说明u-boot-2012.04.01对yaffs不够好
修改uboot
cmd_nand.c
nand_write_skip_bad
if (!need_skip && !(flags & WITH_DROP_FFS)
修改为:
if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB))