[root@localhost u-boot-2014.04]# cd board/tq2440/
修改Makefile
将
obj-y := smdk2410.o
改为:
obj-y := tq2440.o
保存退出
拷贝配置文件(使用相似的smdk2410开发板的配置文件)
[root@localhost u-boot-2014.04]# cp include/configs/smdk2410.h include/configs/tq2440.h
增加开发板配置选项(编译之前需要配置,如make smdk2410_config 现在需添加支持make tq2440_config)
在顶层目录下的 Makefile 中搜索不到 smdk2410
在顶层目录执行如下命令
得到的结果为:
因此可知smdk2410的配置信息在根目录的boards.cfg文件中定义,所以我们同样仿照sdmk2410来定义我们的tq2440
在boards.cfg添加如下信息:
Active arm arm920t s3c24x0 - tq2440 tq2440 -
由于我在board目录下创建开发板目录,所以Vendor指定为空
二、配置时钟
先大致看一下配置文件include/configs/tq2440.h
#define CONFIG_ARM920T /* This is an ARM920T Core */
#define CONFIG_S3C24X0 /* in a SAMSUNG S3C24x0-type SoC */
#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
这里是高级别的一些配置,配置了S3C2410SoC和SMDK2410Board,跟我使用的开发板不一致
根据我自己的开发板tq2440进行如下配置
//#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440
#define CONFIG_AUTO_COMPLETE /* 开启命令自动补全 */
#define CONFIG_SYS_PROMPT "TQ2440 # " /* 命令提示符 */
注:红色的为新加入的 黑色的为原本就有的
屏蔽一些暂时不用的支持,用的时候再加上
#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 */
#endif
#if 0
#define CONFIG_USB_OHCI
#define CONFIG_USB_OHCI_S3C24XX
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#endif
#define CONFIG_CMD_BSP
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
//#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
//#define CONFIG_CMD_NAND
//#define CONFIG_CMD_PING
//#define CONFIG_CMD_REGINFO
//#define CONFIG_CMD_USB
/*
* File system
*/
#if 0
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#endif
从连接脚本文件arch/arm/cpu/u-boot.lds我们可以看出u-boot执行的第一个文件是arch/arm/cpu/arm920t/start.S
修改arch/arm/cpu/arm920t/start.S文件
#endif /* CONFIG_S3C2440 */
#endif /* CONFIG_S3C24X0 */
board/tq2440/tq2440.c 中 board_early_init_f() 函数也初始化了时钟,因为我在start.S中已初始化了时钟,
所以屏蔽掉 board_early_init_f() 中对时钟的初始化代码
可以先配置 u-boot 支持直接烧写进内存 SDRAM 运行
修改配置文件 tq2440.h
#define CONFIG_SYS_TEXT_BASE 0x32000000
CONFIG_SYS_TEXT_BASE 指定了代码的加载地址,待会编译好后生成可执行二进制文件
u—boot.bin,就要把 u-boot.bin 下载到该地址
我们现在需要直接烧写进内存运行,而底层初始化代码还没移植,所以我们需要跳过底层初始化
查看arch/arm/cpu/arm920t/start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
如果没有定义 CONFIG_SKIP_LOWLEVEL_INIT 就跳转 cpu_init_crit 函数执行,该函数进行了一些底
层的初始化,比如内存。因为下面我们直接将u-boot下载到内存中运行,如果在内存中运行的同时再
初始化内存,那么内存中的数据代码会遭到破坏。
所以我们在配置文件tq2440.h中定义该宏
#define CONFIG_SKIP_LOWLEVEL_INIT
修改一下顶层Makefile:
配置:
如果配置成功会出现:Configuring for tq2440 board...
编译:
编译完成生成可执行二进制文件 u—boot.bin ,开发板启动原有好的u-boot
将u-boot.bin下载到SDRAM的 0x32000000 地址,然后跳转到 0x32000000 运行
我这里使用的是tftp下载的方式:
EmbedSky> tftp 32000000 u-boot.bin
EmbedSky> go 32000000
在tq2440.h中定义DEBUG宏
#define DEBUG
重新编译 并使用刚才的方法下载到SDRAM上
可以知道已经探测到开发板的flash的厂家ID为0x1c,设备ID为0x2249
在 jedec_table 表中增加 TQ2440 开发板的 NOR FLASH(EN29LV160AB) 内容
该文件位于 u-boot-2014.04\drivers\mtd\Jedec_flash.c 第166行
在static const struct amd_flash_info jedec_table[]
的末尾添加:
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
{ /* TQ2440 EN29LV160AB */
.mfr_id = 0x1c, /* manufacturer_id */
.dev_id = 0x2249, /* device_id */
.name = "EON EN29LV160AB",
.uaddr = {/* 因为NOR FLASH的ADDR0接到了S3C2440的ADDR1 */
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000, 1),
ERASEINFO(0x02000, 2),
ERASEINFO(0x08000, 1),
ERASEINFO(0x10000, 31),
}
},
#endif
};
在 tq2440.h 中定义 CONFIG_SYS_FLASH_LEGACY_1024Kx16
注释掉512K的宏
//#define CONFIG_SYS_FLASH_LEGACY_512Kx16
#define CONFIG_SYS_FLASH_LEGACY_1024Kx16
重新编译并下载到 开发板:
测试flash读写是否正常
读取0x32000000地址的0x10字节数据到0x0地址,然后比较两份数据是否相等
注意:从flinfo中可以看出0地址所在扇区是RO,要先解保护
TQ2440 # flinfo
TQ2440 # protect off all /*打开写保护*/
TQ2440 # erase 0 7ffff /*先擦除在写入*/
........... done
Erased 11 sectors
TQ2440 # cp.b 32000000 0 10
Copy to Flash... done
TQ2440 # cmp.b 0 32000000 10
Total of 16 byte(s) were the same
再来读:
TQ2440 # md.b 32000000 10
32000000: 0f 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
TQ2440 # md.b 0 10
00000000: 0f 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
两次读取的数据一样,说明nor flash读写正常。
三、移植网卡DM900
网卡DM9000的驱动为drivers/net/dm9000x.c,我们需要将它编译进u-boot,查看drivers/net/Makefile
38 COBJS-$(CONFIG_DRIVER_DM9000) +=dm9000x.o
如果定义了CONFIG_DRIVER_DM9000就将dm9000x.o编译进u-boot,在配置文件tq2440.h中定义该
宏
#define CONFIG_DRIVER_DM9000
在第一步已经经网卡CS8900的相关配置注释掉了重新编译出错
在tq2440.h中添加定义
#define CONFIG_DM9000_NO_SROM
(如果不设置这个宏,uboot会打印类似:
Warning: dm9000 MAC addresses don't match:
Address in SROMis ff:ff:ff:ff:ff:ff
Address in environmen tis 00:0c:29:2a:5c:a5
的信息)
#define CONFIG_DM9000_BASE 0x20000000 //tq2440开发板的网卡dm9000接在S3C2440的bank4
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4) //tq2440开发板的网卡dm9000的cmd引脚接在S3C2440的ADDR2
打开之前第一步暂时注释掉的宏
#define CONFIG_CMD_PING
重新编译下载 看输出信息:
略~~~~~~~~~~~~~~~
九、支持烧写yaffs文件系统
执行:
Nguhyw # ? nand
查看输出信息并没有对yaffs的信息。
在内核里搜索 .yaffs
查看common/cmd_nand.c 第 709行。
发现宏 CONFIG_CMD_NAND_YAFFS 未定义,那好,既然你没有定义那我就来定义你不就可以了吗?
在tq244.h里定义这个宏。
然后覆盖到linux的文件上,重新编译,然后下载到开发板上。
设置参数
set ethaddr 00:12:34:56:ab:cd; set ipaddr 192.168.1.119; set serverip 192.168.1.123
或使用uboot来更新自己:
tftp 30000000 u-boot.bin; nand erase.part u-boot; nand write 30000000 u-boot
Nguhyw # mtdpart default
set 'nand read 30000000 kernel;bootm 30000000'
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
set machid 16a
mtdpart default
save
tftp 30000000 uImage; nand erase.part kernel; nand write 30000000 kernel
tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 0x00460000 $filesize
已经挂载上yaffs2文件系统,因为yaffs文件系统是好的,所以是u-boot烧写yaffs文件系统的问题
YAFFS中,文件是以固定大小的数据块进行存储的,块的大小可以是512字节、1024字节或者2048
字节。这种实现依赖于它能够将一个数据块头和每个数据块关联起来。每个文件(包括目录)都有一
个数据块头与之相对应,数据块头中保存了ECC(ErrorCorrectionCode)和文件系统的组织信息,用于
错误检测和坏块处理。
查看代码common/cmd_nand.c
调 用 函 数drivers/mtd/nand/nand_util.c 函数nand_write_skip_bad 第 554行
if (!need_skip && !(flags & WITH_DROP_FFS)){
rval=nand_write(nand,offset,length,buffer);
这里如果没有坏块而且没有指定WITH_DROP_FFS标志就执行nand_write(nand,offset,length,buffer);
而我们需要执行write_oob(nand,offset,&ops);所以应该加上之前传入的参数
if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB))
和 WITH_YAFFS_OOB
设置参数
set ethaddr 00:12:34:56:ab:cd; set ipaddr 192.168.1.119; set serverip 192.168.1.123
或使用uboot来更新自己:
tftp 30000000 u-boot.bin; nand erase.part u-boot; nand write 30000000 u-boot
Nguhyw # mtdpart default
set bootcmd 'nand read 30000000 kernel;bootm 30000000'
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
tftp 30000000 uImage; nand erase.part kernel; nand write 30000000 kernel
tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 0x00600000 $filesize
至此u-boot成功支持nand falsh的烧写 以及启动
十、 添加 NAND FLASH 硬件 ECC
在tq2440.h 中定义如下宏定义。
#define CONFIG_S3C2440_NAND_HWECC
#ifdef CONFIG_S3C2440_NAND_HWECC
#define CONFIG_SYS_NAND_ECCSIZE 2048
#define CONFIG_SYS_NAND_ECCBYTES 4
#endif
修改 arch/arm/include/asm/arch-s3c24x0/s3c24x0.h:s3c2440_nand结构体,添加寄存器
u32 nfstat0;
u32 nfstat1;
u32 nfmecc0;
u32 nfmecc1;
u32 nfsecc;
u32 nfsblk;
u32 nfeblk;
修改 drivers/mtd/nand/s3c2440_nand.c
修改函数s3c2440_nand_enable_hwecc 为:
修改函数s3c2440_nand_calculate_ecc 为:
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
writel(readl(&nand->nfcont) |(1<<5),&nand->nfcont);/* 锁定main区ECC*/
u32 mecc0;
mecc0 = readl(&nand->nfmecc0);
ecc_code[0] = mecc0 & 0xff;
ecc_code[1] = (mecc0 >> 8) & 0xff;
ecc_code[2] = (mecc0>>16) & 0xff;
ecc_code[3] = (mecc0>>24) & 0xff;
debug("s3c2440_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
mtd , ecc_code[0], ecc_code[1], ecc_code[2],ecc_code[3]);
return 0;
}
修改s3c2440_nand_correct_data 函数 为:
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{