terça-feira, 8 de outubro de 2024

MILK-V DUO 256 - COMUNICAÇÃO ENTRE PROCESSADORES - VIA PONTE SERIAL ARDUINO + LINUX SHELL CONSOLE

Arduino enviando comandos para o LINUX via UART
,

Introdução

Arduino é uma plataforma de hardware de código aberto popular, conhecida por sua simplicidade, facilidade de uso e abertura. Ele fornece uma rica coleção de funções de biblioteca e códigos de exemplo, tornando-o acessível mesmo para indivíduos sem experiência em programação. Além disso, a comunidade Arduino é altamente ativa, permitindo fácil acesso a uma ampla variedade de tutoriais, documentação e suporte de projetos.

A série Milk-V Duo agora suporta o desenvolvimento do Arduino. Você pode usar diretamente o Arduino IDE e, após uma configuração simples, começar a utilizá-lo.

A CPU da série Duo adota um design de núcleo grande, onde o firmware do Arduino é executado no núcleo pequeno, enquanto o núcleo grande é responsável pela comunicação com o IDE do Arduino. Ele recebe o firmware do Arduino e o carrega no pequeno núcleo para execução. Ao mesmo tempo, o sistema Linux no grande núcleo também funciona normalmente.

1. Instale o Arduino

Arduino IDE oferece suporte a três sistemas operacionais: Windows, Linux e macOS. De acordo com o sistema que você está usando, acesse o site oficial do Arduino para baixar o pacote de instalação correspondente para instalação. A versão mais recente atual é 2.3.2 e é recomendado usar a versão mais recente.

Adicione o Duo ao Arduino

Abra o Arduino IDE, selecione Preferences no menu File e adicione o endereço do arquivo de configuração do Duo na aba Additional boards manager URLs Settings:

https://github.com/milkv-duo/duo-arduino/releases/download/config/package_sg200x_index.json


Faça download do endereço do arquivo json mais recente em Releases .

Se você configurou outros endereços de placa de desenvolvimento antes, separe-os com vírgulas ou clique no ícone no lado direito da barra de endereço para abrir a janela e siga as instruções para adicioná-los.

Após configurar, selecione menu  Board no menu Tools, abra o Boards Manager, procure por SG200X e clique em Install.


Neste ponto, o ambiente de desenvolvimento Duo no Arduino IDE foi instalado. Agora você pode escrever e testar o código.

Teste o pisca LED

Atualmente, o sistema de cartão SD do Duo precisa gravar firmware compatível com Arduino. Faça download do firmware com o prefixo arduino da versão mais recente do firmware.

Consulte Inicialize o Duo para instalar o sistema de cartão SD.

No caso 

arduino-milkv-duo256m-sd-v1.1.2-2024-0801.img.zip



Após Boot, LED deve piscar

Use um cabo USB para conectar o Duo ao computador e o Duo ligará automaticamente.

O firmware padrão do Duo, o sistema Linux de núcleo grande, controlará o piscar do LED integrado. Isto é conseguido através do script de inicialização. Agora vamos usar o Arduino de núcleo pequeno para acender o LED. Precisamos desabilitar o script de LED piscando no Linux de núcleo grande. No terminal Execute in do Duo:

mv /mnt/system/blink.sh /mnt/system/blink.sh_backup && sync

Ou seja, renomeie o script de LED piscando. Após reiniciar o Duo, o LED não piscará mais:

reboot

Neste momento, haverá um dispositivo serial adicional na “Porta” do “Gerenciador de Dispositivos” do computador.



Na interface principal do Arduino IDE, clique em Select Board e, em seguida, clique em Select other board and port...


Procure por "duo", selecione Duo Dev Module para Duo, selecione Duo256 Dev Module para Duo256M, selecione a porta serial correspondente na porta e clique em OK.


Abra o programa Examples01.BasicsBlink  de teste no menu File do Arduino IDE. A função deste programa é piscar o LED integrado do dispositivo Arduino. In Duo Também é compatível. Pode ser necessário instalar o pyserial para fazer o upload e, em seguida, vamos clicar no botão Upload para testar:



Neste momento, você pode ver o LED da placa Duo piscando em intervalos de 1 segundo

2. Duo Arduino pin resource

Duo


SPIPWMI2CUARTGPIONAMEPINPINNAMEGPIOADC
1GP0
1
40
VBUS
2GP1
2
39
VSYS
GND
3
38
GND
PWM7GP2
4
37
3V3_EN
PWM6GP3
5
36
3V3(OUT)
PWM5UART3_TXGP4
6
35
PWM6UART3_RXGP5
7
34
GND
8
33
GND
SPI2_SCKPWM9I2C3_SDAGP6
9
32
GP27
SPI2_MOSIPWM8I2C3_SCLGP7
10
31
GP26ADC1
SPI2_MISOPWM7I2C1_SDAGP8
11
30
RUN
SPI2_CSnPWM4I2C1_SCLGP9
12
29
GP22
GND
13
28
GND
PWM10I2C2_SDA14GP10
14
27
GP2127
PWM11I2C2_SCL15GP11
15
26
GP2026
PWM4GP12
16
25
GP1925
PWM5GP13
17
24
GP1824
GND
18
23
GND
19GP14
19
22
GP1722
20GP15
20
21
GP1621
 
0
LED


Duo256M


SPIPWMI2CUARTGPIONAMEPINPINNAMEGPIOADC
1GP0
1
40
VBUS
2GP1
2
39
VSYS
GND
3
38
GND
PWM7GP2
4
37
3V3_EN
PWM6GP3
5
36
3V3(OUT)
PWM5UART3_TXGP4
6
35
PWM6UART3_RXGP5
7
34
GND
8
33
GND
SPI2_SCKPWM9I2C3_SDAGP6
9
32
GP27
SPI2_MOSIPWM8I2C3_SCLGP7
10
31
GP26ADC1
SPI2_MISOPWM7I2C1_SDAGP8
11
30
RUN
SPI2_CSnPWM4I2C1_SCLGP9
12
29
GP22
GND
13
28
GND
PWM10I2C2_SDA14GP10
14
27
GP2127
PWM11I2C2_SCL15GP11
15
26
GP2026
PWM4GP12
16
25
GP1925
PWM5GP13
17
24
GP1824
GND
18
23
GND
19GP14
19
22
GP1722
20GP15
20
21
GP1621
 
0
LED

3. Como fazer o Arduino chamar o SHELL do Linux

No site oficial do milkV DUO há um exemplo escrito em C para comunicar o núcleo principal do DUO com o núcleo secundário onde um aplicativo arduino é executado. Aqui estão as notas desse primeiro contato que tive com a comunicação entre os núcleos através do módulo de caixa de correio e do DUO, o aplicativo fornecido é suficiente para entender e escrever seus próprios programas para enviar dados ou comandos do núcleo principal para o núcleo secundário. Mas surgem as seguintes perguntas: como faço para enviar dados do processador secundário para o processador principal? E se, em vez de usar C no processador principal, eu quiser usar Python? Você não encontrará respostas para essas perguntas no site oficial do fabricante ou perguntando diretamente no fórum DUO, pelo menos a partir da data de publicação destas notas.

Nota: Se alguém encontrar as fontes de mailbox.h e mailbox.cpp do exemplo do Arduino, diga-o nos comentários do vídeo.

Solução para o problema

Enquanto o problema com as bibliotecas de caixa de correio não for resolvido, existe uma solução muito simples, mas totalmente funcional, que também é independente da linguagem de programação que usamos nos processadores principal e secundário e que é comunicar os dois processadores através de UART, o milkV DUO tem até 5 UARTs, então não vejo problema em usar este sistema para esse fim.

Como isso é feito? 

Primeiro nos conectamos por SSH ao nosso DUO e executamos o seguinte comando:

dmesg|grep -i tty

Obteremos o seguinte:

[ 0.000000] Kernel command line: root=/dev/mmcblk0p2 rootwait rw console=ttyS0,115200 earlycon=sbi riscv.fwsz=0x80000 loglevel=9

[ 0.481564] printk: console [ttyS0] disabled

[ 0.486095] 4140000.serial: ttyS0 at MMIO 0x4140000 (irq = 15, base_baud = 1562500) is a 16550A

[ 0.495226] printk: console [ttyS0] enabled

[ 0.514108] 4150000.serial: ttyS1 at MMIO 0x4150000 (irq = 16, base_baud = 1562500) is a 16550A

[ 0.524062] 4160000.serial: ttyS2 at MMIO 0x4160000 (irq = 17, base_baud = 1562500) is a 16550A

[ 0.534049] 4170000.serial: ttyS3 at MMIO 0x4170000 (irq = 18, base_baud = 1562500) is a 16550A

[ 0.544061] 41c0000.serial: ttyS4 at MMIO 0x41c0000 (irq = 19, base_baud = 1562500) is a 16550A

A partir daqui, podemos concluir que a porta ttyS0 está associada ao console do sistema, além disso, esta porta é mapeada para o UART0 da placa (Tx--> Pin16 e Rx--> Pin17) se você conectar um conversor USB para serial, como o FTDI232 (3.3V) e um cliente como CuteCom, poderemos ver em nosso PC o processo de inicialização do DUO, bem como fazer login e acessar o sistema, bem como do que se fosse uma conexão SSH.

Por outro lado, sabemos de acordo com a documentação do DUO que o UART3 é aquele que é configurado por padrão para o aplicativo Arduino que roda no núcleo secundário. Portanto, para enviar dados do processador secundário, devemos unir com uma ponte Tx (Pin6) do UART3 com Rx (Pin17) do UART0, mas primeiro devemos "desanexar" o UART0 do console do sistema e deixá-lo livre para os aplicativos do usuário.

Pino 1 é utilizado para Log.

Para fazer isso, executamos o seguinte comando para editar o arquivo inittab encontrado no diretório /etc:

vi /etc/inittab

Devemos buscar o seguinte parágrafo

# Put a getty on the serial port

#console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL

console::respawn:/sbin/getty -L console 115200 vt100 -n -l /usr/local/bin/autologin

E comentar a última linha

# Put a getty on the serial port

#console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL

#console::respawn:/sbin/getty -L console 115200 vt100 -n -l /usr/local/bin/autologin

Agora podemos enviar dados do processador secundário (arduino) para o processador principal neste exemplo através de um script em Python, mas seria tão fácil fazer a aplicação em C, aqui está o código do exemplo em Python e arduino:

Código arduino

Basicamente ele envia um comando SHELL ls para listar arquivos da pasta root

// the setup function runs once when you press reset or power the board void setup() { Serial.begin(9600); //Conectado no RX do Console - SHELL Serial1.begin(9600); //Log } // the loop function runs over and over again forever void loop() { Serial.println("ls"); //Conectado no RX do Console delay(5000); if(Serial.available() >= 0) { while(!(Serial.available()==0)) Serial1.write(Serial.read()); } }







Este programa implementa manda pela serial UART o comando ls, o qual será processado pelo outro núcleo (SHELL). 

O resultado é enviado por outra serial UART1.

Código Python
import serial import subprocess # Set up serial connection (adjust settings for your specific device) ser = serial.Serial( port='/dev/ttyS0', # Change this to your serial port baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1 # 1 second timeout ) # Function to execute shell commands def execute_shell_command(command): try: # Run the command and capture output result = subprocess.run(command, shell=True, capture_output=True, text=True) return result.stdout if result.stdout else result.stderr except Exception as e: return str(e) # Main loop to act as a proxy between serial and shell while True: # Read from serial if ser.in_waiting > 0: serial_input = ser.readline().decode('ascii', errors='ignore').strip() #print(f"Received from serial: {serial_input}") # Execute the command received from serial if serial_input: output = execute_shell_command(serial_input) print(f"Command output: {output}") # Send result back to serial ser.write(output.encode('utf-8') + b'\r')


Este programa implementa aguarda pela serial o comando ls, o qual será processado acionado para ser executado pelo SHELL.

Compilação e Transferência


Execução (Python)


Execução (Arduino)


Que tal chamar o curl ? :)

Ref:


A SMARTCORE FORNECE CHIPS E MÓDULOS PARA IOT, COMUNICAÇÃO WIRELESS, BIOMETRIA, CONECTIVIDADE, RASTREAMENTO E AUTOMAÇÃO. NOSSO PORTFÓLIO INCLUI MODEM 2G/3G/4G/NB-IOT, SATELITAL, MÓDULOS WIFI, BLUETOOTH, GPS, SIGFOX, LORA, LEITOR DE CARTÃO, LEITOR QR CCODE, MECANISMO DE IMPRESSÃO, MINI-BOARD PC, ANTENA, PIGTAIL, BATERIA, REPETIDOR GPS E SENSORES. 

Nenhum comentário:

Postar um comentário