RM9200中flash文件系统的移植

flash文件系统在嵌入式linux系统中是必须的,无论是作为只读的根文件系统还是作为可写的用户文件系统。目前在linux-2.6.14内核上 移植flash文件系统。下载相应内核,打好at91rm9200的补丁后,却发现先前移植nand文件系统的方法在flash文件系统中完全不行。只好从头开始了。 星光AT91RM9200开发板的flash芯片是SST39VF3201,16 位 ,4M 。按目前计划,准备分区为三个区,分别为uboot(0x40000), kernel(0x1c0000), rootfs(0x200000), 应该可以将linux的最小系统跑起来的。 首先,添加MTD分区的底层驱动文件,在drivers/mtd/maps下添加at91rm9200.c文件,该文件是flash分区的基本驱动文件,包含分区信息、芯片识别等基本flash文件系统的底层实现。事实上,该文件并不需要从头开始创建,可以参考该目录下其它文件来修改,如edb7312.c。代码如下

#define WINDOW_ADDR 0x10000000      /* physical properties of flash */
#define WINDOW_SIZE 0x400000
#define BUSWIDTH    2

#define MSG_PREFIX "RM9200-NOR:"   /* prefix for our printk()'s */
#define MTDID      "rm9200-nor"    /* for mtdparts= partitioning */

static struct mtd_info *mymtd;

struct map_info rm9200nor_map = {
        .name = "NOR flash on rm9200",
        .size = WINDOW_SIZE,
        .bankwidth = BUSWIDTH,
        .phys = WINDOW_ADDR,
};

#ifdef CONFIG_MTD_PARTITIONS

/*
* MTD partitioning stuff 
*/
static struct mtd_partition rm9200_partitions[3] =
{
        {        /* uboot 256K */
                .name = "uboot",
                .size = 0x40000,
                .offset = 0
                /*.mask_flags = MTD_WRITEABLES*/
        },
        {        /* kernel 1.768M */
                .name = "kernel",
                .size = 0x1C0000,
                .offset = 0x40000
                /*.mask_flags = MTD_WRITEABLES*/
        },
        {        /* rootfs 2M */
                .name = "rootfs",
                .size = 0x200000,
                .offset = 0x200000
        },
};

//static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static const char *probes[] = { NULL };

#endif

static int                   mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts    = 0;

int __init init_rm9200nor(void)
{
        const char *part_type = 0;

   printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", 
               WINDOW_SIZE, WINDOW_ADDR);
        rm9200nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);

        if (!rm9200nor_map.virt) {
                printk(MSG_PREFIX "failed to ioremap\n");
                return -EIO;
        }
        
        simple_map_init(&rm9200nor_map);

        mymtd = do_map_probe("jedec_probe", &rm9200nor_map);
        if(!mymtd)
                mymtd = do_map_probe("cfi_probe", &rm9200nor_map);
        
        if (mymtd) {
                mymtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
                mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
                if (mtd_parts_nb > 0)
                  part_type = "detected";

                if (mtd_parts_nb == 0)
                {
                        mtd_parts = rm9200_partitions;        /* static_partitions */
                        mtd_parts_nb = ARRAY_SIZE(rm9200_partitions); /* static_partitions */
                        part_type = "static";
                }
#endif
                add_mtd_device(mymtd);
                if (mtd_parts_nb == 0)
                  printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
                else
                {
                        printk(KERN_NOTICE MSG_PREFIX
                               "using %s partition definition\n", part_type);
                        add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);
                }
                return 0;
        }

        iounmap((void *)rm9200nor_map.virt);
        return -ENXIO;
}

static void __exit cleanup_rm9200nor(void)
{
        if (mymtd) {
                del_mtd_device(mymtd);
                map_destroy(mymtd);
        }
        if (rm9200nor_map.virt) {
                iounmap((void *)rm9200nor_map.virt);
                rm9200nor_map.virt = 0;
        }
}

module_init(init_rm9200nor);
module_exit(cleanup_rm9200nor);

代码比较好理解,因为大部分并不需要自己写,只是照搬过来。

下一步就是要写flash芯片的驱动了。flash为SST39VF3201,查芯片手册,明确其接口形式(先前写上面代码时,用的是CFI接口,只用了do_map_probe("cfi_probe", &rm9200nor_map);
结果死活找不到芯片。后来在cfi_probe.c中根本找不到芯片,当然不能通过了,查手册后才知道自己犯了一个原则性错误)。
在drivers\mtd\chips\jedec_probe.c中找到以下语句
{
.mfr_id = MANUFACTURER_SST, /* should be CFI */
.dev_id = SST39LF160,
.name = "SST 39LF160",
.uaddr = {
[0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
[1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 2,
.regions = {
ERASEINFO(0x1000,256),
ERASEINFO(0x1000,256)
}
},
这是SST39LF1601的代码,依照这个代码,编写SST39VF3201的jedec_table项:
{
.mfr_id = MANUFACTURER_SST, /* should be CFI */
.dev_id = SST39VF3201,
.name = "SST 39VF3201",
.uaddr = {
[0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
[1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
},
.DevSize = SIZE_4MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 2,
.regions = {
ERASEINFO(0x1000,1024)
}
},
在文件开头的宏定义中增加flash的芯片ID号:
#define SST39VF3201 0x235b
基本完成芯片级驱动代码编写,下面就是linux内核的配置了,要将我们的修改增加到内核中去。这一步对了解linux内核配置的来讲比较简单,在此略过。
配置内核:
在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 │ │
│ │
Flash chip driver advanced configuration options │ │
│ │ Flash cmd/query data swapping (NO) ---> │ │
│ │
Specific CFI Flash geometry selection │ │
│ │ [ ] Support 8-bit buswidth │ │
│ │
Support 16-bit buswidth │ │
│ │ [ ] Support 32-bit buswidth │ │
│ │ [ ] Support 64-bit buswidth │ │
│ │ [ ] Support 128-bit buswidth │ │
│ │ [ ] Support 256-bit buswidth │ │
│ │
Support 1-chip flash interleave │ │
│ │ [ ] Support 2-chip flash interleave │ │
│ │ [ ] Support 4-chip flash interleave │ │
│ │ [ ] Support 8-chip flash interleave

在Mapping drivers for chip access中选中我们编写的at92rm9200.c的配置选项。系统配置完毕。
编译内核,启动可以看到输出了:
U-Boot 1.1.4 (Jun 12 2007 - 20:30:10)

U-Boot code: 21F00000 -> 21F1D788 BSS: -> 21F3B204
RAM Configuration:
Bank #0: 20000000 32 MB
SST 39VF3201 flash
Flash: 4 MB
NAND: 0 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
uboot>
uboot> loadb
## Ready for binary (kermit) download to 0x20008000 at 115200 bps...

uboot> bootm
## Booting image at 20008000 ...
Image Name: Linux-2.6.14
Created: 2007-06-19 11:37:53 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1059236 Bytes = 1 MB
Load Address: 20008000
Entry Point: 20008040
Verifying Checksum ... OK
XIP Kernel Image ... OK

Starting kernel ...

Uncompressing Linux.............................................................Linux version 2.6.14 ([email protected]) (gcc version 3.4.1) #26 Tue J7CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: Atmel AT91RM9200-DK
Memory policy: ECC disabled, Data cache writeback
Clocks: CPU 179 MHz, master 59 MHz, main 18.432 MHz
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: mem=32M noinitrd console=ttyS0,115200 init=/linnuxrc root=2AT91: 128 gpio irqs in 4 banks
PID hash table entries: 256 (order: 8, 4096 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 32MB = 32MB total
Memory: 30116KB available (1752K code, 379K data, 96K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
NET: Registered protocol family 16
usbcore: registered new driver usbfs
usbcore: registered new driver hub
NetWinder Floating Point Emulator V0.97 (double precision)
devfs: 2004-01-31 Richard Gooch ([email protected])
devfs: boot_options: 0x1
yaffs Jun 12 2007 20:21:49 Installing.
AT91 Real Time Clock driver.
AT91 SPI driver loaded
AT91 Watchdog Timer enabled (5 seconds)
ttyS0 at MMIO 0xfefff200 (irq = 1) is a AT91_SERIAL
ttyS1 at MMIO 0xfefc4000 (irq = 7) is a AT91_SERIAL
io scheduler noop registered
io scheduler anticipatory registered
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
eth0: AT91 ethernet at 0xfefbc000 int=24 10-HalfDuplex (08:00:3e:26:0a:5b)
eth0: Davicom 9196 PHY (Copper)
RM9200-NOR:0x00400000 at 0x10000000
Found: SST 39VF3201
NOR flash on rm9200: Found 1 x16 devices at 0x0 in 16-bit bank
number of JEDEC chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
RM9200-NOR:using static partition definition
Creating 3 MTD partitions on "NOR flash on rm9200":
0x00000000-0x00040000 : "uboot"
0x00040000-0x00200000 : "kernel"
0x00200000-0x00400000 : "rootfs"
No SmartMedia card inserted.
No NAND device found!!!
at91_cf: irqs det #64, io #0
usbmon: debugfs is not available
at91rm9200-ohci at91rm9200-ohci: AT91RM9200 OHCI
at91rm9200-ohci at91rm9200-ohci: new USB bus registered, assigned bus number 1
at91rm9200-ohci at91rm9200-ohci: irq 23, io mem 0x00300000
usb usb1: Product: AT91RM9200 OHCI
usb usb1: Manufacturer: Linux 2.6.14 ohci_hcd
usb usb1: SerialNumber: at91rm9200
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
udc: at91_udc version 8 March 2005
mice: PS/2 mouse device common for all mice
i2c /dev entries driver
Found AT91 i2c
AT91RM9200 MCI initialized
NET: Registered protocol family 2
IP route cache hash table entries: 512 (order: -1, 2048 bytes)
TCP established hash table entries: 2048 (order: 1, 8192 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17

虽然flash上的文件系统还没有做,但flash芯片及flash文件系统分区信息已经出来了。有了这,就只需要在flash做实际的文件系统了。

添加64M的nandflash后uboot自动识别出来了!
U-Boot 1.1.4 (Jun 12 2007 - 20:30:10)

U-Boot code: 21F00000 -> 21F1D788BSS: -> 21F3B204
RAM Configuration:
Bank #0: 20000000 32 MB
SST 39VF3201 flash
Flash:4 MB
NAND:64 MB
In: serial
Out: serial
Err: serial

你可能感兴趣的:(.net,linux,cache,C#,Flash)