Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
MK4001MTD-USB-Bridge — Firmware RP2040 che collega un microdrive SDIO Toshiba MK4001MTD da 0,85" come dispositivo di archiviazione di massa USB, implementando l'intero stack di protocollo SDIO-ATA da zero con letture/scritture accelerate tramite PIO e recupero dei settori danneggiati. | Kitploit
Strumenti/GitHubGitHub/will127534/mk4001mtd-usb-bridge
Sicurezza Sistemi EmbeddedReverse EngineeringRecupero DatiHacking HardwareSicurezza HardwareSicurezza Hardware e IoTAnalisi del Firmware
GitHubwill127534/mk4001mtd-usb-bridge

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

MK4001MTD-USB-Bridge

Firmware RP2040 che collega un microdrive SDIO Toshiba MK4001MTD da 0,85" come dispositivo di archiviazione di massa USB, implementando l'intero stack di protocollo SDIO-ATA da zero con letture/scritture accelerate tramite PIO e recupero dei settori danneggiati.

Vedi Repository
421252 mesi faRevisionato da Kitploit

Ponte USB MK4001MTD

Firmware RP2040 Pico che trasforma un microdrive Toshiba MK4001MTD da 0,85" SDIO in un dispositivo di archiviazione di massa USB. _DSC1170 _DSC1354

L'MK4001MTD è un Microdrive da 4 GB originariamente utilizzato nel telefono musicale Nokia N91 e in alcuni altri dispositivi, come lettori MP3 o chiavette USB, quando la memoria flash era ancora piuttosto costosa.

Potreste aver visto introduzioni che affermano che questo drive utilizza il protocollo MMC, ma in realtà è errato. Ho indagato per un po': ho provato a costruire un lettore di schede MMCplus a 8 bit e testato diversi lettori SD/MMC senza successo. Come ultima risorsa, ho acquistato un Nokia N91 per catturare tracce logiche e confermare quale protocollo utilizza effettivamente.

Ecco la foto mentre cercavo di usarlo con la mia scheda lettore 8bit-MMCPlus, e si è scoperto che non è MMC :( _DSC0484

Quindi ho finito per procurarmi un N91 per raccogliere tracce: _DSC1093 _DSC1131

A differenza dei microdrive standard ATA/CF, utilizza un'interfaccia SDIO con comandi ATA incapsulati attraverso CMD52/CMD53. Nessun driver esistente supporta questo protocollo, quindi questo firmware implementa l'intero stack da zero.

Questo mi ha sorpreso, perché esiste uno standard SDIO-to-ATA chiamato CE-ATA. Ma se si guarda attentamente alla cronologia dei rilasci, CE-ATA è arrivato dopo questo drive. Di conseguenza, questo drive si basa interamente su comandi SDIO e CE-ATA non è disponibile. CE-ATA ha due nuovi comandi CMD60/CMD61 e utilizza CMD12/39, ma dalle tracce si vede che non ne sta usando nessuno.

Il secondo aspetto hardware da menzionare è che un'altra disinformazione in circolazione—che afferma sia una scheda MMCPlus a 8 bit—non solo è falsa, ma anche il pinout non segue lo standard MMC. È possibile trovare il manuale di servizio del Nokia N91 con un po' di documentazione sul pinout: mentre la numerazione dei pin segue lo standard MMCPlus, la mappatura dei pin no. Questo è un dettaglio importante se lo si cabla da soli: usa lo stesso connettore MMC, ma la mappatura dei pin è diversa, maggiori dettagli nella sezione Hardware.

Infine, si noti che questo è co-sviluppato con Claude/OpenClaw. Ho raccolto le tracce logiche manualmente e ho allestito una stazione di test a ciclo chiuso per permettere a OpenClaw di iterare sullo sviluppo—analizzando le tracce e implementando funzionalità. La documentazione sarà per lo più scritta da Claude; aggiungerò anche le mie note inline. Ho anche letto e ricontrollato la documentazione personalmente, e dovrebbe essere affidabile e facile da seguire.

Per approfondimenti sull'analisi della traccia N91, si trova in /docs/N91_TRACE_ANALYSIS.md, ho anche inserito lì il manuale di servizio N91 insieme alle tracce logiche grezze.

Maggiori dettagli nel post del blog qui: https://www.willwhang.dev/Reading-MK4001MTD/
Vedetelo in azione qui: https://youtu.be/GC4xil3_Bbc

Stato

Archiviazione di massa USB completamente funzionante con letture/scritture accelerate da PIO e gestione dell'alimentazione in idle.

Come Funziona

Architettura

root@kitploit:~
Host USB ←→ USB MSC (TinyUSB) ←→ Livello ATA ←→ Livello SDIO (PIO) ←→ MK4001MTD

Il firmware ha quattro livelli:

  1. USB MSC (msc_device.c) — TinyUSB Mass Storage Class. Traduce SCSI READ(10)/WRITE(10) in operazioni sui settori ATA. Buffer EP da 32 KB, raggruppamento fino a 64 settori per trasferimento USB. L'I/O del drive è sovrapposto all'USB in entrambe le direzioni, come un vero bridge ATA-USB con disco cache: un prefetcher di lettura sequenziale recupera il chunk successivo mentre il precedente viene trasmesso all'host, e le scritture vengono bufferizzate e svuotate mentre l'USB riceve il pezzo successivo. Il dispositivo pubblicizza la propria cache di scrittura (Caching mode page, WCE=1 — gli host segnalano "Write cache: enabled" e inviano SYNCHRONIZE CACHE a fsync/unmount/suspend, che il firmware onora). Uno svuotamento in background fallito si manifesta come MEDIUM ERROR sulla successiva WRITE o SYNCHRONIZE CACHE; le scritture su settori noti come danneggiati seguono un percorso sincrono stretto.

  2. ATA-over-SDIO (ata_sdio.c) — Implementa i comandi ATA (IDENTIFY, READ SECTORS, WRITE SECTORS) scrivendo nei registri ATA mappati nello spazio degli indirizzi della funzione SDIO 1 tramite CMD52, e trasferendo i dati dei settori tramite CMD53. Logica di ritentamento a 3 livelli a livello CMD, dati e ATA.

  3. PIO SDIO (sdio_pio.c, sdio.pio) — SDIO accelerato via hardware utilizzando la periferica PIO dell'RP2040 (bus a 4 bit a 10 MHz, 4 cicli PIO per bit con sincronizzatori di ingresso bypassati). Tre programmi PIO condividono una singola macchina a stati mediante swapping dinamico dei programmi:

    • CMD tx/rx (24 istruzioni) — invia comandi SDIO e riceve risposte
    • DAT read (12 istruzioni) — legge blocchi dati dal bus DAT a 4 bit tramite DMA byte-swap (nessun repack della CPU); la CRC del blocco N viene verificata mentre il blocco N+1 scorre
    • DAT write (14 istruzioni) — scrive blocchi dati sul bus DAT a 4 bit tramite DMA, con ricezione dello stato CRC integrata e busy-wait; il flusso di nibble del blocco N+1 viene costruito mentre il blocco N viene trasferito
  4. Pin/Power () — Inizializzazione GPIO e controllo alimentazione HDD. Tutte le comunicazioni SDIO utilizzano PIO.

Note umane: È interessante notare che Claude era molto riluttante a implementare SDIO in PIO, e molti cicli di sviluppo sono stati sprecati in continui passaggi avanti e indietro tra PIO e bit-banging.

Il Protocollo SDIO-ATA

L'MK4001MTD si presenta come una scheda SDIO con una funzione I/O. L'inizializzazione standard di una scheda SDIO (CMD5/CMD3/CMD7) imposta il bus, quindi i registri ATA vengono acceduti tramite comandi SDIO:

Accesso ai registri (CMD52): Ogni registro ATA è mappato a un indirizzo della funzione 1:

Trasferimento dati (CMD53): I dati dei settori vengono trasferiti emettendo CMD53 in modalità blocco con destinazione del registro DATA (indirizzo 0x00). Per letture multi-settore, un singolo CMD53 con block_count=N trasferisce N × 512 byte in un'unica transazione multi-blocco SDIO.

Segnalazione interrupt: Il drive segnala la prontezza del settore asserendo un interrupt SDIO (bit INT_PENDING 1 nel registro CCCR 0x05). La lettura del registro ATA STATUS cancella l'interrupt.

Percorso di Lettura (PIO Multi-Blocco)

Per una lettura a 16 settori:

root@kitploit:~
1. Scrivere i registri ATA tramite PIO CMD52:
     SECCOUNT=16, LBA_LO/MID/HI, DEV/HEAD=0xE0, CMD=0x20

2. Polling dello STATUS tramite CMD52 finché DRQ (bit 3) non è impostato

3. Scambiare PIO con il programma di lettura DAT
4. Inviare CMD53: block_mode=1, fn=1, addr=0x0000, block_count=16

5. Lettura DAT PIO: per ciascuno dei 16 blocchi:
   a. Attendere il bit di start (tutte le linee DAT basse)
   b. DMA di 1024 nibble (512 byte) dal FIFO RX PIO al buffer
   c. Attendere che la SM finisca di clockare i nibble CRC+end (polling SM PC)
   d. Ripack dei nibble → byte in-place

6. Scambiare PIO di nuovo con il programma CMD

Percorso di Scrittura (PIO Multi-Blocco)

Per una scrittura a 16 settori:

root@kitploit:~
1. Scrivere i registri ATA tramite PIO CMD52:
     SECCOUNT=16, LBA, DEV/HEAD=0xE0, CMD=0x30

2. Polling dello STATUS tramite CMD52 finché DRQ (bit 3) non è impostato
   (STATUS 0xD8 = BSY+DRQ trattato come DRQ-ready, come da traccia N91)

3. Scambiare PIO con il programma di scrittura DAT
4. Inviare CMD53: block_mode=1, fn=1, addr=0x0000, block_count=16

5. Scrittura DAT PIO: per ciascuno dei 16 blocchi:
   a. Precalcolare CRC16-CCITT per linea DAT (4 CRC indipendenti)
   b. Costruire flusso di nibble: start(0x0) + dati(1024 nibble) + CRC(16) + end(0xF)
   c. DMA del flusso di nibble al FIFO TX PIO
   d. Il PIO clocka tutti i nibble, poi:
      - Commuta DAT in input
      - Clocka 16 cicli per lo stato CRC dalla scheda
      - Fa polling di DAT0 finché la scheda non rilascia il busy
      - Attiva IRQ 0 per segnalare il completamento del blocco

6. Scambiare PIO di nuovo con il programma CMD

Swapping dei Programmi PIO

Il PIO dell'RP2040 ha 32 slot di istruzioni per blocco. I nostri tre programmi totalizzano 55 istruzioni, quindi non possono coesistere. Invece, viene utilizzato un singolo SM0 su PIO0 e i programmi vengono scambiati scrivendo direttamente nella memoria delle istruzioni PIO:

root@kitploit:~
static void load_program_raw(const pio_program_t *program) {
    for (uint i = 0; i < program->length; i++)
        pio->instr_mem[FIXED_OFFSET + i] = program->instructions[i];
}

Questo bypassa l'allocatore pio_add_program/pio_remove_program dell'SDK. Lo scambio del programma richiede circa 1 µs. Ogni scambio è seguito da una reinizializzazione specifica del programma che imposta le mappature dei pin, la direzione di shift e il divisore di clock.

Gestione dell'Alimentazione

L'analisi delle tracce logiche del Nokia N91 rivela una gestione aggressiva dell'alimentazione:

  • Modalità idle: STANDBY IMMEDIATE (0xE0) ogni ~7,5 secondi, anche senza I/O. Ogni standby attiva una reinizializzazione SDIO completa (ritentativo CMD5 → CMD3 → CMD7 → configurazione CCCR). In una sessione idle sono stati osservati 28 cicli di standby.
  • Modalità attiva: Standby emesso tra raffiche di I/O (24 cicli durante le operazioni su file del drive USB).
  • Nessun altro comando di alimentazione (IDLE, SLEEP, CHECK POWER MODE) o accessi al registro di alimentazione CCCR sono stati osservati.

Il firmware replica questo comportamento con un timeout di idle configurabile:

root@kitploit:~
#define IDLE_STANDBY_MS 5000  // in main.c

Due percorsi attivano il power gating dell'HDD:

  1. Timeout idle (5 secondi) — il loop principale rileva nessuna attività I/O
  2. Sospensione USB — l'host sospende la porta USB

Entrambi i percorsi inviano ATA STANDBY IMMEDIATE (0xE0) per svuotare la cache di scrittura e parcheggiare le testine, quindi tagliano l'alimentazione tramite GP9.

Sequenza di riattivazione (innescata dalla prima READ/WRITE dopo il gate):

  1. Accendere l'HDD, attendere 500ms per il stabilizzarsi delle tensioni
  2. Reinizializzazione SDIO basata su PIO: CMD5 (OCR) → 10ms di attesa → CMD3 (RCA) → CMD7 (selezione)
  3. Passare al clock PIO veloce, configurare CCCR tramite CMD52 (bus a 4 bit, blocchi da 512B, abilitazione fn1)
  4. Polling della prontezza fn1 (bit IO_READY del CCCR 1)
  5. Polling dello stato DRDY in stile N91 per 30ms finché il drive non è pronto per ATA

Gestione dei Settori Danneggiati

Quando un trasferimento multi-settore incontra un settore danneggiato:

  1. La lettura del chunk fallisce → recupero errori (IO_ABORT + reset fn1, ~500ms)
  2. Ripiega su I/O per singolo settore per identificare con precisione il blocco malfunzionante
  3. Il livello ATA attende abbastanza a lungo per catturare i bit finali STATUS/ERROR invece di collassare il fallimento in un generico DRQ timeout
  4. Qualsiasi blocco non recuperato fallisce immediatamente il comando SCSI con MEDIUM ERROR (lettura: 03/11/00, scrittura: 03/0C/00)
  5. L'LBA del settore danneggiato viene memorizzato nella cache → le letture ripetute falliscono velocemente senza re-impattare il drive (protezione anti-hammer contro tempeste di ritentativi dell'host)
  6. Le scritture toccano sempre il supporto, secondo SBC — una scrittura riuscita su un LBA danneggiato in cache lo rimuove dalla cache, esattamente come un drive che cancella un settore in sospeso

Il punto 6 non è accademico: questo drive aveva un settore illeggibile di lunga data a LBA 1952 (READ: ST=0x51 ERR ERR=0x40 UNC). Una volta che il bridge ha permesso a una scrittura di raggiungerlo effettivamente, il drive ha riscritto il settore e da allora viene letto pulitamente:

root@kitploit:~
[ATA] FAST-RD: ST=0x51 ERR ERR=0x40 UNC LBA=1952
[MSC] BAD SECTOR read LBA=1952
[MSC] Bad sector LBA=1952 repaired by write

Compilazione

Prerequisiti

  • Raspberry Pi Pico SDK — standard, non modificato, fissato alla versione 2.2.0
  • Toolchain ARM (arm-none-eabi-gcc)
  • CMake

La versione dell'SDK è bloccata: se PICO_SDK_PATH è impostato (variabile d'ambiente o di CMake) viene utilizzato e la sua versione viene controllata rispetto al pin — una mancata corrispondenza fallisce la configurazione con istruzioni (si può sovrascrivere con -DMK4001_ALLOW_SDK_MISMATCH=ON). Senza alcun PICO_SDK_PATH, la versione fissata dell'SDK viene scaricata automaticamente da GitHub al momento della configurazione, quindi un semplice git clone && cmake && make è completamente riproducibile.

Il firmware necessita di un driver di classe TinyUSB MSC patchato (dati di senso applicazione preservati su errori di lettura/scrittura + una pagina di modalità di caching con WCE=1). Quel file è fornito in questo repo in lib/tinyusb_patched/msc_device.c — la compilazione lo compila automaticamente invece della copia dell'SDK, quindi non è mai necessaria alcuna modifica all'SDK. Il diff rispetto all'upstream TinyUSB (0.18.0, come fornito con pico-sdk 2.2.0) si trova in lib/tinyusb_patched/; il pin dell'SDK esiste proprio perché questo file fornito deve seguire il TinyUSB dell'SDK.

Compilazione e Flash

root@kitploit:~
cd /home/pi/mk4001_bridge/build
cmake ..
make -j4

sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
  -c "adapter speed 1000" -c "init" -c "reset halt" -c "sleep 200" \
  -c "program /home/pi/mk4001_bridge/build/mk4001_bridge.elf verify" \
  -c "reset run" -c "exit"

Cablaggio Hardware

Nota: GP0 e GP1 sono morti su questa specifica unità Pico. Tutte le assegnazioni dei pin SDIO sono spostate di +2.

Note umane: Claude aveva torto qui perché non si era reso conto che GP0 e GP1 venivano usati per il terminale UART nella sua configurazione di compilazione. Continuava a dimenticarselo, al punto che ho semplicemente spostato i GPIO SDIO fuori da quella UART.

HDD_PWR non è necessario. Non è necessario spegnere e riaccendere il drive per usarlo; è più una comodità di sviluppo per resettare l'HDD quando molte cose sono hard-coded. Detto questo, se si vuole risparmiare energia, si può usare quel segnale, ma può gestire un reset a caldo senza problemi.

Vedrete messaggi di debug sulla UART. Non passano attraverso USB-CDC perché era più facile per Claude impostare un collegamento di log UART-USB separato che non si disconnette o diventa instabile durante le prime fasi di sviluppo.

Il log UART riporta anche la temperatura del drive ogni 30 secondi mentre il drive è attivo ([TEMP] drive temperature: 29 C). Il sensore è stato scoperto decodificando il comando vendor Toshiba 0xC2 — l'N91 lo legge all'inizio di ogni sessione del drive per imporre i propri limiti di temperatura operativa dell'HDD. Dettagli in docs/N91_TRACE_ANALYSIS.md §4.

Ecco un esempio del log:

root@kitploit:~
========================================
  MK4001MTD USB Bridge v0.11
  SDIO-ATA → USB Mass Storage (PIO)
========================================

[MAIN] Pre-delay 5000ms...
[PIO] Init OK: clkdiv=3.12 (~10.0 MHz), CMD@0
[MAIN] Power cycling HDD...
[SDIO] HDD power OFF
[SDIO] HDD power ON
[MAIN] SDIO init (PIO)...
[SDIO] CMD5 ready (OCR=0x901F8000)
[SDIO] RCA=0x0001
[SDIO] fn1 ready (attempt 0)
[MAIN] ATA IDENTIFY...
[ATA] IDENTIFY complete
Model:    [TOSHIBA MK4001MTD]
Serial:   [           763B004HA]
Firmware: [VH173A]
Sectors:  7862400 (3839 MB)
SMART:    not supported (supported=0, enabled=0)
IDENTIFY: W0=0040 W47=0000 W49=0000 W59=0000
  ATA W80=0000  Cmd W82=0000 W83=0000 W84=0000
  En  W85=0000 W86=0000 W87=0000  W89=0008 W128=0001

[DIAG] === Drive Diagnostics ===
[DIAG] Standard SMART: not supported (IDENTIFY W82 bit0 = 0)
[DIAG] Toshiba vendor CMD 0xC2:
  FEAT=0x01 unknown_01                       → SC=00 LBA=02/00/00 ST=50
  FEAT=0x02 unknown_02                       â SC=00 LBA=02/00/00 ST=50
  FEAT=0x03 unknown_03                       → SC=00 LBA=02/00/00 ST=50
  FEAT=0x04 unknown_04                       → SC=00 LBA=02/00/00 ST=50
  FEAT=0x10 diag_10 (LBA_LO varies)          → SC=00 LBA=00/00/00 ST=50
  FEAT=0x11 diag_11                          → SC=00 LBA=00/00/00 ST=50
  FEAT=0x12 diag_12 (LBA_LO varies)          → SC=00 LBA=01/00/00 ST=50
  FEAT=0x20 query_20 (N91: SC=0xFF always)   → SC=FE LBA=00/FF/00 ST=50
  FEAT=0x21 query_21 (N91: SC varies per boot) → SC=1B LBA=00/FF/00 ST=50

[MAIN] MBR: valid 0x55AA
[MAIN] Warming up...
[MAIN] PIO OK, STATUS=0x50
[MAIN] Drive: 7862400 sectors (3839 MB)
[MAIN] Ready.
[PWR] Idle 5000ms → STANDBY + power gate
[PWR] STANDBY IMMEDIATE → power gate
[SDIO] HDD power OFF

Infine, ecco il cablaggio al drive vero.
_DSC1176-2 Ecco un ritaglio dallo schema N91, è possibile mappare anche il numero del pin. immagine

Nota a margine: questo è un drive a 3V ma credo che 3,3V vada bene, principalmente per risparmiare lavoro di level shifting.

L'HW progettato specificamente per questo drive si trova in /hardware! immagine

File Sorgente

Cronologia Versioni

Test

root@kitploit:~
# Verifica che il dispositivo sia apparso
lsblk -dno NAME,MODEL | grep MK4001

# Test del filesystem — monta, copia file, verifica
sudo mount /dev/sdX1 /mnt/mk4001
cp /tmp/testfile /mnt/mk4001/
sync
md5sum /tmp/testfile /mnt/mk4001/testfile    # dovrebbero corrispondere
sudo umount /mnt/mk4001

# Benchmark di velocità (dispositivo grezzo, NON montare prima — corromperà il filesystem)
# Usare un offset sicuro oltre il filesystem o un drive non partizionato
sudo dd if=/dev/sdX of=/dev/null bs=64k count=128 iflag=direct     # lettura
sudo dd if=/dev/zero of=/dev/sdX bs=64k count=64 oflag=direct seek=1024  # scrittura (offset oltre FS)

Note umane, curiosità: quando ha iniziato a fare i test di velocità, in realtà ha eseguito dd direttamente sul drive e danneggiato i filesystem..... Per fortuna non è stato così grave durante lo sviluppo, ma tenetelo sempre a mente quando gestite il vostro setup OpenClaw.

Licenza

Non mi interessa.

Scarica lo strumento
MetricaValore
Velocità di lettura~985 kB/s (limitata dalla velocità USB full-speed)
Velocità di scrittura~920 kB/s (limitata dalla velocità USB full-speed, cache di scrittura pubblicizzata)
Velocità lato SDIO grezza~2,35 MB/s in lettura / ~2,15 MB/s in scrittura (limitata dal drive)
Capacità3,75 GB (7.862.400 settori)
File systemFAT32 verificato (mount/unmount/fsck pulito)
Integrità datiScrittura+rileggere verificato; CRC16 per blocco su tutte e 4 le linee DAT
Standby idle5 s di inattività o sospensione USB → STANDBY IMMEDIATE + power gate
sdio_hw.c
IndirizzoRegistroUtilizzo
0x00DATADestinazione CMD53 per i dati dei settori
0x01ERR/FEATErrore (lettura) / Caratteristica (scrittura)
0x02SECCOUNTConteggio settori
0x03LBA_LOLBA bit 0-7
0x04LBA_MIDLBA bit 8-15
0x05LBA_HILBA bit 16-23
0x06DEV/HEADDispositivo/Testa + LBA bit 24-27
0x07CMD/STATUSComando (scrittura) / Stato (lettura)
Pico GPIOFunzioneNote
GP2SDIO_CLKUscita clock host
GP3SDIO_CMDLinea comando bidirezionale
GP4SDIO_DAT0Bit dati 0
GP5SDIO_DAT1Bit dati 1
GP6SDIO_DAT2Bit dati 2
GP7SDIO_DAT3Bit dati 3
GP9HDD_ENAbilitazione alimentazione drive (HIGH=acceso)
GP12UART TXUscita debug @ 115200
GP13UART RXIngresso debug
GP16LED: Alimentazione HDDAttivo basso
GP17LED: HDD SanoAttivo basso
GP18LED: LetturaAttivo basso
GP19LED: ScritturaAttivo basso
FileRigheScopo
main.c210Inizializzazione, standby idle, sospensione/ripresa USB
msc_device.c400Callback USB MSC, riattivazione power gate, cache settori danneggiati
ata_sdio.c390Comandi ATA, recupero errori, diagnostica vendor
sdio_pio.c635PIO SDIO: CMD52, lettura/scrittura CMD53, swap programma, CRC16
sdio_hw.c45Inizializzazione pin + controllo alimentazione HDD
sdio.pio200Assembly PIO + helper di inizializzazione C SDK
led.h37Helper LED (GP16–GP19, attivo basso)
usb_descriptors.c77Descrittori USB dispositivo/configurazione/stringa
tusb_config.h20Configurazione TinyUSB (MSC, buffer EP 32KB)
VersioneLetturaScritturaModifica chiave
v0.1–v0.3105 kB/s93 kB/sSDIO bit-bang, CRC16, logica di ritentamento
v0.5374 kB/s—PIO a singola SM, swap memoria istruzioni diretta
v0.6583 kB/s93 kB/sLetture CMD53 multi-blocco, fix drenaggio clock CRC
v0.8588 kB/s274 kB/sScritture PIO, fix flush OSR
v0.9475 kB/s371 kB/sChunk da 64 settori, verifica lettura CRC16
v0.10453 kB/s329 kB/sRiassegnazione LED, pin HDD EN, UART su GP12/GP13
v0.11~450 kB/s~340 kB/sPower gate HDD, riattivazione PIO, senso settori danneggiati, sospensione USB
v0.12~985 kB/s~920 kB/sSovrapposizione drive/USB (prefetch lettura + cache di scrittura pubblicizzata con write-behind), blocchi PIO pipeline, DMA bswap, loop PIO a 4 cicli, semantica settori danneggiati stile SBC (riparazione tramite scrittura), driver MSC TinyUSB fornito