#cd linux-2.6.14
#vi Makefile
修改内容如下
ARCH =arm
CROSS_COMPILE = arm-linux-
解压后,把交叉编译工具链的路径添加到环境变量中(修改/etc/bashrc文件)
2.设置Nand Flash分区
修改linux-2.6.14\arch\arm\mach-s3c2410\devs.c
(1)添加下列头文件
#include
#include
#include
(2)添加NandFlash分区表
static struct mtd_partition partition_info[]={
{
name:"bootloader",
size:0x00020000,
offset:0x0,
},
{
name:"param",
size:0x00010000,
offset:0x00020000,
},
{
name:"kernel",
size:0x001c0000,
offset:0x00030000,
},
{
name:"rootfs",
size:0x03e00000,
offset:0x00200000,
//mask_flags:MTD_WRITEABLE,
}//,
};
其中
name:代表分区名字
size:代表flash分区大小(单位:字节)
offset:代表flash分区的起始地址(相对于0x0的偏移)
(3)加入Nand Flash分区
structs3c2410_nand_setnandset={
nr_partitions:4,//5,
partitions:partition_info,
};
nr_partitions:指明partition_info中定义的分区数目
partitions:分区信息表
(4)建立Nand Flash芯片支持
struct s3c2410_platform_nandsuperlpplatform={
tacls:0,
twrph0:30,
twrph1:0,
sets:&nandset,
nr_sets:1,
};
tacls, twrph0, twrph1的意思见S3C2410手册的63,
这3个值最后会被设置到NFCONF中,见S3C2410手册66.
sets:支持的分区集
nr_sets:分区集的个数
(5)加入Nand Flash芯片支持到Nand Flash驱动
另外,还要修改此文件中的s3c_device_nand结构体变量,添加对dev成员的赋值
struct platform_device s3c_device_nand = {
.name= "s3c2410-nand",
.id= -1,
.num_resources= ARRAY_SIZE(s3c_nand_resource),
.resource= s3c_nand_resource,
.dev={
.platform_da
}
};
name:设备名称
id:有效设备编号,如果只有唯一的一个设备为1,
有多个设备从0开始计数.
num_resource:有几个寄存器区
resource:寄存器区数组首地址
dev:支持的Nand Flash设备
修改linux-2.6.14\arch\arm\mach-s3c2410\mach-smdk2410.c
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_nand,
};
(6)禁止Flash ECC校验
内核都是通过UBOOT写到Nand Flash的, UBOOT通过的软件ECC算法产生ECC校验码,这与内核校验的ECC码不一样,内核中的ECC码是由S3C2410中Nand Flash控制器产生的.所以,我们在这里选择禁止内核ECC校验.
修改linux-2.6.14\drivers\mtd\nand\s3c2410.c
找到函数s3c2410_nand_init_chip
最后一条语句chip->eccmode= NAND_ECC_SOFT;
改为chip->eccmode= NAND_ECC_NONE;
3.配置内核选项
参考smdk2410开发板的配置文件,将其默认的配置文件复制到内核代码的根目录下,然后开始配置内核
#cd linux-2.6.14
#cp arch/arm/configs/smdk2410_defconfig.config
#make menuconfig
注意:在每个选项前有个方括号,其中[*]/表示该选项加入内核编译;[ ]/<>表示不选择该选项;
图1 s3c2410 user manual, nand flash memory timing
显然s3c2410 user manual推荐值是TACLS=0 TWRPH0=1 TWRPH1=0
TACLS:1个HCLK TWRPH0:2个HCLK TWRPH1:1个HCLK
内核的频率为200MHZ,即FCLK=200MHZ,则HCLK=100MHZ(周期为10ns),所以
TACLS:10ns TWRPH0:20ns TWRPH1:10ns
图2 NAND Flash(K9F1208U0M) user manual,Read and Write timing
tCLS等价于图1中的TACLS;tWP等价于图1中的TWRPH0;tCLH等价于图1中的TWRPH1
图3 NAND Flash(K9F1208U0M) user manual
结合前3张图,可以看出对NAND Flash(K9F1208U0M)进行读写的顺序要求为:
TACLS tCLS,最小值为0ns
TWRPH0tWP,最小值为25ns
TWRPH1tCLH,最小值为10ns
内核的频率为200MHZ,即FCLK=200MHZ,则HCLK=100MHZ(周期为10ns)
TACLS=0,TWRPH0=2,TWRPH1=0即可满足时序要求,此时
TACLS:10nsTWRPH0:30nsTWRPH1:10ns
现在再看看先前串口输出的信息:
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing:Tacls 10ns, Twrph0 10ns, Twrph1 10ns
No NAND device found!!!
很显然Twrph0 10ns <25ns,原来如此!!!!
不过我试了一下TACLS=0,TWRPH0=1,TWRPH1=0, TACLS:10nsTWRPH0:20nsTWRPH1:10ns,NAND Flash照样正常工作.不知道为什么.
现在要说明一下我是如何修改的, TACLSTWRPH0TWRPH1的值在linux-2.6.14\arch\arm\mach-s3c2410\devs.c中已经设置,代码如下:
struct s3c2410_platform_nandsuperlpplatform={
tacls:0,
twrph0:3,
twrph1:0,
sets:&nandset,
nr_sets:1,
};
这里设置的值和上面的分析是一致的,应该没有问题,但是为什么打印出来的却是
s3c2410-nand: timing:Tacls 10ns, Twrph0 10ns, Twrph1 10ns
s3c2410_nand_inithw函数对NFCONF寄存器初始化,代码如下:
static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
struct device *dev)
{
struct s3c2410_platform_nand *plat = to_nand_plat(dev);
unsigned int tacls, twrph0, twrph1;
unsigned long clkrate = clk_get_rate(info->clk);
unsigned long cfg;
/* calculate the timing information for the controller */
if (plat != NULL) {
tacls= s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
printk("plat->tacls:%d\n",plat->tacls);
printk("plat->twrph0:%d\n",plat->twrph0);
printk("plat->twrph1:%d\n",plat->twrph1);
printk("tacls:%d\n",tacls);
printk("twrph0:%d\n",twrph0);
printk("twrph1:%d\n",twrph1);
printk("clkrate:%d\n",clkrate);
tacls=1;
twrph0 =2;
twrph1 =1;
} else {
/* default timings */
tacls = 4;
twrph0 = 8;
twrph1 = 8;
}
if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
printk(KERN_ERR PFX "cannot get timings suitable for board\n");
return -EINVAL;
}
printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n",
to_ns(tacls, clkrate),
to_ns(twrph0, clkrate),
to_ns(twrph1, clkrate));
if (!info->is_s3c2440) {
cfg= S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls-1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);
} else {
cfg= S3C2440_NFCONF_TACLS(tacls-1);
cfg|= S3C2440_NFCONF_TWRPH0(twrph0-1);
cfg|= S3C2440_NFCONF_TWRPH1(twrph1-1);
}
pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
writel(cfg, info->regs + S3C2410_NFCONF);
return 0;
}
我加了一点代码将相关参数打印出来:
plat->tacls:0
plat->twrph0:3
plat->twrph1:0
tacls:1
twrph0:1
twrph1:1
clkrate:100000000
真是搞不懂plat->tacls, plat->twrph0, plat->twrph1的值和前面初始化的值是一样的,但是经过s3c2410_nand_calc_rate函数处理后就出问题了,正确的输出值应该是
tacls:1twrph0:4twrph1:1
算了,对tacls,twrph0,twrph1三个变量强制性赋值
tacls=1;
twrph0 =2;
twrph1 =1;
修改后NAND Flash可以正常工作了,启动信息如下:
Linux version 2.6.14 (root@localhost.localdomain) (gcc version 3.4.1) #7 Mon Jul 14 09:34:58 EDT 2008
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Da
CPU S3C2410A (id 0x32410002)
S3C2410: core 200.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
S3C2410 Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 mem=64M
irq: clearing subpending status 00000003
irq: clearing subpending status 00000002
PID hash table entries: 512 (order: 9, 8192 bytes)
timer tcon=00500000, tcnt a2c1, tcfg 00000200,00000000, usec 00001eb8
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB = 64MB total
Memory: 62592KB available (1708K co
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
NET: Registered protocol family 16
S3C2410: Initialising architecture
usbcore: registered new driver usbfs
usbcore: registered new driver hub
S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics
DMA channel 0 at c4800000, irq 33
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
NetWinder Floating Point Emulator V0.97 (double precision)
Console: switching to colour frame buffer device 80x25
fb0: Virtual frame buffer device, using 1024K of video memory
S3C2410 RTC, (c) 2004 Simtec Electronics
s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing: Tacls 10ns, Twrph0 20ns, Twrph1 10ns
s3c2410-nand: NF_CONF is 0x8010
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
NAND_ECC_NONE selected by board driver. This is not recommended !!
Scanning device for bad blocks
Creating 5 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00020000 : "bootloader"
0x00020000-0x00030000 : "param"
0x00030000-0x001f0000 : "kernel"
0x00200000-0x02200000 : "rootfs"
0x02200000-0x04000000 : "user"
usbmon: debugfs is not available
mice: PS/2 mouse device common for all mice
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
Reading da
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 92K
Warning: unable to open an initial console.
Reading da
sd_mod: version magic 2.6.8.1-ptx1 ARMv4 gcc-3.3 should be 2.6.14 ARMv4 gcc-3.4
usb_storage: version magic 2.6.8.1-ptx1 ARMv4 gcc-3.3 should be 2.6.14 ARMv4 gcc-3.4
usbvideo: version magic 2.6.8.1-ptx1 ARMv4 gcc-3.3 should be 2.6.14 ARMv4 gcc-3.4
ov511: version magic 2.6.8.1-ptx1 ARMv4 gcc-3.3 should be 2.6.14 ARMv4 gcc-3.4