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):
- 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. - 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. - SPI Framework: Gerencia a fila de mensagens e o agendamento de tarefas do controlador SPI. Localização:
drivers/spi/spi.c. - 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 estruturaerase_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.