在mtd块设备上写

时间:2021-12-25 00:01:30

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

当我读到这里

  • mtdblockN is the read only block device N
  • mtdblockN是唯一读取的块设备
  • mtdN is the read/write char device N
  • mtdN是读写字符设备N
  • mtdNro is the read only char device N
  • mtdNro是只读char设备N

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

但是我想直接用C语言写字节到分区中,我不明白它是如何工作的(我读了一些内容,我必须首先删除我想写的扇区)。

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

我应该使用哪个设备,如何在这个设备上写?

1 个解决方案

#1


13  

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, nanddump and nandwrite, for erasing, read, and writing respectively) without the need for writing code.

要使事情变得简单,您可以使用md -utils(例如flash_erase、nanddump和nandwrite,用于分别擦除、读取和写入),而不需要编写代码。

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 EINVAL it 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中指定的值,或者当前的文件偏移量是不合适的。

#1


13  

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, nanddump and nandwrite, for erasing, read, and writing respectively) without the need for writing code.

要使事情变得简单,您可以使用md -utils(例如flash_erase、nanddump和nandwrite,用于分别擦除、读取和写入),而不需要编写代码。

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 EINVAL it 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中指定的值,或者当前的文件偏移量是不合适的。