Desenvolvimento de Drivers SPI NOR Flash em Plataformas Allwinner

Visão Geral e Escopo

Este guia detalha a implementação e configuração do subsistema de memória NOR Flash em plataformas Sunxi (Allwinner). O suporte abrange diferentes estágios de inicialização e versões de kernel:

  • Boot0: Baseado em brandy-2.0.
  • U-Boot: Versão 2018.
  • Kernel Linux: Versões 4.9 e 5.4.

Arquitetura do Subsistema SPI NOR

A pilha de software no Linux para dispositivos SPI NOR é composta por quatro camadas principais, garantindo a abstração do hardware até a interface MTD (Memory Technology Device):

  1. SPI NOR Framework: Gerencia as particularidades físicas de diferentes fabricentes. Define modos de largura de banda (1-bit, 2-bit, 4-bit, 8-bit) e endereçamento de 4 bytes para memórias superiores a 16MB. Localização: drivers/mtd/spi-nor/spi-nor.c.
  2. M25P80 (Generic Driver): Atua como um driver de protocolo que encapsula as requisições do framework em mensagens SPI. Localização: drivers/mtd/devices/m25p80.c.
  3. SPI Framework: Gerencia a fila de mensagens e o agendamento de tarefas do controlador SPI. Localização: drivers/spi/spi.c.
  4. SPI Controller Driver: Driver específico do SoC Sunxi que configura frequências, modos de clock, CS (Chip Select) e realiza a transferência de dados via CPU ou DMA. Localização: drivers/spi/spi-sunxi.c.

Configuração do Ambiente de Build

Durante a preparação do firmware, é necessário especificar o uso de memória NOR no script de build:

./build.sh config
# Selecione a plataforma (ex: Linux)
# Ao chegar em "All available flash", escolha a opção correspondente:
# 0. default (NAND/eMMC)
# 1. nor
Choice [default]: 1

Para gerar o firmware final, utilize os comandos padrão de empacotamento:

# Firmware padrão
./build.sh pack

# Firmware com depuração via porta serial
./build.sh pack_debug

Definições no arquivo sys_config.fex

Os parâmetros de inicialização do Boot0 são extraídos da seção [spinor_para]. Estes valores são injetados no cabeçalho do binário pelo utilitário update_boot0.

[spinor_para]
spi_sclk      = port:PC00<4><0><2><default>
spi_cs        = port:PC01<4>1><2><default>
spi0_mosi     = port:PC02<4><0><2><default>
spi0_miso     = port:PC03<4><0><2><default>
spi0_wp       = port:PC04<4><0><2><default>
spi0_hold     = port:PC05<4><0><2><default>
read_mode     = 4
flash_size    = 16
frequency     = 100000000
delay_cycle   = 1

Parâmetros principais:

  • read_mode: Largura de banda (1, 2 ou 4 linhas).
  • frequency: Clock do SPI (ex: 100MHz).
  • delay_cycle: Ajuste de amostragem. Use 1 para frequências > 60MHz.

Configuração do U-Boot

Para habilitar o suporte no U-Boot, utilize o menuconfig:

Device Drivers --->
    [*] SPI Support --->
        [*] Sunxi SPI driver
    [*] Sunxi flash support --->
        [*] Support sunxi spinor devices

Configuração do Kernel Linux

No kernel, certifique-se de que os drivers MTD e SPI-NOR estão habilitados:

Device Drivers --->
    <*> Memory Technology Device (MTD) support --->
        <*> SUNXI partitioning support
        <*> Direct char device access to MTD devices
        <*> Caching block device access to MTD devices
        SPI-NOR device support --->
            <*> Support most SPI Flash chips (AT16DF, M25P, etc)

Importante: Se estiver utilizando um sistema de arquivos SquashFS, o método de compressão (GZIP, XZ, LZO) selecionado no kernel deve coincidir com o configurado no script mkcmd.sh da build principal.

Interface de Programação (API)

Funções do Driver (Kernel Space)

As funções abaixo realizam a comunicação direta com o subsistema MTD:

  • spi_nor_read(mtd, from, len, retlen, buf): Lê dados da flash.
  • spi_nor_write(mtd, to, len, retlen, buf): Escreve dados na flash.
  • spi_nor_erase(mtd, instr): Apaga blocos de memória conforme definido na estrutura erase_info.

Funções de Aplicação no U-Boot

O U-Boot utiliza uma interface simplificada para manipulação de partições:

// Inicialização do dispositivo
static int sunxi_flash_spinor_init(int boot_mode, int res);

// Escrita por setores
static int sunxi_flash_spinor_write(uint start_block, uint nblock, void *buffer);

// Atualização do Boot0
static int sunxi_flash_spinor_download_spl(unsigned char *buf, int len, unsigned int ext);

Exemplos de Uso no Shell do U-Boot

O comando sunxi_flash permite manipular partições diretamente pela linha de comando.

1. Leitura de partição:

# Lê a partição 'boot' para o endereço de memória RAM 0x49000000
sunxi_flash read boot 0x49000000

2. Escrita de partição:

# Altera o conteúdo na memória RAM
mm.b 0x44000000
# Grava o conteúdo da RAM na partição 'env'
sunxi_flash write env 0x44000000

Para validar a escrita, recomenda-se reler a partição para um novo endereço de memória e comparar os hashes ou utilizar o comando cmp no U-Boot.

Tags: Allwinner SPI-NOR MTD linux-kernel U-Boot

Publicado em 7-13 01:22