Linux 在 mtd 块设备上写入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15336285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:13:44  来源:igfitidea点击:

Write on a mtd block device

clinuxembeddedflash-memory

提问by marmottus

I'm trying to write on a NAND flash memory using MTD block device but I don't understand everything.

我正在尝试使用 MTD 块设备在 NAND 闪存上写入,但我不了解所有内容。

As I read here

当我在这里阅读时

  • mtdblockNis the read only block device N
  • mtdNis the read/write char device N
  • mtdNrois the read only char device N
  • mtdblockN是只读块设备 N
  • mtdN是读/写字符设备 N
  • mtdNro是只读字符设备 N

But I'd like to directly write bytes to the partition using a simple writein C and I don't understand how it works (I read somewhre that I first must erase the sectors I want to write on).

但是我想使用writeC 中的简单语句直接将字节写入分区,但我不明白它是如何工作的(我读到一些内容,我首先必须擦除要写入的扇区)。

Which device should I use and how to write on this device?

我应该使用哪种设备以及如何在该设备上书写?

采纳答案by Mike

Reading and writing from/to memory technology devices isn't really all that different than any other type of IO, with the exception that before you write you need to erase the sector (erase block)

从/向内存技术设备读取和写入与任何其他类型的 IO 并没有什么不同,除了在写入之前您需要擦除扇区(擦除块)

To make things simple on yourself you can always just use the mtd-utils (such as flash_erase, nanddumpand nandwrite, for erasing, read, and writing respectively) without the need for writing code.

为了让事情变得简单,您可以随时使用 mtd-utils(例如flash_erase,nanddumpnandwrite,分别用于擦除,读取和写入)而无需编写代码。

However if you do want to do it pragmatically, here's an example, make sure to read all the comments as I put all the details in there:

但是,如果您确实想务实地做到这一点,这里有一个示例,请务必阅读所有评论,因为我将所有详细信息都放在那里:

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>

int main()
{
    mtd_info_t mtd_info;           // the MTD structure
    erase_info_t ei;               // the erase block structure
    int i;

    unsigned char data[20] = { 0xDE, 0xAD, 0xBE, 0xEF,  // our data to write
                               0xDE, 0xAD, 0xBE, 0xEF,
                               0xDE, 0xAD, 0xBE, 0xEF,
                               0xDE, 0xAD, 0xBE, 0xEF,
                               0xDE, 0xAD, 0xBE, 0xEF};
    unsigned char read_buf[20] = {0x00};                // empty array for reading

    int fd = open("/dev/mtd0", O_RDWR); // open the mtd device for reading and 
                                        // writing. Note you want mtd0 not mtdblock0
                                        // also you probably need to open permissions
                                        // to the dev (sudo chmod 777 /dev/mtd0)

    ioctl(fd, MEMGETINFO, &mtd_info);   // get the device info

    // dump it for a sanity check, should match what's in /proc/mtd
    printf("MTD Type: %x\nMTD total size: %x bytes\nMTD erase size: %x bytes\n",
         mtd_info.type, mtd_info.size, mtd_info.erasesize);

    ei.length = mtd_info.erasesize;   //set the erase block size
    for(ei.start = 0; ei.start < mtd_info.size; ei.start += ei.length)
    {
        ioctl(fd, MEMUNLOCK, &ei);
        // printf("Eraseing Block %#x\n", ei.start); // show the blocks erasing
                                                  // warning, this prints a lot!
        ioctl(fd, MEMERASE, &ei);
    }    

    lseek(fd, 0, SEEK_SET);               // go to the first block
    read(fd, read_buf, sizeof(read_buf)); // read 20 bytes

    // sanity check, should be all 0xFF if erase worked
    for(i = 0; i<20; i++)
        printf("buf[%d] = 0x%02x\n", i, (unsigned int)read_buf[i]);

    lseek(fd, 0, SEEK_SET);        // go back to first block's start
    write(fd, data, sizeof(data)); // write our message

    lseek(fd, 0, SEEK_SET);              // go back to first block's start
    read(fd, read_buf, sizeof(read_buf));// read the data

    // sanity check, now you see the message we wrote!    
    for(i = 0; i<20; i++)
         printf("buf[%d] = 0x%02x\n", i, (unsigned int)read_buf[i]);


    close(fd);
    return 0;
}

The nice thing about this is since you can use the standards utils as you do from other devices, it makes it easy to understand what write(), open(), and read()do and what to expect from them.

关于这个的好处是,因为当你从其他设备你可以使用标准的utils的,它可以很容易地了解什么write()open()以及read()做,从他们的期望。

For example if while using write()you got a value of EINVALit could mean:

例如,如果在使用时write()您获得了EINVAL它的值可能意味着:

fd is attached to an object which is unsuitable for writing; or the file was opened with the O_DIRECT flag, and either the address specified in buf, the value specified in count, or the current file offset is not suitably aligned.

fd 附着在不适合书写的物体上;或者文件是使用 O_DIRECT 标志打开的,并且 buf 中指定的地址、count 中指定的值或当前文件偏移量未适当对齐。