2013-03-11 12 views
9

Próbuję pisać na pamięci flash NAND za pomocą urządzenia blokowego MTD, ale nie wszystko rozumiem.Napisz na urządzeniu bloku mtd

Jak czytam here

  • mtdblockN jest tylko do odczytu urządzenie blok N
  • mtdN jest do odczytu/zapisu urządzenia char N
  • mtdNro jest czytać urządzenie tylko char N

Ale chciałbym bezpośrednio napisać bajty do partycji za pomocą prostego write w C i nie rozumiem jak działa (czytałem, że najpierw muszę wymazać sektory, które chcę napisać).

Z jakiego urządzenia mam korzystać i jak pisać na tym urządzeniu?

+0

Nie wiem, czy to pomoże, ale widziałeś przykłady podane tutaj: [link] (http://www.linuxforu.com/2012/01/working-with-mtd-devices/) sekcja "Dostęp do MTD z aplikacji" – Habi

+0

Tak, widziałem to ;-) Obecnie próbuję to – marmottus

+0

Urządzenia MTD dają dostęp do surowego flasha. Jeśli chcesz tworzyć, edytować, usuwać pliki i tak dalej. Powinno to zostać dokonane za pomocą systemu plików (yaffs2 w twoim przypadku). Dostęp do lampy błyskowej za pośrednictwem urządzeń MTD nie zapewnia takiej warstwy. – Rerito

Odpowiedz

12

Odczyt i zapis z/do urządzeń technologicznych pamięć nie jest tak naprawdę wszystko, co różni się od każdego innego rodzaju IO, z tą różnicą, że zanim napiszesz trzeba usunąć sektora (kasowanie bloku)

Aby uczynić rzeczy proste na sobie zawsze możesz po prostu użyć mtd-utils (takich jak flash_erase, nanddump i nandwrite, odpowiednio do kasowania, czytania i pisania) bez potrzeby pisania kodu.

Jednak jeśli chcesz zrobić to pragmatycznie, oto przykład, upewnij się, aby przeczytać wszystkie komentarze, jak umieścić wszystkie szczegóły w tam:

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

Dobrą rzeczą jest to, ponieważ można używaj standardów, jak robisz to z innych urządzeń, ułatwia to zrozumienie, czego możesz się spodziewać i czego się od nich oczekuje.

Na przykład jeśli podczas korzystania write() masz wartość EINVAL może to oznaczać:

fd jest dołączony do obiektu, który nie nadaje się do pisania; lub plik został otwarty przy pomocy flagi O_DIRECT, a adres podany w buf, wartość określona w count lub aktualna offset pliku nie jest odpowiednio wyrównana.

+0

OK, tak zrobiłem zgodnie z linkiem podanym przez Habi i działa! Ale muszę wyrównać rozmiar czcionki do następnego sektora, w przeciwnym razie mam ostrzeżenie jądra :-) – marmottus

+0

I kolejne pytanie: W jaki sposób są w tym przypadku obsługiwane złe bloki?Robisz kontrolę poprawności, ale jak kernel radzi sobie z martwymi blokami, które są już nieopisane? – marmottus

+0

@marmottus - w przypadku zmieniających się sektorów, które łatwo można ominąć, wystarczy zmodyfikować polecenie 'lseek' i użyć rozmiaru wymazywania ze struktury mtd_info. Złe bloki (na surowym flashu) to twój obowiązek radzenia sobie z ... większość flashowych układów implementuje coś w rodzaju FTL (flash translation layer), która zajmuje się BBM i levelowaniem dla ciebie, co zwykle robisz w sprzęcie, musisz się skonsultować specyfikacja dla twojego flasha NAND, aby wiedzieć na pewno – Mike