嵌入式开发--蒹葭的专栏

Care and Diligence Bring Luck.(谨慎和勤奋才能抓住机遇!)

用户操作
[即时聊天] [发私信] [加为好友]
蒹葭ID:flylonginsky
170523次访问,排名446好友2人,关注者39
flylonginsky的文章
原创 95 篇
翻译 0 篇
转载 12 篇
评论 118 篇
蒹葭的公告

奋斗永无止境
仁者不忧,知者不惑,勇者不惧。 Gold Price per Gram in China Yuan Renminbi
最近评论
bluehouse1985:Linux 环境下的多核调试
— Intel + Totalview 强强联合!
目前,在软件开发行业,各种性能优异的调试工具层出不穷。但是,它们中的绝大部分都只支持windows环境。即使能支持linux平台,操作起来也很不方便。因此,对于长期在linux上编写程序的开发人员来说,如何调试就成了一个令人头痛的问题!Intel软件 和 Total……
gsb19870:初学者.........看了下........
jxzxf:不好看懂
xkxiaodao:嗯,都是目标没时间的
zhengyun_ustc:非常感谢!!
文章分类
收藏
相册
MetaWeblog API
工作花絮
那人那事
引用
山外有山
Bekars涡轮增压的Blog
linux应用开发电子报(RSS)
叶帆工作室(RSS)
胶管的Blog(RSS)
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 RM9200中flash文件系统的移植收藏

新一篇: (转)关于pipe()的详细解析 | 旧一篇: 文件读写操作的缓存机制

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 (root@localhost.localdomain) (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 (rgooch@atnf.csiro.au)
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 -> 21F1D788  BSS: -> 21F3B204
RAM Configuration:
Bank #0: 20000000 32 MB
SST 39VF3201 flash
Flash:  4 MB
NAND:  64 MB
In:    serial
Out:   serial
Err:   serial

发表于 @ 2008年05月30日 10:28:22|评论(loading...)|编辑

新一篇: (转)关于pipe()的详细解析 | 旧一篇: 文件读写操作的缓存机制

评论:没有评论。

发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © 蒹葭