新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > TE2410移植linux-2.6.14及調試過程總結(1)

        TE2410移植linux-2.6.14及調試過程總結(1)

        作者: 時間:2016-11-10 來源:網絡 收藏
        1.修改Makefile

        #cd linux-2.6.14

        本文引用地址:http://www.104case.com/article/201611/317262.htm

        #vi Makefile

        修改內容如下

        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

        解壓后,把交叉編譯工具鏈的路徑添加到環境變量中(修改/etc/bashrc文件)

        2.設置Nand Flash分區

        修改linux-2.6.14archarmmach-s3c2410devs.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_data =&superlpplatform

        }

        };

        name:設備名稱
        id:有效設備編號,如果只有唯一的一個設備為1,
        有多個設備從0開始計數.
        num_resource:有幾個寄存器區
        resource:寄存器區數組首地址
        dev:支持的Nand Flash設備

        修改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校驗

        內核都是通過UBOOT寫到Nand Flash的, UBOOT通過的軟件ECC算法產生ECC校驗碼,這與內核校驗的ECC碼不一樣,內核中的ECC碼是由S3C2410中Nand Flash控制器產生的.所以,我們在這里選擇禁止內核ECC校驗.

        修改linux-2.6.14driversmtdnands3c2410.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

        注意:在每個選項前有個方括號,其中[*]/<*>表示該選項加入內核編譯;[ ]/<>表示不選擇該選項;表示該選項作為模塊編譯,也就是說可以動態的加載和卸載該模塊.

        Loadable module support ->

        [*]Enable loadable module support #該選項的目的是使內核支持可加載模塊,需要使用modprobe lsmod modinfo insmod rmmod等工具,所以必須選擇;

        [*]Module unloading #卸載模塊選項

        [*]Force module unloading#強制性卸載模塊選項,如用rmmod –f命令強制卸載;

        [ ]Module versioning support

        [ ]Source checksum for all modules

        [*]Automatic kernel module loading#內核在任務中要使用一些被編譯為模塊的驅動或特性時,先使用modprobe命令來加載它,然后該選項自動調用modprobe加載需要的模塊,所以該選項一定要選擇.

        加入內核對S3C2410 DMA(Direct Memory Access)的支持,配置如下:

        System Type ->

        [*]S3C2410 DMA support

        修改命令行參數

        Boot options ->

        Default kernel command string

        修改后內容如下:

        noinitrd root=/dev/mtdblock3init=/linuxrc console=ttySAC0,115200 mem=64M

        或者

        noinitrd root=/dev/mtdblock/3init=/linuxrc console=ttySAC0,115200 mem=64M

        mtdblock3表示使用Flash的第4個分區(就是rootfs分區),console=ttySAC0表示kernel啟動期間的信息全部輸出到串口0上,115200表示波特率為115200,

        mem=64M表示內存大小為64MB

        添加對浮點算法的支持

        Floating point emulation ->

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

        對MTD(Memory Technology Devices)設備(如Flash RAM等芯片)進行配置,選擇配置如下

        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

        為了要內核支持devfs(Device Filesystem,設備文件系統),以及在啟動時能自動加載/dev為devfs,需要對文件系統進行設置。

        File systems ->

        < >Second extended fs support#去除對ext2的支持

        Linux2.6.14 fs/Kconfig沒有支持devfs的選項(從2.6.13開始),所以make menuconfig時找不到相關菜單項

        從2.6.10的fs/Kconfig中copy幾項過來

        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

        除此之外,還需要配置一下選項支持S3C2410 RTC,USB,MMC/SD卡驅動,具體選項如下:

        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

        調試過程中出現的問題及解決辦法

        1.Starting kernel ...就打住了

        應該是從u-boot跳轉至內核的地址不正確,我下載的加了0x40字節頭信息的內核鏡像,下載到0x30008000,正確的跳轉地址應該是0x30008040,在

        u-boot-1.1.3lib_armarmlinux.c的do_bootm_linux函數代碼如下:

        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;

        可以看出跳轉地址是由image_header結構體的ih_ep(Entry Point Address)成員來確定的,而ih_ep是由mkimage時自己填寫的,如下是我填充的mkimage參數,其中的

        -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

        顯然這個值應該是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)

        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,如下,藍色字體為添加內容

        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完全正確,從上面的打印信息可以看出,內核已經解壓成功了,這樣只能進入內核跟蹤調試了

        在內核中arch/arm/kernel/debug.S中存在一個debug函數叫做printascii,使用方法如下:

        adr r0, str_p1
        bl printascii
        str_p1:.asciz"nError: unrecognized/unsupported process typen"

        用printascii在arch/arm/kernel/head.S里跟蹤調試,直到跳轉到start_kernel都沒有發現問題,查到printascii在進入start_kernel之后也可以使用,說明如下:

        mmu已經開啟后,系統中的物理地址都變成虛擬地址了,因此原來基于物理地址的調試方案將都會失敗,但可以使用printascii繼續調試,該調試功能同時支持物理地址與虛擬地址,并且提供了一個解決方案就是將printascii加入到printk的vsprintf()之里。

        修改linux-2.6.14kernelprintk.c,藍色字體為添加內容

        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);

        ...

        ...

        }

        修改后內核啟動成功,超級終端出來一大堆打印信息

        ## 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)

        那么就說明內核沒有問題,而是commandline參數有問題,仔細看,才發現

        noinitrd root=/dev/mtdblock3 init=/linuxrcconsole= ttySAC0,115200 mem=

        64M

        console=之后多了一個空格,但是不確定是否是這個原因,重新設置bootargs參數,去掉空格

        setenv bootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttyS

        AC0,115200 mem=64M

        重新下載,啟動成功.

        在網上查到有說u-boot和內核頻率不一致可能導致串口沒有打印信息,最好將u-boot的頻率設為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)

        原因可能是一下幾點:

        (1)commandline中的root=/dev/mtdblock3表示rootfs在Flash的第4分區,檢查確認rootfs是否是Flash的第4分區(第一個分區號為0)

        (2)Flash的rootfs分區中沒有下載好的根文件系統,確認是否下載好根文件系統

        (3)Flash的驅動有問題,無法對Flash進行讀寫

        我的NAND Flash分區如下:

        mtdpart info. (5 partitions)

        nameoffsetsizeflag

        ------------------------------------------------

        vivi: 0x000000000x000200000128k

        param: 0x000200000x00010000064k

        kernel: 0x000300000x001c000001M+768k

        rootfs: 0x002000000x02000000032M

        user: 0x022000000x01e00000030M

        所以commandline中的mtdblock3沒有錯誤

        我已下載好根文件系統至rootfs分區,再看看串口的打印信息,注意紅色的部分

        No NAND device found!!!

        有點奇怪,其實我不太相信linux的源代碼會有問題,就在根文件系統的加載這一步拖了好多天,一開始由于自己的疏忽,make menuconfig時把有些選項選成模塊了,也沒有搞清楚<*>和的差別,串口打印信息也是到這一步,但是沒有No NAND device found!!!提示,因為NAND Flash的驅動沒有編譯進內核.后來才發現make menuconfig配置時出了問題,修改后,發現是NAND Flash驅動有問題,進入內核跟蹤發現

        linux-2.6.14driversmtdnands3c2410.c中s3c2410_nand_init函數對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++;

        }

        . . .

        }

        經過串口打印出nmtd->scan_res的值為1,根據

        if (nmtd->scan_res == 0) {

        s3c2410_nand_add_partition(info, nmtd, sets);

        }

        來判斷,應該返回0.

        進入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;

        }

        . . .

        }

        根據上面的代碼可以看出沒有在nand_flash_ids數組中找到nand_dev_id匹配值,記得在u-boot中也有nand_probe函數檢測NAND Flash,打印出2個ID值如下

        NAND:Flash chip found:Manufacturer ID:0xEC, Chip ID:0x76

        Linux中nand_flash_ids和nand_manuf_ids數組內容如下:

        /*

        *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值是錯誤的,不是0xec和0x76,從串口打印出來的id值確實不正確,首先我的NAND Flash肯定正常工作,在u-boot中一直是好的,那么可能是Linux中對Flash讀寫的出問題了,懷疑是發出命令后的延時有問題,向NAND Flash發出讀取id命令后的延時太短,導致讀出來的值錯誤,nand_wait_ready這個就是延時等待命令執行完成的函數,經過測試沒有問題,到這個時候,真有點崩潰了.然后估計是NAND Flash的NFCONF寄存器設置有問題, NFCONF寄存器在函數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中設置的NFCONF寄存器值比較發現,不同的是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)

        應該是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個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

        TWRPH0<----------->tWP,最小值為25ns

        TWRPH1<----------->tCLH,最小值為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.14archarmmach-s3c2410devs.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:%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;

        }

        我加了一點代碼將相關參數打印出來:

        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, 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



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 民勤县| 寻甸| 四平市| 柘荣县| 禹州市| 湘潭市| 安阳市| 双辽市| 永川市| 唐山市| 长乐市| 阿拉善右旗| 枣强县| 通榆县| 板桥市| 嘉峪关市| 禹州市| 高唐县| 文山县| 柏乡县| 江阴市| 大同市| 读书| 秦安县| 儋州市| 全椒县| 东乌| 武功县| 临沂市| 商洛市| 内乡县| 乌兰浩特市| 漯河市| 林甸县| 盐池县| 扶沟县| 旺苍县| 左云县| 安远县| 青州市| 铜梁县|