terça-feira, abril 26, 2022

Acessando um SD Card com o RP2040: Parte 2

Em principio um cartão SD nada mais é que uma unidade de armazenamento de massa, onde blocos de dados podem ser acessados em qualquer ordem. Portanto pode-se implementar praticamente qualquer organização de arquivos normalmente usada com HDs. Para fins de interoperabilidade entre equipamentos, o mais comum é usar um sistema de arquivos do tipo FAT.


Muita coisa na estrutura de dados em um cartão SD me leva de volta ao início do PC, nos anos 80. Para começar, o primeiro bloco do cartão tem o MBR (Master Boot Record), introduzido junto com o MS DOS 2.0 e o PC XT.

Ao invés de ser um bootloader simples, que carrega diretamente o sistema operacional (como era o bootloader do MS DOS 1 nos disquetes), o MBR contém uma tabela que divide a unidade em várias partições. Uma destas partições é marcada como ativa e é dela que é carregado o próximo estágio do sistema operacional.

Cartões SD usados em "dispositivos de consumo" (como máquinas fotográficas) costuma usar apenas uma partição FAT. No Raspberry Pi OS temos normalmente duas partições, uma FAT (para configuração fácil em sistemas Windows) e outra no formato ext4 (para o Linux).

As bibliotecas para acesso ao SD com microcontroladores costumam suportar apenas o sistema FAT. FAT é ainda mais antigo que o MS DOS, vindo do standalone BASIC da Microsoft (uma versão de BASIC com acesso a arquivos em máquinas sem sistema operacional). Eu escrevi, décadas atrás, sobre o sistema FAT no DOS 3, mas aqui vou ficar no básico.

No sistema FAT o controle de arquivos é dividido em duas estruturas: diretórios e a tabela de alocação (FAT). Para fins de controle, a unidade é dividida em clusters de tamanho fixo. 

Um diretório registra os arquivos, anotando (no mínimo) o nome, o tamanho (em bytes) e o número do primeiro cluster. A tabela de alocação possui uma posição para cada cluster. Esta posição pode indicar que o cluster está reservado, livre, é o último cluster de um arquivo ou (se em uso e não é o último) o número do próximo cluster do arquivo. Desta forma é montada uma lista ligada simples dos clusters ligados a um arquivo. Esta estrutura é bem adequada para acesso sequencial, porém é desajeitada para acesso aleatório. Como a FAT é crítica para saber onde estão os arquivos, duas cópias idênticas são normalmente gravadas.

Quando o sistema FAT foi criado (o que hoje chamamos de FAT12, pois o número do cluster ocupava 12 bits) a capacidade dos discos era tão baixa que dava para manter a tabela sempre em memória, deixando o acesso rápido. À medida que a capacidade dos discos aumentou, foi preciso ir aumentando primeiro o tamanho dos cluster e, quando o desperdício com arquivos pequenos ficou intolerável, aumentar o número de bits da numeração de clusters (para 16 e depois 32). Inicialmente existia somente um diretório (em uma posição fixa), no DOS 2.0 passamos a ter subdiretórios (que são arquivos com a mesma estrutura que o diretório principal). Outros aperfeiçoamentos foram introduzidos ao longo dos anos, como o suporte a nomes longos.

Para um desempenho bom, não podendo manter toda a FAT em memória, é preciso ter um bom algoritmo de cache, que consiga manter em memória os trechos da FAT que provavelmente serão acessados em breve. Este é um problema sério quando falamos em microcontroladores com memória limitada. Por exemplo, um Arduino Uno tem apenas 2K de Ram e fica difícil manter em memória mais que um buffer de 512 bytes para acesso ao SD.

Na terceira (e última) parte vamos ver uma biblioteca para acessar cartões SD com o RP2040.

Nenhum comentário: