Odczyt i zapis danych na chipach flash dla mikrokontrolerów

Gdy w projekcie potrzebny jest nośnik danych pozwalający mikrokontrolerowi czytać i zapisywać dane możemy sięgnąć po karty SD, czy zazwyczaj będące lepszy wyborem chipy Flash.

W wielu przykładach dla Arduino, np. przy odtwarzaniu plików audio, pojawia się karta SD obsługiwana przez prosty adapter. Łatwo dostępna i łatwa w użyciu. Niemniej gdy projektowane są produkcyjne układy karta SD nie zawsze jest dobrym wyborem - szczególnie gdy użytkownik nie będzie miał do niej dostępu. W takich przypadkach stosuje się chipy flash lutowane bezpośrednio na PCB. Unika się mechanicznego połączenia, a program na mikrokontrolerze może być mniejszy bo nie musi obsługiwać systemu plików karty SD. Za chip o pojemności 16 MB zapłacimy niecałe 5 zł, a do jego wykorzystania potrzebny będzie interfejs SPI.

Podłączając taki chip do Arduino można też wgrać firmware/dane dla jakiegoś urządzenia (np. BIOS starego laptopa), a następnie przenieść chip do tego urządzenia.

WinBond flash chip

Chipy Flash WinBond

Firma WinBond produkuje dość popularne chipy flash, które znaleźć możemy w różnych urządzeniach. Modele o różnej pojemności dostępne są w sklepach z elektroniką, np. na piekarz.pl. Jako że są to obudowy SOP08 bezpośrednie użycie z np. płytką stykową będzie bardzo trudne jeżeli nie niemożliwe. Problem rozwiązać może przejściówka.

Do obsługi tych chipów na Arduino, ESP32 i paru innych mikrokontrolerach użyć można biblioteki SPIFlash. Oferuje ona odczyt/zapis i diagnostykę chipów. Pamięci Flash same z siebie nie mają systemu plików. Struktura podzielona jest na strony (pages) o określonym rozmiarze, na których można zapisywać i odczytywać dane. Zamiast pliku audio na karcie SD na chipie flash dane audio zapisane byłyby w postaci numerycznej gotowej do wrzucenia na DACa bezpośrednio po odczytaniu.

Chipy WinBond używają interfejsu SPI. Dodatkowo dwa piny - blokady zapisu i dostępu. Pracują na napięciu 3.3V i w przypadku 5V Arduino co najmniej zasilanie podłączone do chipa powinny być 3.3V. Pinout wygląda następująco (sprawdź dokumentację dla konkretnego modelu):

WinBond flash chip pinout

W uproszczeniu tak mógłby wyglądać zapis danych bajt po bajcie. Każda strona ma określony rozmiar więc trzeba w pętli zapisywać dane w kolejnych komórkach strony, a gdy pętla dojdzie do ostatniej komórki - przejść do kolejnej strony.

const unsigned char sample[] = {
... audio data here
};

#include<SPIFlash.h>
SPIFlash flash;


void setup() {
  Serial.begin(115200);
  
  flash.begin();

  int j;
  int page = 0;
  int offset = 0;
  flash.eraseChip();
  for (j = 0; j < sizeof(sample); j++ ) {
      flash.writeByte(page, offset, sample[j]);
      offset++;
      if (offset >= 255) {
        page++;
        offset = 0;
      }
  }
  Serial.print(page);
  Serial.print('-');
  Serial.print(offset);
}

void loop() {
}

Ten przykład zawiera dane audio w tablicy sample[], kompilowanej i wrzucanej na mikrokontroler - więc nie może być zbyt duża. W bardziej praktycznej implementacji dane byłyby wysyłane np. poprzez UART na mikrokontroler, który zapisywałby je w pamięci flash.

W podobny sposób można odczytywać dane. Ekstremalnie prosty odtwarzacz audio wyglądałby tak:

#include<SPIFlash.h>
SPIFlash flash;

void setup() {
  flash.begin();
  int maxPages = 1000; // hardcoded for this example

  uint16_t page = 0;
  uint8_t offset = 0;
  for (offset = 0; offset < 255; offset++) {
      uint8_t data = flash.readByte(page, offset);
      dacWrite(25, data); // ESP32 Wroom DAC1 on pin 25
      delayMicroseconds(5); // 1/sample rate - read time
      if (offset >= 254 && page <= maxPages) {
        page++;
        offset = 0;
      }
  }
}

void loop() {
}

W pętli dane są czytane bajt po bajcie z tą samą iteracją po stronach flasha. Zhardkodowany jest rozmiar danych jak i próbkowanie (oraz czas odczytu danych z flasha). Mając całą tablicę z danymi audio wysyłane byłyby na DACa z opóźnieniem równym 1/próbkowanie (8, 16, 32kHz...). Gdy odczytujemy dane zajmuje to na tyle dużo czasu (kilkanaście/dziesiąt mikrosekund) że trzeba to uwzględnić w opóźnieniu pętli audio. Oczywiście jeżeli odczyt zajmie niespodziewanie dużo/mało czasu to taki odtwarzacz zacznie odtwarzać audio z nieoczekiwanymi efektami powolnego lub bardzo szybkiego tempa.

Powiązane artykuły

RkBlog

Elektronika i Python, 7 August 2017

Comment article
Comment article RkBlog main page Search RSS Contact