我正在尝试使用MTD块设备写入NAND闪存,但我不明白所有内容。在mtd块设备上写入
正如我读here
mtdblockN
是只读块设备NmtdN
是读/写炭设备NmtdNro
是只读炭设备N
但我想用C中的一个简单的write
直接写入分区的字节,我不明白它有效(我读了一些我首先必须删除我想写的部门)。
应该使用哪种设备以及如何在此设备上书写?
我正在尝试使用MTD块设备写入NAND闪存,但我不明白所有内容。在mtd块设备上写入
正如我读here
mtdblockN
是只读块设备NmtdN
是读/写炭设备NmtdNro
是只读炭设备N但我想用C中的一个简单的write
直接写入分区的字节,我不明白它有效(我读了一些我首先必须删除我想写的部门)。
应该使用哪种设备以及如何在此设备上书写?
读取和/写入到内存技术设备是不是真的那么比任何其他类型的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;
}
关于这样做的好处是,因为你可以像使用其他设备一样使用标准utils,可以轻松了解write()
,open()
和read()
做什么以及期望从中获得什么。
例如,如果在使用write()
你得到了EINVAL
值,这可能意味着:
fd被连接到一个对象,它是不适合写作;或者使用O_DIRECT标志打开文件,并且buf中指定的地址,count中指定的值或当前文件偏移量不适当对齐。
好吧,这就是我根据Habi给出的链接所做的工作!但我必须将写入大小对齐到下一个扇区,否则我有内核警告:-) – marmottus 2013-03-11 14:20:23
另一个问题:在这种情况下如何处理坏块?你做了一个完整的检查,但内核是如何处理不可写的死区? – marmottus 2013-03-11 14:21:49
@marmottus - 对于不断变化的扇区,这很容易实现,您只需修改'lseek'命令并使用mtd_info结构中的擦除大小即可。坏块(在原始闪存上)是您的责任......大多数闪存芯片实现某种类型的FTL(闪存转换层),它负责为您提供BBM和ware平衡,通常用硬件完成,您需要咨询你的NAND闪存的规格肯定知道 – Mike 2013-03-11 14:26:28
不知道这是否会有所帮助,但你见过在这里提供的例子:[链接](http://www.linuxforu.com/2012/01/working-with-mtd-devices/) “从应用程序访问MTD”部分 – Habi 2013-03-11 10:55:16
是的,我看到了;-)我正在尝试 – marmottus 2013-03-11 10:59:25
MTD设备可让您访问原始Flash。如果你想创建,编辑,删除文件等。这应该通过一个文件系统(在你的情况yaffs2)。通过MTD设备访问闪存不会为您提供此类图层。 – Rerito 2013-03-11 11:10:24