2013-03-11 15 views
9

Ich versuche, auf einem NAND-Flash-Speicher mit MTD-Block-Gerät zu schreiben, aber ich verstehe nicht alles.Schreiben auf ein MTD-Block-Gerät

Wie ich gelesen here

  • mtdblockN das Lesen nur Blockgerät N
  • mtdN die Lese-/char Gerät schreiben N
  • mtdNro wird die Nur-Lese-char Vorrichtung N

Aber ich möchte direkt Bytes in die Partition schreiben mit einem einfachen write in C und ich verstehe nicht wie es funktioniert (ich habe gelesen, dass ich zuerst die Sektoren löschen muss, auf die ich schreiben möchte).

Welches Gerät soll ich verwenden und wie schreibe ich auf diesem Gerät?

+0

Nicht sicher, ob das hilft, aber haben Sie die Beispiele hier bereitgestellten gesehen: [link] (http://www.linuxforu.com/2012/01/working-with-mtd-devices/), Abschnitt "Auf MTDs von Anwendungen zugreifen" – Habi

+0

Ja, ich habe es gesehen ;-) Ich probiere es gerade aus – marmottus

+0

MTD-Geräte geben Ihnen Zugriff auf den rohen Flash. Wenn Sie Dateien erstellen, bearbeiten oder entfernen möchten. Dies sollte über ein Dateisystem erfolgen (yaffs2 in Ihrem Fall). Zugriff auf den Flash über MTD-Geräte bietet Ihnen keine solche Schicht. – Rerito

Antwort

12

Lese und vom/zum Speichertechnologie Geräten Schreiben ist nicht wirklich alles, was anders als jede andere Art von IO, mit der Ausnahme, dass, bevor Sie schreiben Sie den Sektor löschen müssen (Löschblock)

zu machen Dinge einfach auf sich selbst können Sie immer nur die Mtd-Utils (wie flash_erase, nanddump und nandwrite, zum Löschen, Lesen und Schreiben jeweils), ohne die Notwendigkeit zum Schreiben von Code.

Allerdings, wenn Sie es nicht möchten, pragmatisch tun, hier ist ein Beispiel, stellen Sie sicher, dass alle Kommentare zu lesen, wie ich alle Details in dort setzen:

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

Das schöne an dieser seit ist, können Sie Verwenden Sie die Standards utils wie Sie von anderen Geräten, es macht es leicht zu verstehen, was write(), open() und read() tun und was von ihnen zu erwarten ist.

Zum Beispiel, wenn während write() verwenden Sie einen Wert von EINVAL bekommen könnte es bedeuten:

fd an ein Objekt angebracht ist, die zum Schreiben ungeeignet ist; oder die Datei wurde mit dem O_DIRECT-Flag geöffnet und entweder die in BUF angegebene Adresse, der in count angegebene Wert oder der aktuelle Dateioffset sind nicht entsprechend ausgerichtet.

+0

OK, das ist, was ich nach dem Link von Habi gegeben habe und es funktioniert! Aber ich muss die Schreibgröße an den nächsten Sektor anpassen, sonst habe ich eine Kernelwarnung :-) – marmottus

+0

Und noch eine Frage: Wie werden in diesem Fall schlechte Blöcke gehandhabt?Sie machen einen Plausibilitätscheck, aber wie geht der Kernel mit toten Blöcken um, die nicht mehr beschreibbar sind? – marmottus

+0

@marmottus - für die sich ändernden Sektoren, das ist ziemlich einfach zu bekommen, Sie müssen nur den 'lseek' Befehl ändern und die Löschgröße aus der mtd_info Struktur verwenden. Schlechte Blöcke (auf rohen Flash) sind Ihre Verantwortung zu bewältigen ... die meisten Flash-Chips implementieren eine Art von FTL (Flash Translation Layer), die BBM und Warennivellierung für Sie kümmert, das ist in der Regel in Hardware getan, müssen Sie konsultieren die Spezifikation für Ihren NAND-Blitz, um sicher zu wissen – Mike