🛠 Automatización simple con UART en Sapphire RV64
Objetivos
Este tutorial tiene como objetivo comprender la interacción entre el software embebido y el hardware en el SoC Efinix Sapphire RV64. Configuraremos un periférico UART para transmitir mensajes de texto. Aunque el tema menciona la automatización, para un nivel principiante, nos centramos en la comunicación serie, la base esencial de cualquier sistema de automatización o supervisión. Aprenderá a inicializar los registros del dispositivo y a enviar cadenas de caracteres.
Equipo necesario
- Tarjeta FPGA Efinix compatible (gama Titanium, Topaz o Trion T20 o superior).
- Cable USB para programación y comunicación serie.
- Software Efinity 2026.1 o más reciente.
- Terminal serie (como PuTTY, Minicom o la herramienta integrada Efinity).
- Diseño Sapphire RV64 generado con al menos 1 maestro UART activado.
Pasos
- Abra su proyecto Efinity que contiene la configuración Sapphire RV64. Asegúrese de que el bloque IP UART esté incluido en el diseño y conectado al bus AXI4/APB3.
- Genere el bitstream y programe el FPGA. Verifique que el núcleo VexiiRiscv esté activo.
- Abra su entorno de desarrollo (IDE) para RISC-V. Cree un nuevo proyecto C/C++.
- Defina las direcciones de memoria de los registros UART. Estas direcciones son proporcionadas por el archivo de descripción de hardware generado por Efinity. Por ejemplo:
#define UART_BASE 0x40000000
#define UART_DATA (UART_BASE + 0x00)
#define UART_STATUS (UART_BASE + 0x08)
#define UART_CTRL (UART_BASE + 0x10)
- Escriba una función de espera para verificar que el búfer de transmisión esté vacío antes de enviar un byte:
void uart_wait_tx_ready() {
while ((*(volatile unsigned int*)UART_STATUS & 0x1) == 0) {
// Espera activa
}
}
- Implemente la función de envío de carácter:
void uart_putc(char c) {
uart_wait_tx_ready();
*(volatile unsigned int*)UART_DATA = (unsigned int)c;
}
- Cree una función para enviar una cadena completa:
void uart_puts(const char *str) {
while (*str) {
uart_putc(*str++);
}
}
- En
main(), inicialice el controlador UART (ajuste el divisor de baudrate según su frecuencia de reloj, ej: 115200 baudios) y envíe un mensaje:
int main() {
// Inicialización simplificada (adapte según sus registros)
*(volatile unsigned int*)UART_CTRL = 0x1;
uart_puts("Sapphire RV64: System Ready\n");
while(1);
}
- Compile el código para la arquitectura RV64IMACFD. Utilice banderas de compilación adaptadas a su configuración de núcleo (con o sin FPU).
- Cargue el binario en el FPGA mediante el depurador JTAG o el bootloader.
Verificación
Abra un terminal serie conectado al UART de la tarjeta. Configure la velocidad a 115200 baudios (8N1). Si la configuración es correcta, debería ver el mensaje "Sapphire RV64: System Ready". La ausencia de mensaje indica un error de dirección de memoria, configuración de baudrate o mapeo de pines UART.
Para ir más allá
Explore el uso de interrupciones para mejorar la eficiencia de la CPU. Luego, integre un sensor vía I2C (disponible en la tarjeta) para leer datos y transmitirlos vía UART, creando así un primer sistema de adquisición de datos automatizado.
Otros tutoriales para esta placa
- Puesta en marcha de la placa Sapphire RV64
- Controlar GPIOs en Sapphire RV64
- Puesta en marcha de Sapphire RV64 en FPGA Efinix
- Configuración de GPIO y control de periféricos en Sapphire RV64
- Despliegue de un nodo IoT con Sapphire RV64: Red y Almacenamiento
- Puesta en marcha del SoC Sapphire RV64 en FPGA Efinix
Ejemplos de código para esta placa
gpio_blink_riscv.inoC (RISC-V)uart_echo_riscv.inoC (RISC-V)spi_sensor_read.inoC (RISC-V)i2c_master_write.inoC (RISC-V)timer_interrupt_handler.inoC (RISC-V)i2c-bmp280-temperature-6.inoC