🛠 Maîtriser les E/S sur Sapphire RV64 : GPIO et Protocoles

Efinix Sapphire RV64 : SoC RISC-V 64 bits configurable pour 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.

Objectifs

Ce tutoriel vise à implémenter une chaîne d'acquisition de données utilisant les interfaces natives du SoC Sapphire RV64. Nous explorerons la configuration des GPIO pour le contrôle de périphériques simples et l'utilisation des maîtres I2C/SPI pour communiquer avec des capteurs ou affichages. L'accent est mis sur l'optimisation des accès mémoire via le bus AXI4 et la gestion des interruptions.

Matériel nécessaire

Étapes

  1. Configuration du SoC dans Efinity : Ouvrez votre projet et accédez à la configuration du cœur VexiiRiscv. Activez les interfaces souhaitées. Notez que le Sapphire RV64 supporte jusqu'à 32 GPIO, 5 maîtres I2C et 3 maîtres SPI. Assurez-vous que les adresses de base des périphériques (ex: 0x01000000 pour GPIO) sont définies sans conflit dans la carte mémoire.
  1. Génération du bitstream : Compilez le projet pour générer le bitstream. Vérifiez que le synthétiseur ne rapporte pas de conflits de broches. Si vous utilisez la mémoire externe DDR3 ou LPDDR4x, assurez-vous que le contrôleur mémoire est correctement initialisé dans le bootloader.
  1. Développement du driver GPIO : Dans votre code C/C++, définissez les registres de contrôle. Par exemple, pour configurer une broche en sortie :
#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);
}

Utilisez les instructions atomiques (extension A) si plusieurs cœurs accèdent aux mêmes GPIO pour éviter les conditions de course.

  1. Implémentation du protocole I2C/SPI : Pour un capteur I2C, configurez le maître I2C via ses registres de statut et de données. Le bus AXI4/APB3 gère les transactions. Exemple d'écriture d'un octet :
#define I2C_BASE 0x02000000
void i2c_write(uint8_t addr, uint8_t data) {
    // Attendre que le bus soit 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. Gestion des interruptions : Configurez le contrôleur d'interruptions pour réagir aux événements matériels (ex: fin de transfert SPI). Cela libère le CPU pour d'autres tâches, crucial avec le pipeline à 7 étages.

Vérification

Utilisez un analyseur logique pour vérifier les signaux sur les broches physiques. Sur le logiciel, imprimez les valeurs lues du capteur via UART. Vérifiez que les points d'arrêt matériels (jusqu'à 4 disponibles) fonctionnent correctement si vous déboguez le code du driver.

Pour aller plus loin

Explorez l'utilisation du cache L2 partagé pour accélérer l'accès aux tampons de données. Testez la MMU SV39 pour isoler les drivers dans l'espace utilisateur sous Linux si le système d'exploitation est déployé.

Autres tutoriels pour cette carte

Exemples de code pour cette carte

← Retour à la fiche 🛠 Tous les tutoriels