【问题标题】:Getting EINVAL when trying to write to mtd device尝试写入 mtd 设备时获取 EINVAL
【发布时间】:2023-03-11 02:50:01
【问题描述】:

我指的是answer 中的代码。 我添加了错误处理。 open() 擦除和 read() 都执行没有错误,我读取的 20 个字节都是 0xff。 但是,当尝试从 data[] 数组写入 20 个字节时,我从 write() 函数中得到了一个 EINVAL 错误代码。 问题的原因可能是什么?我在尝试写之前确实擦除了内存...

【问题讨论】:

  • 您能否提供更多有关您尝试在其上执行此操作的系统的信息?
  • 这是一个定制板上的 linux 内核 3.6.9,带有 ARM Cortex-A5 和 128MB 的 NAND 闪存。
  • 该答案解释了EINVAL 的可能原因 - 您消除了所有这些原因吗?

标签: c linux embedded embedded-linux


【解决方案1】:

我见过你的original post。 最近遇到同样的问题,发现写大小很重要。

mtd_info_t(struct mtd_info_user) 有一个名为 writesize 的变量 (参考:https://elixir.bootlin.com/linux/v3.2/source/include/mtd/mtd-abi.h#L125

struct mtd_info_user {
    __u8 type;
    __u32 flags;
    __u32 size; /* Total size of the MTD */
    __u32 erasesize;
    __u32 writesize;
    __u32 oobsize;  /* Amount of OOB data per block (e.g. 16) */
    __u64 padding;  /* Old obsolete field; do not use */
};

写入 mtd 时,应注意 writesize

#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>

int main(){
    mtd_info_t mtd_info;           // the MTD structure
    erase_info_t ei;               // the erase block structure
    int i;

    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(hex) bytes\nMTD erase size: %x(hex) bytes\nMTD write size: %x(hex) bytes\n",
        mtd_info.type, mtd_info.size, mtd_info.erasesize, mtd_info.writesize);

    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]);

    /**********************************************************
     *   important part!                                      *
     *   notice the size of data array is mtd_info.writesize  *
     **********************************************************/
    uint32_t write_size = mtd_info.writesize;
    unsigned char data[write_size];//write 0
    bzero(data, write_size);

    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;
}

希望对你有帮助

【讨论】:

    【解决方案2】:

    来自 ./drivers/mtd/nand/nand_base.c

    #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0)
    
    This is the check performed by driver:
    
    /* Reject writes, which are not page aligned */
    if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
        pr_notice("%s: attempt to write non page aligned data\n",__func__);
    return -EINVAL;
    }
    

    你开始写入的地址和你正在写入的缓冲区的长度都必须满足宏条件(是子页面大小的倍数)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-28
      • 1970-01-01
      • 2011-12-27
      相关资源
      最近更新 更多