新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > TE2410移植linux-2.6.14及調(diào)試過程總結(jié)(1)

TE2410移植linux-2.6.14及調(diào)試過程總結(jié)(1)

作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
1.修改Makefile

#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ū)的起始地址(相對(duì)于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手冊(cè)的63,
這3個(gè)值最后會(huì)被設(shè)置到NFCONF中,見S3C2410手冊(cè)66.
sets:支持的分區(qū)集
nr_sets:分區(qū)集的個(gè)數(shù)

(5)加入Nand Flash芯片支持到Nand Flash驅(qū)動(dòng)
另外,還要修改此文件中的s3c_device_nand結(jié)構(gòu)體變量,添加對(duì)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_data =&superlpplatform

}

};

name:設(shè)備名稱
id:有效設(shè)備編號(hào),如果只有唯一的一個(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)生的.所以,我們?cè)谶@里選擇禁止內(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è)方括號(hào),其中[*]/<*>表示該選項(xiàng)加入內(nèi)核編譯;[ ]/<>表示不選擇該選項(xiàng);表示該選項(xiàng)作為模塊編譯,也就是說可以動(dòng)態(tài)的加載和卸載該模塊.

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ū)動(dòng)或特性時(shí),先使用modprobe命令來加載它,然后該選項(xiàng)自動(dòng)調(diào)用modprobe加載需要的模塊,所以該選項(xiàng)一定要選擇.

加入內(nèi)核對(duì)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啟動(dòng)期間的信息全部輸出到串口0上,115200表示波特率為115200,

mem=64M表示內(nèi)存大小為64MB

添加對(duì)浮點(diǎn)算法的支持

Floating point emulation ->

[*]NWFPE math emulation#支持NWFPE浮點(diǎn)數(shù),在許多情況下要使用,所以最好選上

對(duì)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)),以及在啟動(dòng)時(shí)能自動(dòng)加載/dev為devfs,需要對(duì)文件系統(tǒng)進(jìn)行設(shè)置。

File systems ->

< >Second extended fs support#去除對(duì)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 , especially

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 only provided for

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 onto /dev

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 code will generate

debugging messages. See the file

for more

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ū)動(dòng),具體選項(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_DATA_PTR;

ulong len = 0, checksum;

ulong initrd_start, initrd_end;

ulong data;

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 Data Size*/

uint32_tih_load;/* DataLoadAddress*/

uint32_tih_ep;/* Entry Point Address*/

uint32_tih_dcrc;/* Image Data CRC Checksum*/

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

修改后啟動(dòng)信息如下

## Booting image at 30008000 ...

Image Name:Linux-2.6.14

Created:2008-07-148:59:37 UTC

Image Type:ARM Linux Kernel Image (uncompressed)

Data Size:1028136 Bytes = 1004 kB

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)試方案將都會(huì)失敗,但可以使用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)核啟動(dòng)成功,超級(jí)終端出來一大堆打印信息

## Booting image at 30008000 ...

Image Name:Linux-2.6.14

Created:2008-07-148:59:37 UTC

Image Type:ARM Linux Kernel Image (uncompressed)

Data Size:1028136 Bytes = 1004 kB

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, Data cache writeback

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 code, 381K data, 92K init)

<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

重新下載,啟動(dòng)成功.

在網(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, Data cache writeback

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, Data cache writeback

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ū)號(hào)為0)

(2)Flash的rootfs分區(qū)中沒有下載好的根文件系統(tǒng),確認(rèn)是否下載好根文件系統(tǒng)

(3)Flash的驅(qū)動(dòng)有問題,無法對(duì)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的源代碼會(huì)有問題,就在根文件系統(tǒng)的加載這一步拖了好多天,一開始由于自己的疏忽,make menuconfig時(shí)把有些選項(xiàng)選成模塊了,也沒有搞清楚<*>和的差別,串口打印信息也是到這一步,但是沒有No NAND device found!!!提示,因?yàn)镹AND Flash的驅(qū)動(dòng)沒有編譯進(jìn)內(nèi)核.后來才發(fā)現(xiàn)make menuconfig配置時(shí)出了問題,修改后,發(fā)現(xiàn)是NAND Flash驅(qū)動(dòng)有問題,進(jìn)入內(nèi)核跟蹤發(fā)現(xiàn)

linux-2.6.14driversmtdnands3c2410.c中s3c2410_nand_init函數(shù)對(duì)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ù)檢測(cè)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 code, pagesize, chipsize in MegaByte, eraseblock size,

*/

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中對(duì)Flash讀寫的出問題了,懷疑是發(fā)出命令后的延時(shí)有問題,向NAND Flash發(fā)出讀取id命令后的延時(shí)太短,導(dǎo)致讀出來的值錯(cuò)誤,nand_wait_ready這個(gè)就是延時(shí)等待命令執(zhí)行完成的函數(shù),經(jīng)過測(cè)試沒有問題,到這個(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用戶手冊(cè)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張圖,可以看出對(duì)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ù)對(duì)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

算了,對(duì)tacls,twrph0,twrph1三個(gè)變量強(qiáng)制性賦值

tacls=1;

twrph0 =2;

twrph1 =1;

修改后NAND Flash可以正常工作了,啟動(dòng)信息如下:

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, Data cache writeback

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 code, 381K data, 92K init)

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 data from NAND FLASH without ECC is not recommended

VFS: Mounted root (cramfs filesystem) readonly.

Freeing init memory: 92K

Warning: unable to open an initial console.

Reading data from NAND FLASH without ECC is not recommended

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



評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉