c - 在 mtd block 设备上写入

标签 c linux embedded flash-memory

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

当我读到here

  • mtdblockN为只读 block 设备N
  • mtdN为读写字符设备N
  • mtdNro为只读字符设备N

但我想在 C 中使用简单的 write 直接将字节写入分区,但我不明白它是如何工作的(我读到一些东西,我首先必须删除我想要的扇区写上)。

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

最佳答案

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

为了使事情简单化,您总是可以使用 mtd-utils(例如 flash_erasenanddumpnandwrite,用于删除、读取和写入)而无需编写代码。

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

#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 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.

关于c - 在 mtd block 设备上写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15336285/

相关文章:

c - 适用于应用程序的可移植 Linux 环境

arm - GPIO 中断请求 : Falling and Rising edge detection

c - 指向 const 结构的指针,成员还能被修改吗?

c - 代码中的 dbx WUA 错误跟踪

regex - "11th to 16th letter"的正则表达式

embedded - 在不输入 PIN 的情况下,可以从受 PIN 保护的 SIM 中读取哪些数据/元数据?

c++ - 用于嵌入式设备的轻量级 smbclient 模拟

c++ - APNS。 C++ : extract Identifier from error responce

c - 如何在 Minix 中用 <minix/mthread.h> 编译?

c - 定时器和信号中的问题