Débogage JTAG
Hazard3 comprend un RISC-V Debug Module et un Debug Transport Module. Sur les
cartes ECP5, Hazard3 expose le DTM RISC-V via le TAP JTAG de la puce ECP5 et la
primitive JTAGG. OpenOCD voit donc d’abord le TAP ECP5 physique, puis utilise
les instructions privées ER1/ER2 de l’ECP5 pour atteindre DTMCS et DMI de
Hazard3.
Pour une explication du chemin matériel, des commandes abstraites, de l’injection d’instructions, de l’accès au bus système et des fonctions de débogage sélectionnées dans ce bitstream, voir Architecture de débogage RISC-V.
OpenOCD et GDB
GDB se connecte à OpenOCD par TCP, normalement sur localhost:3333. GDB
n’ouvre pas directement l’adaptateur USB JTAG. Le pilote USB et la configuration
de l’adaptateur relèvent donc d’OpenOCD, tandis que
scripts/load-firmware.sh n’utilise GDB qu’après qu’OpenOCD a correctement
examiné la cible.
Pour ULX3S, le lanceur recommandé est :
./scripts/start-openocd.sh
Le lanceur est volontairement utilisable depuis WSL comme depuis Linux natif.
Sous Linux natif, il résout openocd depuis PATH. Sous WSL, il peut
utiliser le openocd.exe Windows fourni pour un checkout monté depuis
Windows lorsque l’interopérabilité WSL est disponible ; sinon, il utilise
OpenOCD Linux natif. Cela maintient les chemins du dépôt et le format de
l’exécutable cohérents avec l’environnement hôte.
Les configurations ULX3S du projet sont prévues pour fonctionner avec OpenOCD
Ubuntu 0.12.0 ainsi qu’avec les builds OpenOCD plus récents actuellement
utilisés par le projet. En particulier, l’orthographe de compatibilité
gdb_report_data_abort est acceptée par 0.12.0 ; les builds plus récents
peuvent afficher un avertissement de dépréciation tout en continuant de
l’accepter. Ne remplacez pas une installation OpenOCD de la distribution
uniquement pour supprimer cet avertissement.
Avec OpenOCD déjà lancé et aucun autre client GDB connecté :
./scripts/load-firmware.sh
Ou fournissez explicitement un ELF :
./scripts/load-firmware.sh /path/to/hazard3-boot-monitor.elf
Pour ULX3S 12F, après programmation de fpga_ulx3s_12f.bit, la commande de
second étage recommandée est :
./scripts/load-firmware-12f.sh
Elle réutilise OpenOCD si le port 3333 est déjà à l’écoute ; sinon elle lance le lanceur OpenOCD du projet, attend le serveur GDB, charge et vérifie le moniteur SDRAM propre à la carte puis arrête uniquement le processus OpenOCD qu’elle a lancé.
La forme sans argument désigne la sortie du build autonome
scripts/build.sh. Pour un build complet de carte, préférez le fichier de
commandes GDB propre à la cible afin de ne pas confondre le moniteur avec un ELF
construit pour une autre horloge ou un autre profil mémoire :
# ULX3S 85F
riscv-none-elf-gdb -batch -x scripts/gdb/load-ulx3s-85f-monitor.gdb
# ULX3S 12F
riscv-none-elf-gdb -batch -x scripts/gdb/load-ulx3s-12f-monitor.gdb
# ULX4M-LD 85F
riscv-none-elf-gdb -batch -x scripts/gdb/load-ulx4m-ld-85f-monitor.gdb
Chaque fichier sélectionne le moniteur sous le répertoire
build/<board>/monitor/ correspondant, arrête la cible, charge et vérifie
l’ELF avec compare-sections, règle $pc sur _start, relance le
processeur puis se déconnecte. N’utilisez pas un ELF générique ou ancien provenant
d’un autre build de carte : il peut s’exécuter tout en utilisant un diviseur UART,
une carte mémoire ou un protocole de chargement incorrect.
Lorsqu’un exécutable Windows .exe fourni est lancé depuis WSL, le shell reste
Bash. Utilisez des chemins comme ./bin/gdb/riscv-none-elf-gdb.exe et une
barre oblique inverse finale (\) pour continuer une commande Bash. La
syntaxe cmd.exe comme .\bin\... et la continuation ^ n’est valide
qu’après être entré explicitement dans cmd.exe ; collée directement dans WSL,
elle est interprétée comme des commandes Bash séparées ou altérées.
FT231X intégré à l’ULX3S
Sur ULX3S, le projet utilise la connexion USB/JTAG FT231X normale de la carte.
Le chemin OpenOCD ft232r actuel a été vérifié sous Windows avec WinUSB
et libusbK. WinUSB est pratique lorsque le même FT231X sert aussi au flasher
FPGA WebUSB de Hazard3-Doom. L’association FTDI VCP/D2XX par défaut est destinée
aux outils FTDI natifs tels que fujprog sous Windows et n’est pas le chemin
libusb d’OpenOCD.
Si OpenOCD Windows signale LIBUSB_ERROR_NOT_SUPPORTED puis
ft232r not found: vid=0403, pid=6015, le FT231X est normalement encore lié
à FTDIBUS/D2XX. Utilisez Zadig pour sélectionner WinUSB ou libusbK pour le
périphérique ULX3S avant de lancer OpenOCD. Si le FPGA a d’abord été programmé
avec fujprog sous Windows, rappelez-vous que fujprog utilise le pilote
FTDI natif ; passer de l’un de ces outils hôtes à l’autre peut donc nécessiter
un changement de pilote.
Voir Flasher FPGA WebUSB pour la matrice de compatibilité des pilotes ULX3S.
Un démarrage OpenOCD sain sur ULX3S 85F contient une sortie similaire à :
JTAG tap: lfe5u85.hazard3 tap/device found: 0x41113043
Examined RISC-V core; found 1 harts
hart 0: XLEN=32
Listening on port 3333 for gdb connections
Dans une VM, une transaction USB initiale peut parfois signaler
LIBUSB_ERROR_TIMEOUT ou une interrogation JTAG entièrement nulle. Jugez
l’état final et pas seulement le premier avertissement : si OpenOCD examine
ensuite le cœur RISC-V et ouvre le port 3333, le serveur de débogage est
utilisable. Un redémarrage immédiat et propre est une bonne confirmation. Si le
TAP/cœur n’est jamais trouvé, vérifiez que le FT231X est attaché à l’invité, que
le flasher FPGA du navigateur est déconnecté et qu’aucun autre processus ne
possède l’interface JTAG.
ULX3S avec Tigard externe
Tigard peut être utilisé à la place du FT231X intégré. C’est particulièrement utile pour comparer des adaptateurs de débogage, éviter de modifier le pilote du FT231X ou utiliser le chemin JTAG MPSSE plus rapide du FT2232H. Le câblage suit les brochages JTAG Tigard et ULX3S publiés ; qualifiez ce chemin d’adaptateur externe sur la carte cible avant de le considérer comme une configuration validée par le projet.
J4 est le connecteur JTAG externe physique, pas un contrôleur JTAG distinct. Ses
signaux TCK, TMS, TDI et TDO sont reliés au TAP JTAG matériel de
la puce ECP5. Ce sont des broches JTAG dédiées, et non des GPIO utilisateur
ordinaires ; le chemin de débogage Hazard3 ECP5 ne les route donc pas via des
contraintes LPF LOCATE normales. Le LPF de référence ULX3S laisse également
ces sites dédiés commentés comme GPIO utilisateur.
Lorsque Hazard3 est configuré pour le transport de débogage ECP5, le chemin est le suivant :
Tigard / FT2232H
|
v
ULX3S J4
|
v
ECP5 hard JTAG TAP
|
v
JTAGG
|
v
Hazard3 ECP5 JTAG DTM
|
v
RISC-V Debug Module
|
v
Hazard3 CPU
JTAGG est la connexion du fabric FPGA au TAP ECP5 existant ; Hazard3 ne crée
pas un second TAP externe. Hazard3 mappe les registres de données RISC-V
DTMCS et DMI sur les hooks de registres utilisateur ER1 et ER2 de
l’ECP5, sélectionnés par les instructions 0x32 et 0x38. Les fonctions TAP
standard telles que IDCODE et BYPASS restent fournies par le TAP ECP5. C’est
également pourquoi OpenOCD identifie d’abord l’ECP5, puis utilise les
instructions privées pour atteindre le débogueur RISC-V.
Cela diffère du mode générique DTM_TYPE="JTAG" de Hazard3, dans lequel un
DTM JTAG RISC-V normal est connecté à quatre ports d’E/S utilisateur. Pour
ULX3S, le mode ECP5 instancie hazard3_ecp5_jtag_dtm et JTAGG en interne ;
J4 se connecte donc au TAP ECP5 et non directement à des broches JTAG RISC-V.
Reliez directement le connecteur JTAG de Tigard au J4 de l’ULX3S :
Tigard GND (pin 2, black) -> ULX3S J4 GND
Tigard TCK (pin 3, white) -> ULX3S J4 TCK
Tigard TDI (pin 4, grey) -> ULX3S J4 TDI
Tigard TDO (pin 5, purple) <- ULX3S J4 TDO
Tigard TMS (pin 6, blue) -> ULX3S J4 TMS
Tigard VTGT -> not connected
Tigard TRST / SRST -> not connected
JTAG externe ULX3S – J4 est le connecteur physique du TAP JTAG
matériel ECP5. Utilisez ses broches dédiées TCK, TDI, TDO et TMS pour la
connexion Tigard ; ce ne sont pas des GPIO FPGA ordinaires.
Réglez Tigard en mode SPI/JTAG et logique 3,3 V. Alimentez normalement
l’ULX3S par US1. Voir Brochages des cartes et câblage pour la disposition physique de J4 et les
précautions de câblage.
La partie adaptateur Tigard d’une configuration OpenOCD est :
adapter driver ftdi
transport select jtag
ftdi vid_pid 0x0403 0x6010
ftdi channel 1
ftdi layout_init 0x0038 0x003b
ftdi layout_signal nTRST -data 0x0010
ftdi layout_signal nSRST -data 0x0020
adapter speed 1000
La partie cible Hazard3 est la même que dans
openocd/ulx3s-openocd.cfg : le TAP ECP5 possède un registre d’instruction de
8 bits, et DTMCS/DMI de Hazard3 sont atteints par les instructions privées ECP5
0x32 et 0x38. Pour une ULX3S 85F, l’IDCODE ECP5 est 0x41113043. Une
carte 12F utilise 0x21111043 à la place.
Une fois qu’OpenOCD a signalé le TAP ECP5, examiné un hart RISC-V 32 bits et ouvert le port 3333, connectez le GDB RISC-V du projet à l’ELF. Avec l’exécutable GDB exact fourni par la toolchain RISC-V installée, le flux interactif est, conceptuellement :
$ riscv-none-elf-gdb path/to/hazard3-boot-monitor.elf
(gdb) target extended-remote localhost:3333
(gdb) monitor halt
(gdb) break main
(gdb) continue
(gdb) next
(gdb) stepi
(gdb) info registers
(gdb) continue
next et step opèrent au niveau source lorsque les informations de
débogage sont disponibles ; nexti et stepi opèrent instruction machine
par instruction machine. Il s’agit d’un véritable débogage pas à pas du cœur
RISC-V Hazard3 exécuté dans le FPGA. Tigard externe entre toujours par le TAP
JTAG ECP5 ; il ne se connecte pas directement à des broches RISC-V.
Débogage de l’ESP32 ULX3S intégré avec Tigard
L’ESP32 intégré est une cible JTAG totalement distincte de Hazard3. C’est un ESP32 Xtensa double cœur classique ; utilisez donc la prise en charge OpenOCD ESP32 d’Espressif et un GDB Xtensa, et non le GDB RISC-V utilisé pour Hazard3. Cette connexion est déduite du schéma/LPF ULX3S et des broches JTAG documentées par Espressif ; elle n’a pas encore été qualifiée par le projet sur ULX3S.
Le JTAG natif de l’ESP32 utilise :
TDI -> GPIO12 / MTDI
TCK -> GPIO13 / MTCK
TMS -> GPIO14 / MTMS
TDO <- GPIO15 / MTDO
Sur ULX3S, ces quatre signaux ESP32 sont partagés avec l’interface microSD. La connexion Tigard pratique les atteint donc via les signaux SD :
Tigard TDI (pin 4, grey) -> SD DAT2 -> ESP32 GPIO12
Tigard TCK (pin 3, white) -> SD DAT3 -> ESP32 GPIO13
Tigard TMS (pin 6, blue) -> SD CLK -> ESP32 GPIO14
Tigard TDO (pin 5, purple) <- SD CMD <- ESP32 GPIO15
Tigard GND (pin 2, black) -> board GND
Les contacts microSD correspondants sont DAT2 broche 1, DAT3 broche 2, CMD broche 3, CLK broche 5 et VSS/GND broche 6. Un breakout ou une rallonge est bien plus simple et plus sûr que de sonder directement les contacts du connecteur. Retirez la carte SD.
Avertissement
L’ECP5 est connecté aux mêmes signaux SD. Ne déboguez pas l’ESP32 sur ces
fils tant que le FPGA peut piloter le bus SD. Utilisez ou vérifiez une image
FPGA qui laisse SD_D2, SD_D3, SD_CLK et SD_CMD en haute
impédance. Le design Hazard3-Doom normal utilise la SD ; cette isolation doit
donc être réalisée délibérément avant de connecter Tigard.
Maintenir l’ESP32 en reset avec J3
Si des problèmes de carte SD sont rencontrés côté FPGA, le cavalier J3 de
l’ULX3S peut maintenir l’ESP32 en reset. J3 est un connecteur à 2 broches
qui met le signal EN de l’ESP32 à la masse lorsqu’il est court-circuité.
Cela désactive l’ESP32 et peut aider à l’isoler du bus SD partagé pendant le
diagnostic ou lorsque le FPGA doit avoir la propriété exclusive de la carte SD.
Cavalier ULX3S J3 (WIFI_OFF) – court-circuiter J3 tire le signal
EN de l’ESP32 à l’état bas et maintient l’ESP32 en reset/désactivé.
Le SRST de Tigard peut, en option, être connecté au côté WIFI_OFF/EN du
cavalier J3 de l’ULX3S pour un reset matériel. EN de l’ESP32 est un signal
d’activation actif à l’état haut ; le tirer à l’état bas réinitialise/désactive
la puce. Ne connectez pas le fil de reset au côté masse de J3, et ne connectez
pas VTGT de Tigard lorsque l’ULX3S est auto-alimentée.
Avec OpenOCD Espressif installé, la configuration est équivalente à :
openocd \
-f interface/ftdi/tigard.cfg \
-c "set ESP32_FLASH_VOLTAGE 3.3" \
-f target/esp32.cfg
Utilisez ensuite l’ELF produit par le build ESP32 :
$ xtensa-esp32-elf-gdb path/to/esp32-app.elf
(gdb) target remote localhost:3333
(gdb) monitor halt
(gdb) break app_main
(gdb) continue
(gdb) next
(gdb) stepi
Le réglage ESP32_FLASH_VOLTAGE est important car GPIO12/TDI est également
une entrée de strap de démarrage de l’ESP32. La configuration OpenOCD
d’Espressif utilise ce réglage de tension flash pour maintenir l’état inactif
de JTAG TDI adapté à une mémoire flash 3,3 V.
ULX4M-LD avec Tigard
La connexion DFU Micro-B de l’ULX4M est le chemin de configuration/bootloader du FPGA. Ce n’est pas l’adaptateur de débogage JTAG de Hazard3. Pour le débogage ULX4M-LD, utilisez un Tigard FT2232H externe.
Configuration Tigard connue comme fonctionnelle
Utilisez ces réglages :
Élément |
Réglage |
|---|---|
Sélecteur de mode Tigard |
|
Alimentation cible Tigard |
|
Tension de référence cible |
3,3 V |
USB VID:PID |
|
Canal FTDI OpenOCD |
|
Horloge JTAG |
1000 kHz |
Composant ECP5 |
LFE5UM-85F |
IDCODE ECP5 |
|
Instructions Hazard3 DTMCS/DMI |
|
L’IDCODE correct du LFE5UM-85F est 0x01113043. N’utilisez pas la valeur
0x41113043 associée à une autre variante de composant ECP5.
Séparation des pilotes Windows
Tigard expose deux interfaces USB FT2232H indépendantes. Configurez-les une fois et laissez-les ainsi :
Interface USB |
Canal FT2232H |
Pilote Windows |
Utilisation dans le projet |
|---|---|---|---|
Interface 0 |
A |
FTDI VCP |
Port COM UART |
Interface 1 |
B |
libusbK |
JTAG OpenOCD |
Cela permet d’utiliser PuTTY/Web Serial sur l’UART et OpenOCD JTAG en même temps ; il n’y a aucune raison de continuer à changer de pilote entre les deux. Si libusbK est installé par erreur sur Interface 0, le port COM UART disparaît. Restaurez Interface 0 sur le pilote FTDI USB Serial/VCP et laissez Interface 1 sur libusbK.
Appliquez libusbK à Tigard Interface 1 pour JTAG. Gardez Interface 0 sur le pilote FTDI VCP pour le port COM UART.
UART ULX4M-LD via Tigard
L’interface UART de Tigard est indépendante de son canal JTAG. Utilisez 115200 8N1, sans contrôle de flux. Sur le connecteur 40 broches de style Raspberry Pi du carrier Waveshare, le câblage confirmé est :
Tigard UART TX (yellow) -> physical pin 16 -> GPIO23 -> FPGA N4 -> uart_rx
Tigard UART RX (orange) <- physical pin 18 -> GPIO24 <- FPGA N3 <- uart_tx
Tigard GND -> physical pin 20
Tigard VCC -> not connected
TX et RX doivent être croisés exactement comme indiqué. Voir Brochages des cartes et câblage pour le brochage annoté du carrier ULX4M-LD.
Configuration OpenOCD ULX4M-LD
La configuration du projet est :
./bin/openocd.exe -d2 \
-f ./third_party/Hazard3/example_soc/ulx4m-openocd-tigard.cfg
Les valeurs importantes de la configuration sont équivalentes à :
adapter driver ftdi
ftdi vid_pid 0x0403 0x6010
ftdi channel 1
ftdi layout_init 0x0038 0x003b
ftdi layout_signal nTRST -data 0x0010
ftdi layout_signal nSRST -data 0x0020
transport select jtag
adapter speed 1000
set _CHIPNAME lfe5um85
jtag newtap $_CHIPNAME hazard3 \
-expected-id 0x01113043 \
-irlen 8 \
-irmask 0xFF \
-ircapture 0x5
set _TARGETNAME $_CHIPNAME.hazard3
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
riscv set_ir dtmcs 0x32
riscv set_ir dmi 0x38
gdb_report_data_abort enable
init
halt
Le câblage Tigard établi ne connecte pas de fil de reset cible. Ne comptez pas sur SRST/TRST pour réinitialiser ou démarrer le design ULX4M ; les entrées de layout FTDI restent dans la configuration de l’adaptateur, mais le reset n’est pas physiquement câblé à la cible dans cette configuration.
Une session saine atteint une sortie similaire à :
JTAG tap: lfe5um85.hazard3 tap/device found: 0x01113043
Examined RISC-V core; found 1 hart
XLEN=32
Listening on port 3333 for gdb connections
La valeur Hazard3 DTMCS connue comme correcte est 0x00004071.
Interpréter dtmcontrol is 0
Le TAP JTAG matériel de l’ECP5 peut renvoyer l’IDCODE de la puce même lorsque le bitstream utilisateur Hazard3 ne s’exécute pas. Cette combinaison est donc utile pour le diagnostic :
JTAG IDCODE = 0x01113043
dtmcontrol = 0
Elle prouve que le chemin JTAG physique Tigard-vers-ECP5 fonctionne, mais ne
prouve pas que la logique utilisateur Hazard3 JTAGG/DTM est active.
Avant de modifier le RTL DTM ou le câblage JTAG, confirmez que le bitstream
utilisateur ULX4M a réellement démarré. Si la carte est encore dans son
bootloader DFU, exécutez :
./bin/dfu-util.exe -a 0 -e
Puis réessayez OpenOCD. Dans la séquence de mise en route validée, quitter DFU de cette façon a démarré le design utilisateur, restauré l’UART Hazard3 et rendu la logique FPGA utilisateur disponible pour les tests suivants.
Si le design utilisateur s’exécute visiblement sur l’UART mais que DTMCS reste nul, utilisez le scan brut ECP5 ER1/DTMCS ou comparez avec un build OpenOCD connu comme fonctionnel avant de modifier le RTL Hazard3.
Construire et charger un moniteur adapté à l’horloge
Le profil FPGA ULX4M-LD actuellement qualifié exécute Hazard3/AHB à 40 MHz. Construisez un moniteur logiciel correspondant sans relancer le routage FPGA :
HAZARD3_BUILD_DIR="$PWD/build/ulx4m-ld-monitor-test/monitor" \
HAZARD3_MEMORY_PROFILE=64m \
HAZARD3_SYS_CLK_HZ=40000000 \
./scripts/build.sh
Puis, avec OpenOCD ayant déjà examiné la cible :
./scripts/load-firmware.sh \
./build/ulx4m-ld-monitor-test/monitor/hazard3-boot-monitor.elf
Un chargement réussi signale des sections .vectors, .text, données en
lecture seule et .data correspondantes avant de reprendre à l’adresse
0x00000040.
VisualGDB
Les utilisateurs Windows peuvent utiliser les fichiers du projet sous
VisualGDB/ avec Visual Studio. Le débogueur communique toujours avec la même
cible OpenOCD/GDB ; le chemin en ligne de commande reste donc le workflow de
référence. Déconnectez VisualGDB avant d’exécuter le chargeur batch de firmware,
car un seul client GDB doit posséder la cible OpenOCD à la fois.
Le script d’assistance au démarrage GDB est :
scripts/hazard3-debug.gdb
Dépannage
Si le module de débogage n’est pas détecté de manière fiable, distinguez d’abord l’accès au TAP physique de l’accès au DTM Hazard3. Un IDCODE ECP5 correct avec DTMCS nul est une panne différente d’un adaptateur incapable de lire l’IDCODE ECP5. Ne réduisez l’horloge JTAG qu’après avoir vérifié l’image FPGA active, la séparation des pilotes Tigard et les réglages d’alimentation/référence de la cible.
Voir Dépannage pour les problèmes courants liés à OpenOCD et à la propriété des interfaces.