精华内容
下载资源
问答
  • 这个文件中并没有增加mtd块设备,mtd块设备的代码文件是Mtd_blkdevs.c。它的功能是为mtd块设备读写提供...驱动入口:static struct mtd_blktrans_ops mtdblock_tr = {.name= "mtdblock",.major= 31,.part_bits= 0,....

    这个文件中并没有增加mtd块设备,mtd块设备的代码文件是Mtd_blkdevs.c。它的功能是为mtd块设备读写提供缓冲操作。

    另外还有一个文件mtdblock_ro.c,它定义的是mtd块设备缓冲的只读操作。

    驱动入口:

    static struct mtd_blktrans_ops mtdblock_tr = {

    .name= "mtdblock",

    .major= 31,

    .part_bits= 0,

    .blksize = 512,

    .open= mtdblock_open,

    .flush= mtdblock_flush,

    .release= mtdblock_release,

    .readsect= mtdblock_readsect,

    .writesect= mtdblock_writesect,

    .add_mtd= mtdblock_add_mtd, //增加一个mtd_blktrans_dev

    .remove_dev= mtdblock_remove_dev,

    .owner= THIS_MODULE,

    };

    static int __init init_mtdblock(void)

    {

    return register_mtd_blktrans(&mtdblock_tr);

    }

    static void __exit cleanup_mtdblock(void)

    {

    deregister_mtd_blktrans(&mtdblock_tr);

    }

    module_init(init_mtdblock);

    module_exit(cleanup_mtdblock);

    缓冲数据结构定义:

    static struct mtdblk_dev {

    struct mtd_info *mtd;

    int count;//使用计数

    struct mutex cache_mutex;

    unsigned char *cache_data; //缓冲区数据

    unsigned long cache_offset; //缓冲区数据的偏移地址(全局)

    unsigned int cache_size; //一般等于FLASH的擦除大小

    enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;

    } *mtdblks[MAX_MTD_DEVICES];

    mtd_blktrans_dev结构:

    struct mtd_blktrans_dev {

    struct mtd_blktrans_ops *tr;

    struct list_head list;

    struct mtd_info *mtd;

    struct mutex lock;

    int devnum; //分区序号,等于mtd->index

    unsigned long size;//分区大小,单位是512字节

    int readonly; //是否是只读的

    void *blkcore_priv; //指向gen_disk结构};

    mtd_blktrans_dev对应于mtd_info,每个分区有一个mtd_blktrans_dev实体。

    (1)open例程

    static int mtdblock_open(struct mtd_blktrans_dev *mbd)

    {

    struct mtdblk_dev *mtdblk;

    struct mtd_info *mtd = mbd->mtd;

    int dev = mbd->devnum;

    DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");

    if (mtdblks[dev]) {//如果如果mtdblk_dev存在,则返回

    mtdblks[dev]->count++;

    return 0;

    }

    //mtdblk_dev不存在,则新增一个

    /* OK, it's not open. Create cache info for it */

    mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);

    if (!mtdblk)

    return -ENOMEM;

    mtdblk->count = 1;

    mtdblk->mtd = mtd;

    mutex_init(&mtdblk->cache_mutex);

    mtdblk->cache_state = STATE_EMPTY;

    if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) {

    mtdblk->cache_size = mtdblk->mtd->erasesize;

    mtdblk->cache_data = NULL;

    }

    mtdblks[dev] = mtdblk;

    DEBUG(MTD_DEBUG_LEVEL1, "ok\n");

    return 0;

    }

    (2)release例程

    它检查检查mtdblk_dev的使用计数,若为0,则释放内存。

    static int mtdblock_release(struct mtd_blktrans_dev *mbd)

    {

    int dev = mbd->devnum;

    struct mtdblk_dev *mtdblk = mtdblks[dev];

    DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");

    mutex_lock(&mtdblk->cache_mutex);

    write_cached_data(mtdblk);

    mutex_unlock(&mtdblk->cache_mutex);

    if (!--mtdblk->count) {

    /* It was the last usage. Free the device */

    mtdblks[dev] = NULL;

    if (mtdblk->mtd->sync)

    mtdblk->mtd->sync(mtdblk->mtd);

    vfree(mtdblk->cache_data);

    kfree(mtdblk);

    }

    DEBUG(MTD_DEBUG_LEVEL1, "ok\n");

    return 0;

    }

    (3)writesect例程

    static int mtdblock_writesect(struct mtd_blktrans_dev *dev,

    unsigned long block, char *buf)

    {

    struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];

    if (unlikely(!mtdblk->cache_data && mtdblk->cache_size)) {//如果mtdblk->cache_data为空,则分配内存

    mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);

    if (!mtdblk->cache_data)

    return -EINTR;

    /* -EINTR is not really correct, but it is the best match

    * documented in man 2 write for all cases. We could also

    * return -EAGAIN sometimes, but why bother?

    */

    }

    return do_cached_write(mtdblk, block<<9, 512, buf);//把512字节数据写入到block<<9的地址处

    }

    static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,

    int len, const char *buf)

    {

    struct mtd_info *mtd = mtdblk->mtd;

    unsigned int sect_size = mtdblk->cache_size;

    size_t retlen;

    int ret;

    DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",

    mtd->name, pos, len);

    if (!sect_size) //直接写入

    return mtd->write(mtd, pos, len, &retlen, buf);

    ///单次写入的数据大小不能超过sect_size,写入时如果小于sect_size,则先写入到cache

    while (len > 0) {

    unsigned long sect_start = (pos/sect_size)*sect_size;

    unsigned int offset = pos - sect_start;

    unsigned int size = sect_size - offset;

    if( size > len )

    size = len;

    if (size == sect_size) {//如果刚好是一个sect的大小,则不经cache直接写入

    /*

    * We are covering a whole sector. Thus there is no

    * need to bother with the cache while it may still be

    * useful for other partial writes.

    */

    ret = erase_write (mtd, pos, size, buf);

    if (ret)

    return ret;

    } else {//使用cache

    /* Partial sector: need to use the cache */

    if (mtdblk->cache_state == STATE_DIRTY && //如果cache有数据且cache的数据和写入的数据不在同一个sect中,则先把cache中的数据写入

    mtdblk->cache_offset != sect_start) {

    ret = write_cached_data(mtdblk);

    if (ret)

    return ret;

    }

    if (mtdblk->cache_state == STATE_EMPTY || //如果cache中没有数据,则先把FLASH中对应的数据读出来放到cache

    mtdblk->cache_offset != sect_start) {

    /* fill the cache with the current sector */

    mtdblk->cache_state = STATE_EMPTY;

    ret = mtd->read(mtd, sect_start, sect_size,

    &retlen, mtdblk->cache_data);

    if (ret)

    return ret;

    if (retlen != sect_size)

    return -EIO;

    mtdblk->cache_offset = sect_start;

    mtdblk->cache_size = sect_size;

    mtdblk->cache_state = STATE_CLEAN;

    }

    /* write data to our local cache *///修改cache中的数据

    memcpy (mtdblk->cache_data + offset, buf, size);

    mtdblk->cache_state = STATE_DIRTY;

    }

    buf += size;

    pos += size;

    len -= size;

    }

    return 0;

    }

    static int write_cached_data (struct mtdblk_dev *mtdblk)

    {

    struct mtd_info *mtd = mtdblk->mtd;

    int ret;

    if (mtdblk->cache_state != STATE_DIRTY)

    return 0;

    DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "

    "at 0x%lx, size 0x%x\n", mtd->name,

    mtdblk->cache_offset, mtdblk->cache_size);

    //erase_write调用mtd_info的相应操作

    ret = erase_write (mtd, mtdblk->cache_offset,

    mtdblk->cache_size, mtdblk->cache_data);

    if (ret)

    return ret;

    /*

    * Here we could argubly set the cache state to STATE_CLEAN.

    * However this could lead to inconsistency since we will not

    * be notified if this content is altered on the flash by other

    * means. Let's declare it empty and leave buffering tasks to

    * the buffer cache instead.

    */

    mtdblk->cache_state = STATE_EMPTY;

    return 0;

    }

    (3)readsect例程

    static int mtdblock_readsect(struct mtd_blktrans_dev *dev,

    unsigned long block, char *buf)

    {

    struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];

    return do_cached_read(mtdblk, block<<9, 512, buf);

    }

    static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,

    int len, char *buf)

    {

    struct mtd_info *mtd = mtdblk->mtd;

    unsigned int sect_size = mtdblk->cache_size;

    size_t retlen;

    int ret;

    DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",

    mtd->name, pos, len);

    if (!sect_size)

    return mtd->read(mtd, pos, len, &retlen, buf);

    while (len > 0) {

    unsigned long sect_start = (pos/sect_size)*sect_size;

    unsigned int offset = pos - sect_start;

    unsigned int size = sect_size - offset;

    if (size > len)

    size = len;

    /*

    * Check if the requested data is already cached 检查读取的数据是否已经在cache中

    * Read the requested amount of data from our internal cache if it

    * contains what we want, otherwise we read the data directly

    * from flash.

    */

    if (mtdblk->cache_state != STATE_EMPTY &&

    mtdblk->cache_offset == sect_start) {

    memcpy (buf, mtdblk->cache_data + offset, size);

    } else {

    ret = mtd->read(mtd, pos, size, &retlen, buf);

    if (ret)

    return ret;

    if (retlen != size)

    return -EIO;

    }

    buf += size;

    pos += size;

    len -= size;

    }

    return 0;

    }

    (4)flush例程

    它将cache中数据写入到存储

    static int mtdblock_flush(struct mtd_blktrans_dev *dev)

    {

    struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];

    mutex_lock(&mtdblk->cache_mutex);

    write_cached_data(mtdblk);

    mutex_unlock(&mtdblk->cache_mutex);

    if (mtdblk->mtd->sync)

    mtdblk->mtd->sync(mtdblk->mtd);

    return 0;

    }

    展开全文
  • sudo modprobe mtdblock sudo dd if=/home/test/app.img of=/dev/mtdblock0 (dd命令是指定大小的块拷贝文件,并在拷贝的同时进行制定的转换 if=file输出文件名) <p>3.创建挂载点...
  • 在/dev中存在mtd文件,但是却没有mtdblock,这让我很费解了,我的linux内核版本是2.6.31 感觉mtd与mtdblock应该要同时创建的才对啊,难道这个版本的内核不创建mtdblock文件?求告知。。。 如果可以,顺便说下mtd和...
  • mtd和mtdblock的区别

    千次阅读 2018-07-11 20:23:52
    做升级方案用到了mtd-utils中的flash_eraseall和flash_cp两个工具,在进行方案验证的时候,遭遇到各种不解和疑惑,因对MTD的原理不熟悉,所以只能多次尝试,虽然最后把方案搞定了,不过觉得MTD中的mtd和mtdblock区别...

    原文地址:http://my.oschina.net/shelllife/blog/123482

    • 做升级方案用到了mtd-utils中的flash_eraseall和flash_cp两个工具,在进行方案验证的时候,遭遇到各种不解和疑惑,因对MTD的原理不熟悉,所以只能多次尝试,虽然最后把方案搞定了,不过觉得MTD中的mtd和mtdblock区别这块还是值得总结学习一下。这里先说明一下问题现象,然后在进行具体的区别原理解释。

    MTD设备(Nor Flash)使用中的问题现象表现

    • mtd-utils工具对mtd和mtdblock分区设备的区别处理
    / $ flash_eraseall /dev/mtdblock/2
    flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
    / $ flash_eraseall /dev/mtdblock/2
    flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
    / $ flash_eraseall /dev/mtd/2
    Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
    / $ flashcp rootfs_version /dev/mtdblock2
    This doesn't seem to be a valid MTD flash device!
    / $ flashcp rootfs_version /dev/mtdblock/2
    This doesn't seem to be a valid MTD flash device!
    / $ flashcp rootfs_version /dev/mtd2
    • mtd和mtdblock分区设备mount时的区别
    / $ mount -t jffs2 /dev/mtd/2 qqzm/
    mount: Mounting /dev/mtd/2 on qqzm/ failed: Invalid argument
    / $ mount -t jffs2 /dev/mtd2 qqzm/
    mount: Mounting /dev/mtd2 on qqzm/ failed: Invalid argument
    / $ mount -t jffs2 /dev/mtdblock/2 qqzm/
    • mtdblock挂载成功,但擦除后卸载失败
    / $ flash_eraseall /dev/mtd/2 <span></span> Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
    /qqzm $ mount
    /dev/root on / type jffs2 (rw,noatime)
    proc on /proc type proc (rw,nodiratime)
    sysfs on /sys type sysfs (rw)
    devfs on /dev type devfs (rw)
    devpts on /dev/pts type devpts (rw)
    /dev/mmcblk0p1 on /mnt/sd type vfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)
    /dev/mtdblock/2 on /qqzm type jffs2 (rw,noatime)
    none on /qqzm/www/cgi-bin/tmp type ramfs (rw)
    /qqzm $ cd ..
    / $ umount /qqzm
    umount: Couldn't umount /qqzm: Inappropriate ioctl for device
    / $ umount /dev/mtdblock/2
    umount: Couldn't umount /dev/mtdblock/2: Inappropriate ioctl for device
    / $
    • 通过上面的不断尝试和错误反馈,我把方案基本验证通过了,只是对其中的原理不清楚:

      • 为什么mtd和mtdblock明明是同一个设备分区却有不同的操作?
      • mount命令只能挂载块设备吗?
      • 卸载mtdblock设备时,Inappropriate ioctl for device是什么意思?
      • unable to get MTD device info,又是什么意思?

    MTD技术的基本原理

    • MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口,并进行了一个层次划分,层次从上到下大致为:设备文件、MTD设备层、MTD原始设备层、硬件驱动层。MTD的所有源代码在/drivers/mtd子目录下。
    系统中的MTD设备文件
    ~ $ ls /dev/mtd* -l
    crw-rw----    1 root     root      90,   0 Jan  1 00:00 /dev/mtd0
    crw-rw----    1 root     root      90,   1 Jan  1 00:00 /dev/mtd0ro
    crw-rw----    1 root     root      90,   2 Jan  1 00:00 /dev/mtd1
    crw-rw----    1 root     root      90,   3 Jan  1 00:00 /dev/mtd1ro
    crw-rw----    1 root     root      90,   4 Jan  1 00:00 /dev/mtd2
    crw-rw----    1 root     root      90,   5 Jan  1 00:00 /dev/mtd2ro
    crw-rw----    1 root     root      90,   6 Jan  1 00:00 /dev/mtd3
    crw-rw----    1 root     root      90,   7 Jan  1 00:00 /dev/mtd3ro
    brw-rw----    1 root     root      31,   0 Jan  1 00:00 /dev/mtdblock0
    brw-rw----    1 root     root      31,   1 Jan  1 00:00 /dev/mtdblock1
    brw-rw----    1 root     root      31,   2 Jan  1 00:00 /dev/mtdblock2
    brw-rw----    1 root     root      31,   3 Jan  1 00:00 /dev/mtdblock3
    
    /dev/mtd:
    crw-rw-rw-    1 root     root      90,   0 Jan  1 00:00 0
    cr--r--r--    1 root     root      90,   1 Jan  1 00:00 0ro
    crw-rw-rw-    1 root     root      90,   2 Jan  1 00:00 1
    cr--r--r--    1 root     root      90,   3 Jan  1 00:00 1ro
    crw-rw-rw-    1 root     root      90,   4 Jan  1 00:00 2
    cr--r--r--    1 root     root      90,   5 Jan  1 00:00 2ro
    crw-rw-rw-    1 root     root      90,   6 Jan  1 00:00 3
    cr--r--r--    1 root     root      90,   7 Jan  1 00:00 3ro
    
    /dev/mtdblock:
    brw-------    1 root     root      31,   0 Jan  1 00:00 0
    brw-------    1 root     root      31,   1 Jan  1 00:00 1
    brw-------    1 root     root      31,   2 Jan  1 00:00 2
    brw-------    1 root     root      31,   3 Jan  1 00:00 3
    ~ $
    • 可以看到有mtdN和对应的/dev/mtd/N、mtdblockN和对应的/dev/mtdblock/N两类MTD设备,分别是字符设备,主设备号90和块设备,主设备号31。其中/dev/mtd0和/dev/mtd/0是完全等价的,/dev/mtdblock0和/dev/mtdblock/0是完全等价的,而/dev/mtd0和/dev/mtdblock0则是同一个MTD分区的两种不同应用描述,操作上是有区别的。
    /dev/mtdN设备
    • /dev/mtdN 是MTD架构中实现的mtd分区所对应的字符设备(将mtd设备分成多个区,每个区就为一个字符设备),其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。

    • mtd-utils中的flash_eraseall等工具,就是以这些ioctl为基础而实现的工具,实现一些关于Flash的操作。比如,mtd 工具中 flash_eraseall中:

    if (ioctl(fd, MEMGETINFO, &meminfo) != 0) 
    {
       fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device);
       return 1;
    }
    • MEMGETINFO是Linux MTD中的drivers/mtd/mtdchar.c中的ioctl命令,使用mtd字符设备需要加载mtdchar内核模块。该代码解释了上面的第一个现象。
    /dev/mtdblockN设备
    • /dev/mtdblockN,是Flash驱动中用add_mtd_partitions()添加MTD设备分区,而生成的对应的块设备。MTD块设备驱动程序可以让flash器件伪装成块设备,实际上它通过把整块的erase block放到ram里面进行访问,然后再更新到flash,用户可以在这个块设备上创建通常的文件系统。

    • 而对于MTD块设备,MTD设备层是不提供ioctl的实现方法的,也就不会有对应的MEMGETINFO命令之类,因此不能使用nandwrite,flash_eraseall,flash_erase等工具去对/dev/mtdblockN去进行操作,否则就会出现上面的现象一,同时也解释了现象3——用mtd2擦除分区后,在用mtdblock2进行umount就会造成混乱。

    • mtd块设备的大小可以通过proc文件系统进行查看:

    ~ $ cat /proc/partitions
    major minor  #blocks  name
    
      31     0        512 mtdblock0
      31     1       1024 mtdblock1
      31     2       5632 mtdblock2
      31     3       9216 mtdblock3
     254     0   30760960 mmcblk0    
     254     1   30756864 mmcblk0p1
    ~ $
    • 后面的两个是SD块设备的分区大小。每个block的大小是1KB。
    MTD设备分区和总结
    • 通过proc文件系统查看mtd设备的分区情况:
    ~ $ cat /proc/mtd
    dev:    size   erasesize  name
    mtd0: 00080000 00020000 "boot"
    mtd1: 00100000 00020000 "kernel"
    mtd2: 00580000 00020000 "roofs70"
    mtd3: 00900000 00020000 "app"
    ~ $
    • 可以发现,实际上mtdN和mtdblockN描述的是同一个MTD分区,对应同一个硬件分区,两者的大小是一样的,只不过是MTD设备层提供给上层的视图不一样,给上层提供了字符和块设备两种操作视图——为了上层使用的便利和需要,比如mount命令的需求,你只能挂载块设备(有文件系统),而不能对字符设备进行挂载,否则会出现上面的现象2:无效参数。

    • 这里对于mtd和mtdblock设备的使用场景进行简单总结:

      • mtd-utils工具只能应用与/dev/mtdN的MTD字符设备
      • mount、umount命令只对/dev/mtdblockN的MTD块设备有效
      • /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区(N一样)
    展开全文
  • mtdblock.c中的算法思想

    2015-11-11 17:19:26
    以前以为mtdblock.c文件很简单,其实它蕴含着大道理 1. cache原理 为了方便数据快速操作,mtdblock加入了 cache。 以前以为cache等同于page,但是看code发现cache_size其实是erase size即block size,在代码中由变量...

    以前以为mtdblock.c文件很简单,其实它蕴含着大道理

    1. cache原理

    为了方便数据快速操作,mtdblock加入了 cache。

    以前以为cache等同于page,但是看code发现cache_size其实是erase size即block size,在代码中由变量sec_size表示。

    nand flash的操作本质上是在do_cached_read和do_cached_write中实现的,可以看到是以block为单位而不是page size。


    2.mtd_blktrans_ops


    mtd_blocktrans_ops包含了设备读写操作函数指针,比较重要的是mtdblock_readsect和mtdblock_writesect。

    研究其代码发现其实readsect和writesect读写是按512bytes为单位的,其中当然使用了上面将的cache原理。


    在这里先留个疑问,为什么不按照page size读写?难道是为了跟硬盘等设备按512 byte统一?

    对,其实假如我要读一个page,要调用4次readsect,但是不需要重复发read page命令。

    因为第一次其实已经将其拷贝到cache中了,只需要将cache的数据拷贝出来就可以了。

    这样的好处是可以方便的在上面加fat32等文件系统。


    展开全文
  • root=/dev/mtdblock4 rootfstype=yaffs2 console=ttySAC0,115200 init=/linuxrc 板子为s5pv210,文件系统为yaffs2,利用busybox-1.31.1制作,错误如下: 1. [0.712506] VFS: Cannot open root device "mtdblock4" ...

        在移植嵌入式linux文件系统时,常常出现文件挂载错误,以下是我的内核配置参数:
        root=/dev/mtdblock4 rootfstype=yaffs2 console=ttySAC0,115200 init=/linuxrc 
        板子为s5pv210,文件系统为yaffs2,利用busybox-1.31.1制作,错误如下:

    1.   [0.712506] VFS: Cannot open root device "mtdblock4" or unknown-block(0,0)
        [0.718583] Please append a correct "root=" boot option; here are the available partitions:
        [0.726895] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
    原因分析:以上内核启动参数是把指明文件系统烧在flash的第5个分区上(从0开始),始过我的分析和测试,unknown-block(0,0)即是表明内核找不到这个flash分区,也就是说很可能内核中并没有对flash分区。经过存细检查,内核打印的串口信息中确实没有flash分区信息,这种情况需要移植flash分区驱动,重启后应该有如下信息:
        [    1.437490] NAND subpage size: 2048 bytes
        <5>Creating 5 MTD partitions on "s5pv210-nand":
        [    1.445722] Creating 5 MTD partitions on "s5pv210-nand":
        <5>0x0000000c0000-0x000000100000 : "misc"
        [    1.454734] 0x0000000c0000-0x000000100000 : "misc"
        <5>0x000000100000-0x000000600000 : "recovery"
        [    1.463574] 0x000000100000-0x000000600000 : "recovery"
        <5>0x000000600000-0x000000b00000 : "kernel"
        [    1.472586] 0x000000600000-0x000000b00000 : "kernel"
        <5>0x000000b00000-0x000000e00000 : "ramdisk"
        [    1.481512] 0x000000b00000-0x000000e00000 : "ramdisk"
        <5>0x000000e00000-0x000040000000 : "system"
        [    1.490437] 0x000000e00000-0x000040000000 : "system"    
        
    文件系统就烧在system这个分区中。

    2.   VFS: Cannot open root device "mtdblock4" or unknown-block(31,4)
    [    1.854179] VFS: Cannot open root device "mtdblock4" or unknown-block(31,4)
    Please append a correct "root=" boot option; here are the available partitions:
    [    1.868130] Please append a correct "root=" boot option; here are the available partitions:
    1f00             256 mtdblock0 [    1.879135] 1f00             256 mtdblock0  (driver?)

    原因分析:从这里的打印信息来看,unknown-block(31,4)表明分区是没有问题的,已经识别了,主设备号是31,分区号为4,
    只是识别不了文件系统,这种情况有可能是文件设备类型和指定的类型对不上,还有就是内核不支持指定的文件系统,这就需要
    在内核配置中加上,我这种情况是内核不支持yaffs2文件系统,内核中配置如下:
    File System->Miscellaneous filesystems->yaffs2
    重新编译烧录后,就不会再报这个错了。

    另外随便说一下,内核要打印详细的配置信息,除了串口配置正确和内核启动调试以外,还有一项很重要的选项是:
    General setup->Configure standard kernel features (expert users)  ---> 
    将这下面的所有选项都选上。

    展开全文
  • Buffer I/O error on device mtdblock

    千次阅读 2014-06-25 13:37:30
    Buffer I/O error on device mtdblock end_request: I/O error, dev mtdblock8   驱动代码错误
  • mtd块设备缓冲操作---mtdblock.c

    千次阅读 2014-02-19 11:58:44
    这个文件中并没有增加mtd块设备,mtd块设备的代码文件是Mtd_blkdevs.c。...static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, .blksize = 512, .o
  • linux内核启动过程中有以下的打印信息: 1f00 1024 mtdblock0 (driver?) 1f01 15360 mtdblock1 (driver?) 1f02 40960 mtdblock2 (driver?) 1f03 51200 mtdblock3 (driver?) 1f04
  • cat /dev/mtdblock1 > 123.txt hexdump 123.txt -c flash_eraseall /dev/mtd6 flashcp -v 123.txt /dev/mtd6 hexdump /dev/mtd6 -c   ============================================== mkfs....
  • end_request: I/O error, dev mtdblock3, sector 0

    千次阅读 2017-06-06 15:34:19
    end_request: I/O error, dev mtdblock3, sector 0  ​ 挂载root时候出错: end_request: I/O error, dev mtdblock3, sector 0 Buffer I/O error on device mtdblock3, logical block 0 end_request: I/...
  • utils中的flash_eraseall和flash_cp两个工具,在进行方案验证的时候,遭遇到各种不解和疑惑,因对MTD的原理不熟悉,所以只能多次尝试,虽然最后把方案搞定了,不过觉得MTD中的mtd和mtdblock区别这块还是值得总结学习...
  • 如果是设置 root=/dev/mtdblock2 ,但内核启动后报错VFS: Cannot open root device "mtdblock2" or unknown-block(31,2): error -2 第一步 第二步 第三步,确认下 即设置了MTD的block device支持,此步...
  • 关于内核启动提示Wait for root filesystem /dev/mtdblock3… 有可能的原因 之前使用4.13版本的内核可以正常启动,但是换成5.2版本的内核后就提示上述错误,最开始认为是spi驱动加载不正确,但是对比之前的内核配置和...
  • 最近玩荔枝派,使用全志f1c100s的芯片,编译出来的uboot,kernel,rootfs,dtb打包烧进去以后,系统上电进入到内核部分总是提示Waiting for root device /dev/mtdblock3…,并且也没有打印分区信息,感觉应该是内核没有识别...
  • /dev/mtd和/dev/mtdblock的区别

    千次阅读 2016-03-11 12:52:43
    这里对于mtd和mtdblock设备的使用场景进行简单总结: mtd-utils工具只能应用与/dev/mtdN的MTD字符设备 mount、umount命令只对/dev/mtdblockN的MTD块设备有效 /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区...
  • VFS: Cannot open root device "mtdblock5" or unknown-block(0,0): error -6解决方法
  • 【问题】 系统启动后,虽然nand驱动表现...Kernel command line: root=/dev/mtdblock2 rw init=/linuxrc console=ttyAMA1,115200 mem=64M rootfstype=yaffs2。。。。。。。。 AS353X NAND Driver, (c) 2010 austri...
  • 【问题】 系统启动后,虽然nand驱动表现正常,但是最后挂载rootfs时候出错: Kernel command line: root=/dev/mtdblock2 rw init=/linuxrc console=ttyAMA1,115200 mem=64M rootfstype=...
  • 这里对于mtd和mtdblock设备的使用场景进行简单总结: mtd-utils工具只能应用于/dev/mtdN的MTD字符设备 mount、umount命令只对/dev/mtdblockN的MTD块设备有效 /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区...
  • can't read superblock on /dev/mtdblock0 1.fsck /dev/xxx 2.e2fsck -b 8193 <device> e2fsck -b 32768 <device> 都不行,试来试去, 最后灵机一动,在uboot下操作: sf probe sf erase 0...
  • end_request: I/O error, dev mtdblock2, sector 0 Buffer I/O error on device mtdblock2, logical block 0 原因分析:由于内核是通过uboot烧写到nandflash中,因此uboot产生的ecc校验码与内核的ecc校验码...
  • linux 之 mtd and mtdblock

    2021-04-28 17:31:47
     1 Jan 1 00:00 mtdblock1 brw-rw---- 1 root root 31, 2 Jan 1 00:00 mtdblock2 brw-rw---- 1 root root 31, 3 Jan 1 00:00 mtdblock3 通过proc文件系统查看mtd设备的分区情况 # cat /proc/mtd dev: ...
  • 1、./dev/mtdblock4 是用于存储配置使用的分区,之前使用16M 的flash是能够正常挂载的,现在使用了32M 的flash,并且分区划分没有发生变化,但是在使用烧录器烧写flah的时候,发现从flash中读取出来的数据和我生成的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,679
精华内容 3,871
关键字:

mtdblock