
Firmware RP2040 que faz a ponte entre um microdrive SDIO Toshiba MK4001MTD de 0,85" como um dispositivo de armazenamento em massa USB, implementando toda a pilha de protocolo SDIO-ATA do zero com leituras/escritas aceleradas por PIO e recuperação de setores defeituosos.
Firmware RP2040 Pico que faz a ponte de um microdrive SDIO Toshiba MK4001MTD de 0,85" como dispositivo de armazenamento em massa USB.

O MK4001MTD é um Microdrive de 4 GB originalmente usado no telefone musical Nokia N91 e em alguns outros dispositivos, como tocadores de MP3 ou unidades USB, na época em que o armazenamento flash ainda era bastante caro.
Você pode ter visto introduções afirmando que este drive usa o protocolo MMC, mas isso está incorreto. Estou investigando isso há algum tempo: tentei construir um leitor de cartão MMCplus de 8 bits e testei diferentes leitores SD/MMC sem sucesso. Como último recurso, comprei um Nokia N91 para capturar traces lógicos e confirmar qual protocolo ele realmente usa.
Aqui está a foto quando eu estava tentando usá-lo com minha placa leitora 8bit-MMCPlus, e descobriu-se que não é MMC :(

Então acabei comprando um N91 para coletar traces:

Ao contrário dos microdrives ATA/CF padrão, ele usa uma interface SDIO com comandos ATA tunelados através do CMD52/CMD53. Nenhum driver existente suporta esse protocolo, então este firmware implementa toda a pilha do zero.
Isso me surpreendeu, porque existe um padrão SDIO-para-ATA chamado CE-ATA. Mas se você observar atentamente a linha do tempo de lançamento, o CE-ATA veio depois deste drive. Como resultado, este drive depende inteiramente de comandos SDIO, e o CE-ATA não está disponível. O CE-ATA tem dois novos comandos CMD60/CMD61 e utiliza CMD12/39, mas você pode ver pelos traces que ele não está usando nenhum deles.
O segundo ponto de hardware a mencionar é que outra desinformação circulando—afirmando que é um cartão MMCPlus de 8 bits—não é apenas falsa, mas a pinagem também não segue o padrão MMC. Você pode encontrar o manual de serviço do Nokia N91 com alguma documentação sobre a pinagem: embora a numeração dos pinos siga o padrão MMCPlus, o mapeamento dos pinos não. Este é um detalhe importante se você estiver fazendo a fiação você mesmo: ele usa o mesmo conector MMC, mas o mapeamento dos pinos é diferente, mais na seção Hardware.
Finalmente, note que isso foi desenvolvido em conjunto com Claude/OpenClaw. Eu coletei os traces lógicos manualmente e montei uma estação de teste em malha fechada para o OpenClaw iterar no desenvolvimento—analisando os traces e implementando funcionalidades. A documentação será escrita principalmente por Claude; também adicionarei minhas anotações inline. Também li e verifiquei a documentação pessoalmente, e ela deve ser confiável e fácil de seguir.
Para insights sobre as análises do trace do N91, está em /docs/N91_TRACE_ANALYSIS.md, também coloquei o manual de serviço do N91 lá junto com os traces lógicos brutos.
Veja mais no post do blog aqui: https://www.willwhang.dev/Reading-MK4001MTD/
Veja em atividade aqui: https://youtu.be/GC4xil3_Bbc
Armazenamento em massa USB totalmente funcional com leituras/escritas aceleradas por PIO e gerenciamento de energia ociosa.
| Metric | Value |
|---|---|
| Velocidade de leitura | ~985 kB/s (limitado pela USB full-speed) |
| Velocidade de escrita | ~920 kB/s (limitado pela USB full-speed, cache de escrita anunciado) |
| Velocidade bruta do lado SDIO | ~2,35 MB/s leitura / ~2,15 MB/s escrita (limitado pelo drive) |
| Capacidade | 3,75 GB (7.862.400 setores) |
| Sistema de arquivos | FAT32 verificado (mount/unmount/fsck limpo) |
| Integridade dos dados | Escrita+releitura verificada; CRC16 por bloco em todas as 4 linhas DAT |
| Espera ociosa | 5 s inativo ou suspensão USB → STANDBY IMMEDIATE + corte de energia |
USB Host ←→ USB MSC (TinyUSB) ←→ ATA Layer ←→ SDIO Layer (PIO) ←→ MK4001MTD
O firmware tem quatro camadas:
USB MSC (msc_device.c) — TinyUSB Mass Storage Class. Traduz SCSI READ(10)/WRITE(10) em operações de setor ATA. Buffer EP de 32 KB, agrupando até 64 setores por transferência USB. A E/S do drive é sobreposta com USB em ambas as direções, como uma ponte ATA-USB real com um disco de cache: um pré-buscador de leitura sequencial busca o próximo bloco enquanto o anterior é transmitido ao host, e as escritas são enfileiradas e liberadas enquanto a USB recebe a próxima parte. O dispositivo anuncia seu cache de escrita (Caching mode page, WCE=1 — os hosts reportam "Write cache: enabled" e emitem SYNCHRONIZE CACHE em fsync/desmontagem/suspensão, que o firmware honra). Uma liberação de fundo com falha surge como MEDIUM ERROR no próximo WRITE ou SYNCHRONIZE CACHE; escritas em setores conhecidamente ruins seguem um caminho estritamente síncrono.
ATA-over-SDIO (ata_sdio.c) — Implementa comandos ATA (IDENTIFY, READ SECTORS, WRITE SECTORS) escrevendo em registradores ATA mapeados no espaço de endereço da função 1 SDIO via CMD52, e transferindo dados de setor via CMD53. Lógica de retry em 3 níveis nos níveis CMD, dados e ATA.
PIO SDIO (sdio_pio.c, sdio.pio) — SDIO acelerado por hardware usando o periférico PIO do RP2040 (barramento de 4 bits a 10 MHz, 4 ciclos PIO por bit com sincronizadores de entrada desviados). Três programas PIO compartilham uma única máquina de estado via troca dinâmica de programas:
Pin/Power (sdio_hw.c) — Inicialização de GPIO e controle de energia do HDD. Toda comunicação SDIO usa PIO.
Notas humanas: Curiosamente, Claude estava realmente relutante em implementar SDIO em PIO, e muitos ciclos de desenvolvimento foram desperdiçados indo e voltando entre PIO e bit-banging.
O MK4001MTD se apresenta como um cartão SDIO com uma função I/O. A inicialização padrão do cartão SDIO (CMD5/CMD3/CMD7) configura o barramento, então os registradores ATA são acessados através de comandos SDIO:
Acesso a registradores (CMD52): Cada registrador ATA é mapeado para um endereço da função 1:
| Endereço | Registrador | Uso |
|---|---|---|
| 0x00 | DATA | Alvo CMD53 para dados de setor |
| 0x01 | ERR/FEAT | Erro (leitura) / Feature (escrita) |
| 0x02 | SECCOUNT | Contagem de setores |
| 0x03 | LBA_LO | LBA bits 0-7 |
| 0x04 | LBA_MID | LBA bits 8-15 |
| 0x05 | LBA_HI | LBA bits 16-23 |
| 0x06 | DEV/HEAD | Dispositivo/Cabeça + LBA bits 24-27 |
| 0x07 | CMD/STATUS | Comando (escrita) / Status (leitura) |
Transferência de dados (CMD53): Os dados do setor são transferidos emitindo CMD53 em modo bloco visando o registrador DATA (endereço 0x00). Para leituras de múltiplos setores, um único CMD53 com block_count=N transfere N × 512 bytes em uma transação multi-bloco SDIO.