A saga da placa RISC-V sem nome (Parte 1)

Eu tenho esse hábito (ou vício) de acumular placas. RISC-V, SoCs obscuros, microcontroladores… por aí vai. No meio da bagunça, tinha três que se destacam: Uma Milk-V Duo, uma Luck Fox Mini e uma outra placa baseada no RV1106G que eu não tem nem modelo.

As specs eram modestas (ou não): 64 MB de RAM, SPI NAND de 256MB, Ethernet de 100 Mbps e USB-C Host/Device. O consumo? Estáveis 5V @ 1A (ou não, não medi). Pra muita gente, passaria batido. Pra mim, virou um desafio pessoal de domingo.

Introdução

Desde que comprei essa placa, nunca fiz nada tão grande nela. Rodei Linux, fiz o LED piscar, rodei comandos de rede, weeee… Bem legal, rodar Linux numa placa é impressionante e divertido. Mas sem uma utilidade para ela, acabou ficando de lado.

O chip dela é bastante poderoso, essa placa parece um monstro perto das outras duas, ainda assim, o design da placa em si me atrapalhou em alguns quesitos.

Pelo que parece a placa foi desenvolvida para operar como controladora em alguma espécie de automação envolvendo câmeras, IA e rede. Os destaques do chip e da placa são as capacidades de operar câmeras, displays LCD, ter uma NPU para aceleração de IA… um monte de coisa

Não sei por qual motivo, mas várias portas do conector estavam desconectadas, deixando de suportar diversas funções que poderia ter. Por conta disso também, passei semanas quebrando cabeça com o barramento I2C da placa, que se não importa o quanto eu tentasse, não reconhecia os dispositivos.

I2C: Protocolo de comunicação (como o USB por exemplo) usado para comunicação entre circuitos eletrônicos.

O sacrifício: ATS-20+

Eu tinha um pequeno rádio que comprei pela internet, um ATS-20+, que é basicamente um chip SI4732 junto com um Arduino Nano e alguns periféricos para fazer um rádio que funciona em AM, FM e SSB.

SI4732: Circuito integrado digital responsável por toda a parte do rádio.

Foto de um rádio modelo ATS-20+

Decidi canibalizar ele, para aproveitar o display OLED para fazer alguma coisa. Então segui e desmontei, e como de esperado, encontrei um Arduino Uno soldado à uma placa, que se conectava ao painel frontal com cabos flat.

Placa do ATS-20+

A placa principal é bem hacker-friendly, bem documentada na própria placa, foi fácil identificar as portas de comunicação usadas pelo display. Após identificar as portas SDA e SCL (características do protocolo I2C), e as portas GND e 3.3V de alimentação e conectar na placa RISC-V bastava rodar o comando de teste…

Rodei o comando i2cdetect, várias e várias vezes… Sem sucesso.

i2cdetect: Comando do Linux para detectar dispositivos conectados ao barramento I2C.

De início comecei a suspeitar da minha solda, dos jumpers que eu estava usando. Até que em fim, depois de alguns dias de tenta e desiste, caiu a luz.

A dor de cabeça

Depois de dias tentando, entrei em contato com o fabricante da placa, Shenzhen LC Technology, que me enviou um esquemático do modelo especifico que eu tinha, porém um detalhe passou batido.

A placa minha era similar ao modelo LuckFox Pico Pro Max, que também tinha um pinout parecido. Esse layout inclusive, indicado pelo fabricante, era totalmente compatível com a placa que eu tinha, exceto por algumas diferenças.

Pinout: Organização dos pinos em uma placa.

Pinout da placa Luck Fox Pico Pro Max baseada no chip RV1006G2
Pinout do LCPI-RV1106


Se notar a segunda imagem, há vários pinos conectados, entre os pinos 3 e 7, 8 e 9, e outros… Estes destacados eram justamente os pinos que eu precisava, onde seriam os pinos I2C3_SDA_M1 e etc.

Para piorar a situação, as outras portas I2C não estavam mapeadas adequadamente no kernel do Linux, ou seja, acessar os arquivos /dev/i2c-3 e /dev/i2c-4 não acessava o barramento presente nos pinos da placa, e sim em alguma porta não mapeada à nenhuma saída externa da placa.

grep -r "i2c" /sys/firmware/devicetree/base 2>/dev/null

Este comando deveria listar os dispositivos (ou alguma coisa assim), e filtrar pelo termo “i2c”

/sys/firmware/devicetree/base/pinctrl/i2c4/i2c4m2-xfer/name:i2c4m2-xfer

Essa foi a resposta: O Linux estava reconhecendo a porta I2C que eu precisava (i2c4), porém estava direcionada à outra porta (pelo sufixo m2). Por isso, nada funcionada quando eu tentava conectar a tela na porta 4.

Depois de muito resistir, cedi à solução: Baixar o código-fonte do desse chip e modificar ele para usar as portas que eu tinha. Eu estava mais perto do que nunca de fazer isso funcionar, ainda assim, conseguir fazer código fonte rodar

O desespero

Antes de fazer qualquer modificação, precisava certificar que era possível compilar a fonte em meu computador. Para isso, instalei os pacotes descritos na documentação e executei os comandos. Defini as configurações e mandei compilar. Depois longos minutos, o resultado: Erro.

Não sei exatamente o que causou o erro. Ainda com pouca experiência em código C de tão baixo nível, as mensagens de erro pareciam incompreensíveis (e olha que eu sou bom nisso).

Como a documentação sugeria um ambiente com Ubuntu 22.04, e eu estava em uma distribução similar, mas diferente, decidi tentar compilar dentro de um container.

Rodei um container com Ubuntu 22.04, e depois de mais longos minutos… outro erro. Dessa vez um mais compreensível: Problema de versão. Como parecia que algum pacote estava desatualizado decidi testar com Ubuntu 24.04, e… SUCESSO!

Naquele momento pude editar o arquivo que determinava o mapeamento das portas no Linux (rv1106g-luckfox-pico-pro-max.dts) e forcei o mapeamento apropriado para meu modelo de placa.

/* Adicionado ao fim do arquivo */
&i2c4 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c4m0_xfer>; /* Force it to M0 */
    /delete-property/ pinctrl-1;
};

&pinctrl {
    i2c4 {
        /delete-node/ i2c4m2-xfer;
    };
};

Isso, claro, na terceira tentativa de recompilação — depois de algumas horas perdidas nas primeiras builds — veio a recompensa:

[root@luckfox root]# i2cdetect -y 4
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --  
...
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 

Saída do comando i2cdetect, o texto 3c indica que um dispositivo foi detectado naquele endereço.

Ali estava ele. O OLED (canibalizado do ATS-20+) finalmente respondeu.

Agora, ser feliz

Com o display conectado no Linux, agora era só ser feliz.

Escrevi uma simples biblioteca em Python para escrever caracteres na tela. E depois de alguns ajustes e testes, consegui fazer um painel para mostrar informações do sistema na tela:

Mostrei para o meu pai e ele me sugeriu tentar colocar algum desenho. Eis um urso em ASCII:

O que vem por aí?

Agora que este experimento deu certo, quero tentar integrar essa placa no rádio ATS-20+, substituir o Arduino Nano original pelo RV1106G e controlar o chip de RF diretamente via rede… Ou talvez eu so canibalize o display de vez para outro projeto… Quem sabe?