🛠 Automatisation simple avec l'UART sur Sapphire RV64
Objectifs
Ce tutoriel vise à comprendre l'interaction entre le logiciel embarqué et le matériel sur le SoC Efinix Sapphire RV64. Nous allons configurer un périphérique UART pour transmettre des messages textuels. Bien que le sujet mentionne l'automatisation, pour un niveau débutant, nous nous concentrons sur la communication sérialisée, base essentielle de tout système d'automatisation ou de supervision. Vous apprendrez à initialiser les registres du périphérique et à envoyer des chaînes de caractères.
Matériel nécessaire
- Carte FPGA Efinix compatible (gamme Titanium, Topaz ou Trion T20 ou supérieur).
- Câble USB pour la programmation et la communication série.
- Logiciel Efinity 2026.1 ou plus récent.
- Terminal série (comme PuTTY, Minicom ou l'outil intégré Efinity).
- Conception Sapphire RV64 générée avec au moins 1 UART maître activé.
Étapes
- Ouvrez votre projet Efinity contenant la configuration Sapphire RV64. Assurez-vous que le bloc IP UART est inclus dans la conception et connecté au bus AXI4/APB3.
- Générez le bitstream et programmez le FPGA. Vérifiez que le cœur VexiiRiscv est actif.
- Ouvrez votre environnement de développement (IDE) pour RISC-V. Créez un nouveau projet C/C++.
- Définissez les adresses mémoire des registres UART. Ces adresses sont fournies par le fichier de description matérielle généré par Efinity. Par exemple :
#define UART_BASE 0x40000000
#define UART_DATA (UART_BASE + 0x00)
#define UART_STATUS (UART_BASE + 0x08)
#define UART_CTRL (UART_BASE + 0x10)
- Écrivez une fonction d'attente pour vérifier que le tampon d'émission est vide avant d'envoyer un octet :
void uart_wait_tx_ready() {
while ((*(volatile unsigned int*)UART_STATUS & 0x1) == 0) {
// Attente active
}
}
- Implémentez la fonction d'envoi de caractère :
void uart_putc(char c) {
uart_wait_tx_ready();
*(volatile unsigned int*)UART_DATA = (unsigned int)c;
}
- Créez une fonction pour envoyer une chaîne complète :
void uart_puts(const char *str) {
while (*str) {
uart_putc(*str++);
}
}
- Dans le
main(), initialisez le contrôleur UART (réglez le diviseur de baudrate selon votre fréquence d'horloge, ex: 115200 bauds) et envoyez un message :
int main() {
// Initialisation simplifiée (adaptez selon vos registres)
*(volatile unsigned int*)UART_CTRL = 0x1;
uart_puts("Sapphire RV64: System Ready\n");
while(1);
}
- Compilez le code pour l'architecture RV64IMACFD. Utilisez les flags de compilation adaptés à votre configuration de cœur (avec ou sans FPU).
- Chargez le binaire sur le FPGA via le débogueur JTAG ou le bootloader.
Vérification
Ouvrez un terminal série connecté à l'UART de la carte. Configurez la vitesse à 115200 bauds (8N1). Si la configuration est correcte, vous devriez voir s'afficher le message "Sapphire RV64: System Ready". L'absence de message indique une erreur d'adresse mémoire, de configuration de baudrate ou de brochage UART.
Pour aller plus loin
Explorez l'utilisation des interruptions pour améliorer l'efficacité CPU. Intégrez ensuite un capteur via I2C (disponible sur la carte) pour lire des données et les transmettre via UART, créant ainsi un premier système d'acquisition de données automatisé.
Autres tutoriels pour cette carte
Exemples de code pour cette carte
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