MCU & FPGA geral Sistemas de Arquivos em Microcontroladores: LittleFS, SPIFFS e SD Card no STM32N6

Sistemas de Arquivos em Microcontroladores: LittleFS, SPIFFS e SD Card no STM32N6

Arquitetura proposta: STM32N6, SD Card, FATFS e FreeRTOS

Para um projeto com STM32N6, SD Card e FreeRTOS, a arquitetura mais coerente é tratar o cartão SD como uma mídia de blocos e usar uma camada de sistema de arquivos compatível com esse tipo de dispositivo. Nesse cenário, o caminho mais comum é usar FATFS, especialmente quando o projeto é criado com ferramentas da ST, como STM32CubeMX e STM32CubeIDE.

A ideia geral é simples: o STM32N6 acessa o cartão SD por meio de uma interface física, normalmente SDMMC ou, em projetos mais simples, SPI. O driver de baixo nível conversa com o cartão, enquanto o FATFS organiza os setores em arquivos e diretórios. O FreeRTOS entra como ambiente de execução das tarefas, mas não precisa ser o centro da discussão. Para este artigo, vamos considerar apenas que uma tarefa será responsável por montar o cartão, criar um arquivo e gravar dados.

Observe que o FATFS não fala diretamente com o hardware. Ele chama uma interface intermediária chamada, normalmente, de disk I/O layer. Essa camada implementa funções como disk_initialize, disk_status, disk_read, disk_write e disk_ioctl. No ecossistema STM32, essas funções costumam ser geradas ou parcialmente integradas pelo STM32CubeMX quando ativamos o middleware FATFS e o periférico SDMMC.

Em um projeto real com FreeRTOS, é importante não permitir que várias tarefas escrevam no cartão ao mesmo tempo sem controle. O sistema de arquivos precisa ser protegido por um mutex, porque uma tarefa pode estar escrevendo um arquivo enquanto outra tenta ler uma configuração ou criar um log. Sem essa proteção, podem ocorrer corrupção de dados, falhas de escrita ou comportamento imprevisível. Não precisamos entrar nos detalhes internos do FreeRTOS, mas precisamos reconhecer que o acesso ao sistema de arquivos deve ser serializado.

A estrutura mínima do firmware pode ser pensada com três partes. A primeira é a inicialização do hardware, onde o clock, os GPIOs, o SDMMC e o DMA são configurados. A segunda é a inicialização do sistema operacional, criando a tarefa responsável pelo armazenamento. A terceira é a própria tarefa, que monta o cartão e executa as operações de arquivo.

Um esqueleto simplificado ficaria assim:

#include "main.h"
#include "cmsis_os.h"
#include "fatfs.h"

/*
 * Handles gerados normalmente pelo STM32CubeMX.
 * Os nomes podem variar conforme a configuração do projeto.
 */
extern SD_HandleTypeDef hsd1;

/*
 * Mutex para proteger o acesso ao sistema de arquivos.
 * Em um projeto real, ele deve ser criado antes do scheduler iniciar.
 */
osMutexId_t fsMutexHandle;

/*
 * Protótipo da tarefa de armazenamento.
 */
void StorageTask(void *argument);

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_DMA_Init();
    MX_SDMMC1_SD_Init();
    MX_FATFS_Init();

    osKernelInitialize();

    const osMutexAttr_t fsMutex_attributes = {
        .name = "fsMutex"
    };

    fsMutexHandle = osMutexNew(&fsMutex_attributes);

    const osThreadAttr_t storageTask_attributes = {
        .name = "StorageTask",
        .stack_size = 2048,
        .priority = osPriorityNormal
    };

    osThreadNew(StorageTask, NULL, &storageTask_attributes);

    osKernelStart();

    while (1)
    {
    }
}

Esse código ainda não grava nada no cartão. Ele apenas mostra a ideia arquitetural: o hardware é inicializado, o FATFS é preparado, o mutex é criado e uma tarefa FreeRTOS chamada StorageTask será responsável por manipular o SD Card. Em projetos STM32, parte desses nomes pode variar dependendo da placa, da instância SDMMC usada e da configuração feita no CubeMX.

Agora podemos criar uma tarefa simples que monta o sistema de arquivos e grava um arquivo de texto no cartão SD:

#include "ff.h"
#include "fatfs.h"
#include "cmsis_os.h"
#include <string.h>
#include <stdio.h>

extern osMutexId_t fsMutexHandle;

/*
 * Objetos globais normalmente declarados pelo middleware FATFS.
 * Em muitos projetos STM32Cube, eles aparecem em fatfs.c/fatfs.h.
 */
extern FATFS SDFatFS;
extern char SDPath[4];

void StorageTask(void *argument)
{
    FRESULT result;
    FIL file;
    UINT bytesWritten;

    const char *message =
        "STM32N6 gravando dados no SD Card com FATFS e FreeRTOS.\r\n";

    /*
     * Em sistemas com SD Card removível, seria melhor verificar
     * presença do cartão antes de montar.
     */
    osMutexAcquire(fsMutexHandle, osWaitForever);

    result = f_mount(&SDFatFS, SDPath, 1);

    if (result == FR_OK)
    {
        result = f_open(&file, "log_stm32n6.txt", FA_CREATE_ALWAYS | FA_WRITE);

        if (result == FR_OK)
        {
            result = f_write(
                &file,
                message,
                strlen(message),
                &bytesWritten
            );

            if (result == FR_OK && bytesWritten == strlen(message))
            {
                f_sync(&file);
            }

            f_close(&file);
        }

        f_mount(NULL, SDPath, 0);
    }

    osMutexRelease(fsMutexHandle);

    for (;;)
    {
        osDelay(1000);
    }
}

Esse exemplo mostra o fluxo essencial: montar, abrir, escrever, sincronizar, fechar e desmontar. A função f_mount conecta o FATFS ao volume lógico. A função f_open cria ou abre o arquivo. A função f_write grava os bytes. A função f_sync força a sincronização dos dados pendentes, reduzindo o risco de perda se houver desligamento logo após a escrita. A função f_close fecha o arquivo corretamente, e f_mount(NULL, SDPath, 0) desmonta o volume.

Em aplicações reais, nem sempre é interessante montar e desmontar o cartão a cada operação. Muitas vezes, o sistema monta uma vez na inicialização e mantém o volume ativo enquanto o cartão estiver presente. Porém, para um primeiro exemplo didático, montar, gravar e desmontar deixa claro o ciclo completo de uso.

Também é importante destacar que f_sync não substitui um projeto elétrico seguro. Se o dispositivo pode perder energia durante uma gravação, o ideal é prever capacitores, supervisores de tensão, detecção de queda de energia ou uma política de escrita transacional. Em sistemas embarcados, a confiabilidade do armazenamento depende tanto do software quanto da eletrônica.

Essa arquitetura com FATFS é a base mais apropriada para SD Card no STM32N6. Na próxima seção, podemos transformar esse exemplo em algo mais realista: uma tarefa que recebe mensagens de log por fila e grava no cartão SD sem bloquear o restante da aplicação.

0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

0
Adoraria saber sua opinião, comente.x