2013-03-11 7 views
9

Sto provando a scrivere su una memoria flash NAND utilizzando il dispositivo blocco MTD ma non capisco tutto.Scrivere su un dispositivo blocco MDD

Leggendo here

  • mtdblockN è l'unico dispositivo a blocchi di lettura N
  • mtdN è la lettura/scrittura del dispositivo char N
  • mtdNro è la lettura dispositivo unico char N

Ma mi piacerebbe scrivere direttamente byte alla partizione usando un semplice write in C e non capisco come funziona (leggo in qualche modo che devo prima cancellare i settori su cui voglio scrivere).

Quale dispositivo dovrei usare e come scrivere su questo dispositivo?

+0

Non sono sicuro se questo aiuta, ma avete visto gli esempi forniti qui: [link] (http://www.linuxforu.com/2012/01/working-with-mtd-devices/), sezione "Accesso agli MTD dalle applicazioni" – Habi

+0

Sì, l'ho visto ;-) Al momento sto provandolo – marmottus

+0

I dispositivi MTD consentono di accedere al flash raw. Se si desidera creare, modificare, rimuovere file e così via. Questo dovrebbe essere fatto su un filesystem (yaffs2 nel tuo caso). L'accesso al flash tramite dispositivi MTD non fornisce tale livello. – Rerito

risposta

12

Lettura e scrittura da/verso dispositivi di tecnologia di memoria non è poi così diverso da qualsiasi altro tipo di IO, con l'eccezione che prima di scrivere è necessario cancellare il settore (cancellare blocco)

Per rendere le cose semplici su di te puoi sempre usare semplicemente mtd-utils (come flash_erase, nanddump e nandwrite, per cancellare, leggere e scrivere rispettivamente) senza la necessità di scrivere codice.

Tuttavia, se si vuole farlo in modo pragmatico, ecco un esempio, assicurarsi di leggere tutti i commenti che come ho messo tutti i dettagli in là:

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

La cosa bella di questo è perché si può usa gli strumenti di utilità standard come fai da altri dispositivi, facilita la comprensione di cosa fanno write(), open() e read() e cosa aspettarsi da loro.

Per esempio, se durante l'utilizzo write() hai un valore EINVAL potrebbe significare:

fd è collegato a un oggetto che non è adatto per la scrittura; oppure il file è stato aperto con il flag O_DIRECT e l'indirizzo specificato in buf, il valore specificato in count, o l'offset del file corrente non è adeguatamente allineato.

+0

OK questo è quello che ho fatto in base al link dato da Habi e funziona! Ma devo allineare le dimensioni della scrittura al settore successivo altrimenti ho un avvertimento sul kernel :-) – marmottus

+0

E un'altra domanda: come sono gestiti i blocchi danneggiati in questo caso?Fai un controllo di integrità mentale, ma come fa il kernel a gestire blocchi morti che non sono più scrivibili? – marmottus

+0

@marmottus: per i settori che cambiano, è abbastanza facile da ottenere, è sufficiente modificare il comando 'lseek' e utilizzare la dimensione di cancellazione dalla struttura mtd_info. I blocchi danneggiati (su flash non elaborati) sono sotto la tua responsabilità ... la maggior parte dei chip flash implementano una sorta di FTL (strato di traduzione flash) che si occupa di BBM e di livellamento degli articoli per te, che è tipicamente fatto in hardware, è necessario consultare le specifiche per il tuo flash NAND da sapere per certo – Mike

Problemi correlati