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