Kecepatan kartu SD di ESP32 - kenapa berhenti di 20 MHz

Penampil foto ESP32 saya membaca setiap foto dari kartu SD, jadi saya ingin tahu seberapa cepat kartunya sebenarnya. Kebanyakan halaman hanya menyebut kelas kartu atau clock SPI. Saya mengukur apa yang benar-benar didapat ESP32 dengan library Arduino SD, dan menemukan dua batas yang tidak terlihat jelas.
Perangkatnya
- ESP32 DOIT DevKit V1 (ESP32-WROOM-32), Arduino core untuk ESP32 3.3.
- Modul kartu SD di bus SPI sendiri (HSPI). SCK 14, MOSI 13, MISO 27, CS 15, dengan kabel jumper di breadboard.
- Library Arduino
SD, kartu berformat FAT32.
Batas 1 - 25 MHz tidak bisa didapat
Kartu SD di mode SPI dirancang sampai 25 MHz, jadi itu yang saya minta.
SD.begin(PIN_SD_CS, sdSpi, 25000000);
Busnya berjalan di 20 MHz. Ada dua hal yang bertemu di sini.
- Library SD membatasi clock di 25 MHz. Di file
sd_diskio.cppmilik core, sebuah komentar menyebutnya “SD spec maximum for non-UHS cards”. - ESP32 membuat clock SPI dengan membagi clock bus 80 MHz dengan bilangan bulat. Pilihan teratas adalah 80 / 2 = 40 MHz, 80 / 3 = 26,7 MHz dan 80 / 4 = 20 MHz. 26,7 melewati batas, jadi pilihan berikutnya 20 MHz.
Jadi dengan library ini, 20 MHz adalah batas sebenarnya. Kecepatan mentah busnya 20 MHz / 8 = 2,5 MB/s.
Hasil pengukuran
Saya menulis 512 KB ke kartu, membacanya lagi dan memeriksa setiap byte. Hanya waktu di dalam fungsi file yang dihitung, bukan waktu menyiapkan data uji.
uint32_t t0 = micros();
size_t n = f.write(buf, chunk); // same for f.read(buf, chunk)
busy += micros() - t0;
Hasil di 20 MHz.
| Ukuran blok | Tulis | Baca |
|---|---|---|
| 4 KB | 1,3 MB/s | 1,37 MB/s |
| 16 KB | 1,7 MB/s | 1,37 MB/s |
| 32 KB | 1,7 MB/s | 1,37 MB/s |
Batas 2 - blok baca yang lebih besar tidak membantu
Menulis jadi lebih cepat dengan blok yang lebih besar, sampai sekitar 16 KB. Membaca tetap di 1,37 MB/s, berapa pun ukuran bloknya. Itu 55% dari 2,5 MB/s yang bisa dibawa bus.
Penyebabnya ada di cara library SD membaca. Library memindahkan setiap sektor 512 byte dengan CPU, tanpa DMA, dan menunggu kartu di antara sektor. Blok yang lebih besar hanya berarti lebih banyak sektor berturut-turut, masing-masing dengan waktu tunggu yang sama. Bus diam selama menunggu.
Dua hal lain yang saya lihat.
- Penulisan kadang berhenti 10 sampai 250 ms. Itu kartu yang sedang menghapus di dalamnya. Untuk logging, simpan data di buffer supaya jeda itu tidak menghilangkan apa pun.
- Di kartu SDHC 4 GB saya, file yang disalin dari PC terbaca lebih lambat (sekitar 0,75–0,8 MB/s) daripada file yang baru ditulis ESP32 (1,37 MB/s). Itu berasal dari dalam kartu, bukan dari ESP32. Kartu yang lebih cepat (kelas A1 atau U3) mungkin lebih baik.
Cara supaya lebih cepat
- Tulis dengan blok 16 KB atau lebih. Gratis, dan memberi sekitar 30% kecepatan tulis lebih dari 4 KB.
- Pakai driver SD-over-SPI dari ESP-IDF, bukan yang dari Arduino. Driver itu bisa memakai DMA, jadi seharusnya lebih dekat ke batas 2,5 MB/s. Saya belum mengukurnya.
- Pakai bus 4-bit milik kartu SD sendiri (SDMMC), bukan SPI. ESP32 punya hardware-nya, dan jauh lebih cepat. Tapi pin tetapnya termasuk GPIO2 dan GPIO12, yang merupakan pin strapping. Terutama GPIO12 bisa membuat papan tidak mau menyala, seperti yang saya jelaskan di ESP32 tidak mau menyala dengan kartu SD di GPIO12.
Catatan soal kabel
Ini proyek akhir pekan di breadboard, dengan kabel jumper. Kabel itu tidak membatasi angka-angka di atas. Bus sudah berjalan di batas library, 20 MHz, dan setiap byte terbaca kembali dengan benar.
Kabel itu akan membatasi kalau kamu ingin lebih cepat. Bus SDMMC berjalan di 20–40 MHz di enam jalur sekaligus, dan di situlah kabel panjang yang lepas menimbulkan error. Saya melihat hal yang sama dengan layar di proyek ini. Di SPI 80 MHz muncul garis terpotong di breadboard saya, jadi saya tetap di 40 MHz.
Jadi kalau kamu membuat PCB sungguhan untuk mengejar kecepatan, beberapa hal sederhana paling membantu.
- Jalur pendek, beberapa sentimeter, di atas ground plane yang utuh.
- Resistor seri kecil (sekitar 22–33 Ω) dekat ESP32 di jalur clock dan data, untuk meredam ringing.
- Pull-up 10 kΩ di jalur command dan data kartu, dan kapasitor decoupling tepat di sebelah kartu.
Impedansi terkontrol tidak diperlukan di kecepatan ini. Itu penting untuk sinyal yang jauh lebih cepat atau jalur yang jauh lebih panjang.
Format kartu
Library Arduino SD membaca FAT32 (dan FAT16). Kartu di atas 32 GB biasanya diformat exFAT, yang tidak didukung secara bawaan. Format ulang ke FAT32 sebelum dipakai.