TE2410移植linux-2.6.14及調(diào)試過程總結(jié)(1)
#cd linux-2.6.14
本文引用地址:http://butianyuan.cn/article/201611/317262.htm#vi Makefile
修改內(nèi)容如下
ARCH =arm
CROSS_COMPILE = arm-linux-
下載交叉編譯器arm-linux-gcc3.4.1
http://www.handhelds.org/download/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2
解壓后,把交叉編譯工具鏈的路徑添加到環(huán)境變量中(修改/etc/bashrc文件)
2.設(shè)置Nand Flash分區(qū)
修改linux-2.6.14archarmmach-s3c2410devs.c
(1)添加下列頭文件
#include
#include
#include
(2)添加NandFlash分區(qū)表
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:代表分區(qū)名字
size:代表flash分區(qū)大小(單位:字節(jié))
offset:代表flash分區(qū)的起始地址(相對于0x0的偏移)
(3)加入Nand Flash分區(qū)
structs3c2410_nand_setnandset={
nr_partitions:4,//5,
partitions:partition_info,
};
nr_partitions:指明partition_info中定義的分區(qū)數(shù)目
partitions:分區(qū)信息表
(4)建立Nand Flash芯片支持
struct s3c2410_platform_nandsuperlpplatform={
tacls:0,
twrph0:30,
twrph1:0,
sets:&nandset,
nr_sets:1,
};
tacls, twrph0, twrph1的意思見S3C2410手冊的63,
這3個(gè)值最后會被設(shè)置到NFCONF中,見S3C2410手冊66.
sets:支持的分區(qū)集
nr_sets:分區(qū)集的個(gè)數(shù)
(5)加入Nand Flash芯片支持到Nand Flash驅(qū)動
另外,還要修改此文件中的s3c_device_nand結(jié)構(gòu)體變量,添加對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:設(shè)備名稱
id:有效設(shè)備編號,如果只有唯一的一個(gè)設(shè)備為1,
有多個(gè)設(shè)備從0開始計(jì)數(shù).
num_resource:有幾個(gè)寄存器區(qū)
resource:寄存器區(qū)數(shù)組首地址
dev:支持的Nand Flash設(shè)備
修改linux-2.6.14archarmmach-s3c2410mach-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校驗(yàn)
內(nèi)核都是通過UBOOT寫到Nand Flash的, UBOOT通過的軟件ECC算法產(chǎn)生ECC校驗(yàn)碼,這與內(nèi)核校驗(yàn)的ECC碼不一樣,內(nèi)核中的ECC碼是由S3C2410中Nand Flash控制器產(chǎn)生的.所以,我們在這里選擇禁止內(nèi)核ECC校驗(yàn).
修改linux-2.6.14driversmtdnands3c2410.c
找到函數(shù)s3c2410_nand_init_chip
最后一條語句chip->eccmode= NAND_ECC_SOFT;
改為chip->eccmode= NAND_ECC_NONE;
3.配置內(nèi)核選項(xiàng)
參考smdk2410開發(fā)板的配置文件,將其默認(rèn)的配置文件復(fù)制到內(nèi)核代碼的根目錄下,然后開始配置內(nèi)核
#cd linux-2.6.14
#cp arch/arm/configs/smdk2410_defconfig.config
#make menuconfig
注意:在每個(gè)選項(xiàng)前有個(gè)方括號,其中[*]/<*>表示該選項(xiàng)加入內(nèi)核編譯;[ ]/<>表示不選擇該選項(xiàng);
Loadable module support ->
[*]Enable loadable module support #該選項(xiàng)的目的是使內(nèi)核支持可加載模塊,需要使用modprobe lsmod modinfo insmod rmmod等工具,所以必須選擇;
[*]Module unloading #卸載模塊選項(xiàng)
[*]Force module unloading#強(qiáng)制性卸載模塊選項(xiàng),如用rmmod –f命令強(qiáng)制卸載;
[ ]Module versioning support
[ ]Source checksum for all modules
[*]Automatic kernel module loading#內(nèi)核在任務(wù)中要使用一些被編譯為模塊的驅(qū)動或特性時(shí),先使用modprobe命令來加載它,然后該選項(xiàng)自動調(diào)用modprobe加載需要的模塊,所以該選項(xiàng)一定要選擇.
加入內(nèi)核對S3C2410 DMA(Direct Memory Access)的支持,配置如下:
System Type ->
[*]S3C2410 DMA support
修改命令行參數(shù)
Boot options ->
Default kernel command string
修改后內(nèi)容如下:
noinitrd root=/dev/mtdblock3init=/linuxrc console=ttySAC0,115200 mem=64M
或者
noinitrd root=/dev/mtdblock/3init=/linuxrc console=ttySAC0,115200 mem=64M
mtdblock3表示使用Flash的第4個(gè)分區(qū)(就是rootfs分區(qū)),console=ttySAC0表示kernel啟動期間的信息全部輸出到串口0上,115200表示波特率為115200,
mem=64M表示內(nèi)存大小為64MB
添加對浮點(diǎn)算法的支持
Floating point emulation ->
[*]NWFPE math emulation#支持NWFPE浮點(diǎn)數(shù),在許多情況下要使用,所以最好選上
對MTD(Memory Technology Devices)設(shè)備(如Flash RAM等芯片)進(jìn)行配置,選擇配置如下
Device Drivers->
Memory Technology Devices(MTD)->
[*]MTD partitioning support
Device Drivers->
Memory Technology Devices(MTD)->
RAM/ROM/Flash chip drivers->
<*>Detect flash chips by Common Flash Interface(CFI)probe
<*>Detect non-CFI AMD/JEDEC-compatible flash chips
<*>Support for Intel/Sharp flash chips
<*>Support for AMD/Fujitsu flash chips
<*>Support for ROM chips in bus mapping
Device Drivers->
Memory Technology Devices(MTD)->
NAND Flash Device Drivers->
<*>NAND Device Support
<*>NAND Flash support for S3C2410/S3C2440 SoC
為了要內(nèi)核支持devfs(Device Filesystem,設(shè)備文件系統(tǒng)),以及在啟動時(shí)能自動加載/dev為devfs,需要對文件系統(tǒng)進(jìn)行設(shè)置。
File systems ->
< >Second extended fs support#去除對ext2的支持
Linux2.6.14 fs/Kconfig沒有支持devfs的選項(xiàng)(從2.6.13開始),所以make menuconfig時(shí)找不到相關(guān)菜單項(xiàng)
從2.6.10的fs/Kconfig中copy幾項(xiàng)過來
config DEVFS_FS
bool "/dev file system support (OBSOLETE)"
depends on EXPERIMENTAL
help
This is support for devfs, a virtual file system (like /proc) which
provides the file system interface to device drivers, normally found
in /dev. Devfs does not depend on major and minor number
allocations. Device drivers register entries in /dev which then
appear automatically, which means that the system administrator does
not have to create character and block special device files in the
/dev directory using the mknod command (or MAKEDEV script) anymore.
This is work in progress. If you want to use this, you *must* read
the material in
the file README there.
Note that devfs no longer manages /dev/pts!If you are using UNIX98
ptys, you will also need to mount the /dev/pts filesystem (devpts).
Note that devfs has been obsoleted by udev,
It has been stripped down to a bare minimum and is on
legacy installations that use its naming scheme which is
unfortunately different from the names normal Linux installations
use.
If unsure, say N.
config DEVFS_MOUNT
bool "Automatically mount at boot"
depends on DEVFS_FS
help
This option appears if you have CONFIG_DEVFS_FS enabled. Setting
this to Y will make the kernel automatically mount devfs on
when the system is booted, before the init thread is started.
You can override this with the "devfs=nomount" boot option.
If unsure, say N.
config DEVFS_DEBUG
bool "Debug devfs"
depends on DEVFS_FS
help
If you say Y here, then the /dev file system co
debugging messages. See the file
details.
If unsure, say N.
File systems ->
Pseudo filesystems ->
[*]/proc file system support
[*]/dev file system support(OBSOLETE)
[*]Automatically mount at boot
[*]Virtual memory file system support(former shm fs)
Miscellaneous filesystems ->
<*>Compressed ROM file system support(cramfs)
Network File Systems ->
<*>NFS file system support
除此之外,還需要配置一下選項(xiàng)支持S3C2410 RTC,USB,MMC/SD卡驅(qū)動,具體選項(xiàng)如下:
Device Drivers->
Character devices->
[*]Nonstandard serial port support
[*]S3C2410 RTC Driver
Device Drivers->
USB Support->
<*>Support for Host-side USB
Device Drivers->
MMC/SD Card Support
<*>MMC Support
<*>MMC block device driver
調(diào)試過程中出現(xiàn)的問題及解決辦法
1.Starting kernel ...就打住了
應(yīng)該是從u-boot跳轉(zhuǎn)至內(nèi)核的地址不正確,我下載的加了0x40字節(jié)頭信息的內(nèi)核鏡像,下載到0x30008000,正確的跳轉(zhuǎn)地址應(yīng)該是0x30008040,在
u-boot-1.1.3lib_armarmlinux.c的do_bootm_linux函數(shù)代碼如下:
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],ulong addr, ulong *len_ptr, int verify)
{
DECLARE_GLOBAL_DA
ulong len = 0, checksum;
ulong initrd_start, initrd_end;
ulong da
void (*theKernel)(int zero, int arch, uint params);
image_header_t *hdr = &header;
bd_t *bd = gd->bd;
. . .
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
. . .
/* we assume that the kernel is in place */
printf ("nStarting kernel ...nn");
#ifdef CONFIG_USB_DEVICE
{
extern void udc_disconnect (void);
udc_disconnect ();
}
#endif
cleanup_before_linux ();
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
}
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
typedef struct image_header {
uint32_tih_magic;/* Image Header Magic Number*/
uint32_tih_hcrc;/* Image Header CRC Checksum*/
uint32_tih_time;/* Image Creation Timestamp*/
uint32_tih_size;/* Image Da
uint32_tih_load;/* Da
uint32_tih_ep;/* Entry Point Address*/
uint32_tih_dcrc;/* Image Da
uint8_tih_os;/* Operating System*/
uint8_tih_arch;/* CPU architecture*/
uint8_tih_type;/* Image Type*/
uint8_tih_comp;/* Compression Type*/
uint8_tih_name[IH_NMLEN];/* Image Name*/
} image_header_t;
可以看出跳轉(zhuǎn)地址是由image_header結(jié)構(gòu)體的ih_ep(Entry Point Address)成員來確定的,而ih_ep是由mkimage時(shí)自己填寫的,如下是我填充的mkimage參數(shù),其中的
-e 0x30008000就是來填充ih_ep成員的.
mkimage -A arm -O Linux -T kernel -C none -a 0x30008000-e 0x30008000-n Linux-2.6.14 -d zImage uImage
顯然這個(gè)值應(yīng)該是0x30008040
mkimage -A arm -O Linux -T kernel -C none -a 0x30008000-e 0x30008040-n Linux-2.6.14 -d zImage uImage
修改后啟動信息如下
## Booting image at 30008000 ...
Image Name:Linux-2.6.14
Created:2008-07-148:59:37 UTC
Image Type:ARM Linux Kernel Image (uncompressed)
Da
Load Address: 30008000
Entry Point:30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
commandline:noinitrd root=/dev/mtdblock3 init=/linuxrc console= ttySAC0,115200 mem=64M
Starting kernel ...
Uncompressing Linux.................................................................... done, booting the kernel.
2.Starting kernel ...
Uncompressing Linux............................................................
......... done, booting the kernel.
Error: unrecognized/unsupported machine ID (r1 = 0x000000c2).
Available machine support:
ID (hex)NAME
000000c1SMDK2410
Please check your kernel config and/or bootloader.
修改linux-2.6.14archarmkernelhead.S,如下,藍(lán)色字體為添加內(nèi)容
ENTRY(stext)
msrcpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
@ and irqs disabled
bl__lookup_processor_type@ r5=procinfo r9=cpuid
movsr10, r5@ invalid processor (r5=0)?
beq__error_p@ yes, error p
movr1, #0xc1@參考linux-2.6.14includeasm-armmach-types.h
bl__lookup_machine_type@ r5=machinfo
movsr8, r5@ invalid machine (r5=0)?
beq__error_a@ yes, error a
3.Starting kernel ...
Uncompressing Linux.................................................
......... done, booting the kernel.
然后就停止了
查看commandline完全正確,從上面的打印信息可以看出,內(nèi)核已經(jīng)解壓成功了,這樣只能進(jìn)入內(nèi)核跟蹤調(diào)試了
在內(nèi)核中arch/arm/kernel/debug.S中存在一個(gè)debug函數(shù)叫做printascii,使用方法如下:
adr r0, str_p1
bl printascii
str_p1:.asciz"nError: unrecognized/unsupported process typen"
用printascii在arch/arm/kernel/head.S里跟蹤調(diào)試,直到跳轉(zhuǎn)到start_kernel都沒有發(fā)現(xiàn)問題,查到printascii在進(jìn)入start_kernel之后也可以使用,說明如下:
mmu已經(jīng)開啟后,系統(tǒng)中的物理地址都變成虛擬地址了,因此原來基于物理地址的調(diào)試方案將都會失敗,但可以使用printascii繼續(xù)調(diào)試,該調(diào)試功能同時(shí)支持物理地址與虛擬地址,并且提供了一個(gè)解決方案就是將printascii加入到printk的vsprintf()之里。
修改linux-2.6.14kernelprintk.c,藍(lán)色字體為添加內(nèi)容
extern void printascii(const char*);
asmlinkage int vprintk(const char *fmt, va_list args)
{
unsigned long flags;
int printed_len;
char *p;
static char printk_buf[1024];
static int log_level_unknown = 1;
preempt_disable();
if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
zap_locks();
spin_lock_irqsave(&logbuf_lock, flags);
printk_cpu = smp_processor_id();
/* Emit the output into the temporary buffer */
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
printascii(printk_buf);
...
...
}
修改后內(nèi)核啟動成功,超級終端出來一大堆打印信息
## Booting image at 30008000 ...
Image Name:Linux-2.6.14
Created:2008-07-148:59:37 UTC
Image Type:ARM Linux Kernel Image (uncompressed)
Da
Load Address: 30008000
Entry Point:30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
Starting kernel ...
Uncompressing Linux.................................................................... done, booting the kernel.
<5>Linux version 2.6.14 (root@localhost.localdomain) (gcc version 3.4.1) #3 Mon Jul 14 04:59:17 EDT 2008
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Da
CPU S3C2410A (id 0x32410002)
S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
<6>S3C2410 Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
<7>On node 0 totalpages: 16384
<7>DMA zone: 16384 pages, LIFO batch:7
<7>Normal zone: 0 pages, LIFO batch:1
<7>HighMem zone: 0 pages, LIFO batch:1
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
<5>Kernel command line: noinitrd root=/dev/mtdblock3 init=/linuxrcconsole= ttySAC0,115200 mem=64M
irq: clearing subpending status 00000003
PID hash table entries: 512 (order: 9, 8192 bytes)
timer tcon=00500000, tcnt a509, tcfg 00000200,00000000, usec 00001e4c
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)
<6>Memory: 64MB = 64MB total
<5>Memory: 62592KB available (1708K co
<7>Calibrating delay loop... 101.17 BogoMIPS (lpj=252928)
Mount-cache hash table entries: 512
<6>CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
<6>NET: Registered protocol family 16
S3C2410: Initialising architecture
<6>usbcore: registered new driver usbfs
<6>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
<4>NetWinder Floating Point Emulator V0.97 (double precision)
Console: switching to colour frame buffer device 80x25
<6>fb0: Virtual frame buffer device, using 1024K of video memory
S3C2410 RTC, (c) 2004 Simtec Electronics
<6>s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
<6>s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
<6>s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
<6>io scheduler noop registered
<6>io scheduler anticipatory registered
<6>io scheduler deadline registered
<6>io scheduler cfq registered
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
<6>s3c2410-nand: mapped registers at c4980000
<6>s3c2410-nand: timing: Tacls10ns, Twrph010ns, Twrph110ns
<4>No NAND device found!!!
<5>usbmon: debugfs is not available
<6>mice: PS/2 mouse device common for all mice
<6>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)
<6>TCP: Hash tables configured (established 4096 bind 4096)
<6>TCP reno registered
<6>TCP bic registered
<6>NET: Registered protocol family 1
<3>Root-NFS: No NFS server available, giving up.
<3>VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "mtdblock3" or unknown-block(2,0)
Please append a correct "root=" boot option
<0>Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
那么就說明內(nèi)核沒有問題,而是commandline參數(shù)有問題,仔細(xì)看,才發(fā)現(xiàn)
noinitrd root=/dev/mtdblock3 init=/linuxrcconsole= ttySAC0,115200 mem=
64M
console=之后多了一個(gè)空格,但是不確定是否是這個(gè)原因,重新設(shè)置bootargs參數(shù),去掉空格
setenv bootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttyS
AC0,115200 mem=64M
重新下載,啟動成功.
在網(wǎng)上查到有說u-boot和內(nèi)核頻率不一致可能導(dǎo)致串口沒有打印信息,最好將u-boot的頻率設(shè)為200M,不過我試過了,202.800 MHz也沒有問題
Uncompressing Linux............................................................ done, booting the kernel.
Linux version 2.6.14 (root@localhost.localdomain) (gcc version 3.4.1) #3 Mon Jul 14 04:59:17 EDT 2008
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Da
CPU S3C2410A (id 0x32410002)
S3C2410: core202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
Starting kernel ...
Uncompressing Linux................................................................... done, booting the kernel.
Linux version 2.6.14 (root@localhost.localdomain) (gcc version 3.4.1) #20 Sat Jul 5 10:01:30 EDT 2008
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Da
CPU S3C2410A (id 0x32410002)
S3C2410: core200.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
1.S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing: Tacls 10ns, Twrph0 10ns, Twrph1 10ns
No NAND device found!!!
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
Root-NFS: No NFS server available, giving up.
VFS: Unable to mount root fs via NFS, trying floppy.
VFS:Cannot open root device "mtdblock3" or unknown-block(2,0)
Please append a correct "root=" boot option
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
原因可能是一下幾點(diǎn):
(1)commandline中的root=/dev/mtdblock3表示rootfs在Flash的第4分區(qū),檢查確認(rèn)rootfs是否是Flash的第4分區(qū)(第一個(gè)分區(qū)號為0)
(2)Flash的rootfs分區(qū)中沒有下載好的根文件系統(tǒng),確認(rèn)是否下載好根文件系統(tǒng)
(3)Flash的驅(qū)動有問題,無法對Flash進(jìn)行讀寫
我的NAND Flash分區(qū)如下:
mtdpart info. (5 partitions)
nameoffsetsizeflag
------------------------------------------------
vivi: 0x000000000x000200000128k
param: 0x000200000x00010000064k
kernel: 0x000300000x001c000001M+768k
rootfs: 0x002000000x02000000032M
user: 0x022000000x01e00000030M
所以commandline中的mtdblock3沒有錯(cuò)誤
我已下載好根文件系統(tǒng)至rootfs分區(qū),再看看串口的打印信息,注意紅色的部分
No NAND device found!!!
有點(diǎn)奇怪,其實(shí)我不太相信linux的源代碼會有問題,就在根文件系統(tǒng)的加載這一步拖了好多天,一開始由于自己的疏忽,make menuconfig時(shí)把有些選項(xiàng)選成模塊了,也沒有搞清楚<*>和
linux-2.6.14driversmtdnands3c2410.c中s3c2410_nand_init函數(shù)對NAND Flash初始化
static int __init s3c2410_nand_init(void)
{
printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronicsn");
driver_register(&s3c2440_nand_driver);
returndriver_register(&s3c2410_nand_driver);
}
static struct device_drivers3c2410_nand_driver= {
.name= "s3c2410-nand",
.bus= &platform_bus_type,
.probe=s3c2410_nand_probe,
.remove= s3c2410_nand_remove,
};
static ints3c2410_nand_probe(struct device *dev)
{
returns3c24xx_nand_probe(dev, 0);
}
static ints3c24xx_nand_probe(struct device *dev, int is_s3c2440)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c2410_platform_nand *plat = to_nand_plat(dev);
struct s3c2410_nand_info *info;
struct s3c2410_nand_mtd *nmtd;
struct s3c2410_nand_set *sets;
struct resource *res;
. . .
for (setno = 0; setno < nr_sets; setno++, nmtd++) {
pr_debug("initialising set %d (%p, info %p)n",
setno, nmtd, info);
s3c2410_nand_init_chip(info, nmtd, sets);
nmtd->scan_res =nand_scan(&nmtd->mtd,
(sets) ? sets->nr_chips : 1);
if (nmtd->scan_res == 0) {
s3c2410_nand_add_partition(info, nmtd, sets);
}
if (sets != NULL)
sets++;
}
. . .
}
經(jīng)過串口打印出nmtd->scan_res的值為1,根據(jù)
if (nmtd->scan_res == 0) {
s3c2410_nand_add_partition(info, nmtd, sets);
}
來判斷,應(yīng)該返回0.
進(jìn)入nand_scan
int nand_scan (struct mtd_info *mtd, int maxchips)
{
int i, nand_maf_id, nand_dev_id, busw, maf_id;
struct nand_chip *this = mtd->priv;
. . .
/* Select the device */
this->select_chip(mtd, 0);
/* Send the command for reading device ID */
this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
nand_maf_id= this->read_byte(mtd);
nand_dev_id= this->read_byte(mtd);
. . .
/* Print and store flash device information */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (nand_dev_id != nand_flash_ids[i].id)
continue;
if (!mtd->name) mtd->name = nand_flash_ids[i].name;
this->chipsize = nand_flash_ids[i].chipsize << 20;
. . .
/* Try to identify manufacturer */
for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) {
if (nand_manuf_ids[maf_id].id == nand_maf_id)
break;
}
. . .
printk (KERN_INFO "NAND device: Manufacturer ID:"
" 0x%02x, Chip ID: 0x%02x (%s %s)n", nand_maf_id, nand_dev_id,
nand_manuf_ids[maf_id].name , nand_flash_ids[i].name);
break;
}
if (!nand_flash_ids[i].name) {
printk (KERN_WARNING "No NAND device found!!!n");
this->select_chip(mtd, -1);
return 1;
}
. . .
}
根據(jù)上面的代碼可以看出沒有在nand_flash_ids數(shù)組中找到nand_dev_id匹配值,記得在u-boot中也有nand_probe函數(shù)檢測NAND Flash,打印出2個(gè)ID值如下
NAND:Flash chip found:Manufacturer ID:0xEC, Chip ID:0x76
Linux中nand_flash_ids和nand_manuf_ids數(shù)組內(nèi)容如下:
/*
*Chip ID list*
*Name. ID co
*/
struct nand_flash_dev nand_flash_ids[] = {
{"NAND 1MiB 5V 8-bit",0x6e, 256, 1, 0x1000, 0},
{"NAND 2MiB 5V 8-bit",0x64, 256, 2, 0x1000, 0},
{"NAND 4MiB 5V 8-bit",0x6b, 512, 4, 0x2000, 0},
{"NAND 1MiB 3,3V 8-bit",0xe8, 256, 1, 0x1000, 0},
{"NAND 1MiB 3,3V 8-bit",0xec, 256, 1, 0x1000, 0},
{"NAND 2MiB 3,3V 8-bit",0xea, 256, 2, 0x1000, 0},
{"NAND 4MiB 3,3V 8-bit",0xd5, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit",0xe3, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit",0xe5, 512, 4, 0x2000, 0},
. . .
{"NAND 64MiB 3,3V 8-bit",0x76, 512, 64, 0x4000, 0},
. . .
{NULL,}
};
/*
*Manufacturer ID list
*/
struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_TOSHIBA, "Toshiba"},
{NAND_MFR_SAMSUNG, "Samsung"},
{NAND_MFR_FUJITSU, "Fujitsu"},
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix"},
{0x0, "Unknown"}
};
/*
* NAND Flash Manufacturer ID Codes
*/
#define NAND_MFR_TOSHIBA0x98
#defineNAND_MFR_SAMSUNG0xec
#define NAND_MFR_FUJITSU0x04
#define NAND_MFR_NATIONAL0x8f
#define NAND_MFR_RENESAS0x07
#define NAND_MFR_STMICRO0x20
#define NAND_MFR_HYNIX0xad
這樣就說明nand_scan中讀取NAND Flash的id值是錯(cuò)誤的,不是0xec和0x76,從串口打印出來的id值確實(shí)不正確,首先我的NAND Flash肯定正常工作,在u-boot中一直是好的,那么可能是Linux中對Flash讀寫的出問題了,懷疑是發(fā)出命令后的延時(shí)有問題,向NAND Flash發(fā)出讀取id命令后的延時(shí)太短,導(dǎo)致讀出來的值錯(cuò)誤,nand_wait_ready這個(gè)就是延時(shí)等待命令執(zhí)行完成的函數(shù),經(jīng)過測試沒有問題,到這個(gè)時(shí)候,真有點(diǎn)崩潰了.然后估計(jì)是NAND Flash的NFCONF寄存器設(shè)置有問題, NFCONF寄存器在函數(shù)s3c2410_nand_inithw中初始化,s3c2410_nand_inithw中將NFCONF寄存器的值打印出來,如下:
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing:Tacls10ns, Twrph010ns, Twrph110ns
s3c2410-nand: NF_CONF is0x8000
與u-boot中設(shè)置的NFCONF寄存器值比較發(fā)現(xiàn),不同的是TACLS TWRPH0 TWRPH1以及是否初始化ECC,nFCE的值
U-boot中TACLS TWRPH0 TWRPH1值分別為0 4 2,初始化ECC, nFCE=1(inactive)
Linux中TACLS TWRPH0 TWRPH1值分別為0 0 0,未初始化ECC, nFCE=0(active)
應(yīng)該是TACLS TWRPH0 TWRPH1的問題,查看S3C2410 user manual和NAND Flash用戶手冊Samsung K9F1208U0M user manual,找到三張圖,如下:
圖1 s3c2410 user manual, nand flash memory timing
顯然s3c2410 user manual推薦值是TACLS=0 TWRPH0=1 TWRPH1=0
TACLS:1個(gè)HCLK TWRPH0:2個(gè)HCLK TWRPH1:1個(gè)HCLK
內(nèi)核的頻率為200MHZ,即FCLK=200MHZ,則HCLK=100MHZ(周期為10ns),所以
TACLS:10ns TWRPH0:20ns TWRPH1:10ns
圖2 NAND Flash(K9F1208U0M) user manual,Read and Write timing
tCLS等價(jià)于圖1中的TACLS;tWP等價(jià)于圖1中的TWRPH0;tCLH等價(jià)于圖1中的TWRPH1
圖3 NAND Flash(K9F1208U0M) user manual
結(jié)合前3張圖,可以看出對NAND Flash(K9F1208U0M)進(jìn)行讀寫的順序要求為:
TACLS <----------->tCLS,最小值為0ns
TWRPH0<----------->tWP,最小值為25ns
TWRPH1<----------->tCLH,最小值為10ns
內(nèi)核的頻率為200MHZ,即FCLK=200MHZ,則HCLK=100MHZ(周期為10ns)
TACLS=0,TWRPH0=2,TWRPH1=0即可滿足時(shí)序要求,此時(shí)
TACLS:10nsTWRPH0:30nsTWRPH1:10ns
現(xiàn)在再看看先前串口輸出的信息:
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照樣正常工作.不知道為什么.
現(xiàn)在要說明一下我是如何修改的, TACLSTWRPH0TWRPH1的值在linux-2.6.14archarmmach-s3c2410devs.c中已經(jīng)設(shè)置,代碼如下:
struct s3c2410_platform_nandsuperlpplatform={
tacls:0,
twrph0:3,
twrph1:0,
sets:&nandset,
nr_sets:1,
};
這里設(shè)置的值和上面的分析是一致的,應(yīng)該沒有問題,但是為什么打印出來的卻是
s3c2410-nand: timing:Tacls 10ns, Twrph0 10ns, Twrph1 10ns
s3c2410_nand_inithw函數(shù)對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:%dn",plat->tacls);
printk("plat->twrph0:%dn",plat->twrph0);
printk("plat->twrph1:%dn",plat->twrph1);
printk("tacls:%dn",tacls);
printk("twrph0:%dn",twrph0);
printk("twrph1:%dn",twrph1);
printk("clkrate:%dn",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 boardn");
return -EINVAL;
}
printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldnsn",
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%lxn", cfg);
writel(cfg, info->regs + S3C2410_NFCONF);
return 0;
}
我加了一點(diǎn)代碼將相關(guān)參數(shù)打印出來:
plat->tacls:0
plat->twrph0:3
plat->twrph1:0
tacls:1
twrph0:1
twrph1:1
clkrate:100000000
真是搞不懂plat->tacls, plat->twrph0, plat->twrph1的值和前面初始化的值是一樣的,但是經(jīng)過s3c2410_nand_calc_rate函數(shù)處理后就出問題了,正確的輸出值應(yīng)該是
tacls:1twrph0:4twrph1:1
算了,對tacls,twrph0,twrph1三個(gè)變量強(qiáng)制性賦值
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
評論