我正在尝试使用 MTD 块设备在 NAND 闪存上写入,但我并不了解所有内容。
正如我在这里读到的
mtdblockN
是只读块设备 NmtdN
是读/写字符设备 NmtdNro
是只读字符设备 N
但是我想使用简单write
的 C 语言直接将字节写入分区,但我不明白它是如何工作的(我读到我首先必须擦除要写入的扇区)。
我应该使用哪种设备以及如何在此设备上书写?
我正在尝试使用 MTD 块设备在 NAND 闪存上写入,但我并不了解所有内容。
正如我在这里读到的
mtdblockN
是只读块设备 NmtdN
是读/写字符设备 NmtdNro
是只读字符设备 N但是我想使用简单write
的 C 语言直接将字节写入分区,但我不明白它是如何工作的(我读到我首先必须擦除要写入的扇区)。
我应该使用哪种设备以及如何在此设备上书写?
从/向内存技术设备读取和写入与任何其他类型的 IO 并没有什么不同,除了在您写入之前您需要擦除扇区(擦除块)
为了使事情变得简单,您始终可以只使用 mtd-utils(例如flash_erase
,nanddump
和nandwrite
, 分别用于擦除、读取和写入)而无需编写代码。
但是,如果您确实想务实地这样做,这里有一个示例,请务必阅读所有评论,因为我将所有详细信息都放在那里:
#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;
}
这样做的好处是,由于您可以像在其他设备上一样使用标准工具,因此很容易理解write()
、open()
和read()
做什么以及对它们的期望。
例如,如果在使用时write()
你得到EINVAL
它的值可能意味着:
fd 附着在不适合书写的物体上;或者文件是使用 O_DIRECT 标志打开的,并且 buf 中指定的地址、count 中指定的值或当前文件偏移量未适当对齐。