web-dev-qa-db-ja.com

mtdブロックデバイスに書き込む

MTDブロックデバイスを使用してNANDフラッシュメモリに書き込もうとしていますが、すべてがわかりません。

私が読んだように ここ

  • mtdblockNは読み取り専用ブロックデバイスNです
  • mtdNは読み取り/書き込み文字デバイスNです
  • mtdNroは読み取り専用のcharデバイスNです

しかし、Cで単純なwriteを使用してパーティションに直接バイトを書き込みたいのですが、それがどのように機能するのかわかりません(最初に書き込みたいセクターを消去する必要があることを読んだことがあります)。

どのデバイスを使用する必要があり、このデバイスに書き込む方法は?

11
marmottus

メモリテクノロジデバイスとの間の読み取りと書き込みは、他のタイプのIOとそれほど違いはありません。ただし、書き込む前にセクターを消去する必要があります(ブロックの消去)。

自分で物事を簡単にするために、mtd-utils(消去、読み取り、書き込み用にそれぞれ_flash_erase_、nanddumpnandwriteなど)を必要なく使用できます。コードを書くため。

ただし、実際に実行したい場合は、ここに例を示します。すべての詳細をそこに記載しているので、必ずすべてのコメントを読んでください。

_#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で指定された値、または現在のファイルオフセットのいずれかが適切に配置されていません。

16
Mike