🛠 Dominar E/S en Sapphire RV64: GPIO y Protocolos

Efinix Sapphire RV64: SoC RISC-V de 64 bits configurable para FPGA · avance · Configurez et pilotez les interfaces périphériques avancées (GPIO, I2C, SPI) du SoC Sapphire RV64 pour des interactions matérielles complexes.

Objetivos

Este tutorial tiene como objetivo implementar una cadena de adquisición de datos utilizando las interfaces nativas del SoC Sapphire RV64. Exploraremos la configuración de GPIO para el control de dispositivos simples y el uso de maestros I2C/SPI para comunicarse con sensores o pantallas. El enfoque está en la optimización del acceso a la memoria a través del bus AXI4 y la gestión de interrupciones.

Hardware Necesario

Pasos

  1. Configuración del SoC en Efinity: Abra su proyecto y acceda a la configuración del núcleo VexiiRiscv. Habilite las interfaces deseadas. Tenga en cuenta que Sapphire RV64 soporta hasta 32 GPIO, 5 maestros I2C y 3 maestros SPI. Asegúrese de que las direcciones base de los periféricos (ej: 0x01000000 para GPIO) estén definidas sin conflictos en el mapa de memoria.
  1. Generación del bitstream: Compile el proyecto para generar el bitstream. Verifique que el sintetizador no reporte conflictos de pines. Si utiliza memoria externa DDR3 o LPDDR4x, asegúrese de que el controlador de memoria esté correctamente inicializado en el bootloader.
  1. Desarrollo del driver GPIO: En su código C/C++, defina los registros de control. Por ejemplo, para configurar un pin como salida:
#define GPIO_BASE 0x01000000
#define GPIO_DIR (GPIO_BASE + 0x00)
#define GPIO_OUT (GPIO_BASE + 0x04)

void gpio_set_output(int pin) {
    *(volatile uint32_t*)GPIO_DIR |= (1 << pin);
}

Utilice instrucciones atómicas (extensión A) si múltiples núcleos acceden a los mismos GPIO para evitar condiciones de carrera.

  1. Implementación del protocolo I2C/SPI: Para un sensor I2C, configure el maestro I2C a través de sus registros de estado y datos. El bus AXI4/APB3 gestiona las transacciones. Ejemplo de escritura de un byte:
#define I2C_BASE 0x02000000
void i2c_write(uint8_t addr, uint8_t data) {
    // Esperar a que el bus esté libre
    while (*(volatile uint32_t*)(I2C_BASE + 0x04) & 0x01);
    *(volatile uint32_t*)(I2C_BASE + 0x08) = addr;
    *(volatile uint32_t*)(I2C_BASE + 0x0C) = data;
    *(volatile uint32_t*)(I2C_BASE + 0x00) = 0x01; // Start
}
  1. Gestión de interrupciones: Configure el controlador de interrupciones para reaccionar a eventos de hardware (ej: fin de transferencia SPI). Esto libera la CPU para otras tareas, crucial con el pipeline de 7 etapas.

Verificación

Utilice un analizador lógico para verificar las señales en los pines físicos. En el software, imprima los valores leídos del sensor mediante UART. Verifique que los puntos de interrupción de hardware (hasta 4 disponibles) funcionen correctamente si depura el código del driver.

Para ir más allá

Explore el uso de la caché L2 compartida para acelerar el acceso a los búferes de datos. Pruebe la MMU SV39 para aislar los drivers en el espacio de usuario bajo Linux si se despliega el sistema operativo.

Otros tutoriales para esta placa

Ejemplos de código para esta placa

← Volver a la ficha 🛠 Todos los tutoriales