Espace d’adressage des peripheriques APB
Hazard3-Doom expose ses peripheriques SoC a faible debit par un bus APB 32 bits
place derriere le bus systeme AHB-L de Hazard3. Les chargements et stockages CPU
dans la region 0x40000000 traversent le pont AHB-vers-APB puis sont decodes
par le separateur APB de
third_party/Hazard3/example_soc/soc/example_soc.v.
Les adresses de cette page appartiennent a l’integration SoC de Hazard3-Doom. Elles ne sont pas des adresses architecturales RISC-V et ne sont pas imposees par le CPU Hazard3.
Fenetres du decodeur APB
Le separateur APB expose actuellement six esclaves :
Peripherique |
Base CPU |
Fenetre du decodeur |
Interface RTL / logiciel |
|---|---|---|---|
Timer RISC-V |
|
|
|
UART |
|
|
|
GPIO |
|
|
|
SAO I2C/GPIO |
|
|
|
SPI micro-SD |
|
|
|
HDMI/video |
|
|
|
Les fenetres du decodeur sont plus grandes que les ensembles de registres implementes. Une adresse situee dans une fenetre decodee ne signifie pas qu’un registre existe a cette adresse. Le logiciel doit utiliser uniquement les offsets documentes ci-dessous.
La plage 0x4000B000-0x4000BFFF n’est affectee a aucun peripherique par le
separateur APB actuel.
Acces MMIO commun
Les exemples autonomes utilisent un acces 32 bits volatile simple :
#include <stdint.h>
#define MMIO32(address) \
(*(volatile uint32_t *)(uintptr_t)(address))
Les definitions partagees des exemples se trouvent dans
examples/common/hazard3_apb.h. Une definition centralisee reduit le risque
de divergence entre les exemples et la carte RTL.
Timer RISC-V - 0x40000000
Le timer fournit un compteur mtime 64 bits et un comparateur mtimecmp
64 bits sur le bus APB 32 bits. Hazard3-Doom fournit un tick d’une microseconde,
donc mtime compte les microsecondes lorsque le hart s’execute. Le compteur
s’arrete lorsque le hart est arrete par le debogueur.
Offset |
Adresse |
Registre |
Description |
|---|---|---|---|
|
|
|
Le bit 0 active le timer. Il est actif apres reset. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pour lire une valeur 64 bits coherente, verifiez que le mot haut n’a pas change autour de la lecture du mot bas :
static uint64_t timer_read_us(void)
{
uint32_t hi1;
uint32_t lo;
uint32_t hi2;
do {
hi1 = MMIO32(0x4000000cu);
lo = MMIO32(0x40000008u);
hi2 = MMIO32(0x4000000cu);
} while (hi1 != hi2);
return ((uint64_t)hi1 << 32) | lo;
}
Lors d’une mise a jour de mtimecmp, ecrivez d’abord 0xFFFFFFFF dans le
mot haut si une comparaison intermediaire intempestive serait genante, puis le
mot bas et enfin le mot haut definitif.
UART - 0x40004000
L’UART est le peripherique uart_mini de Hazard3-libfpga. Il fournit de petits
FIFO TX/RX, un diviseur fractionnaire, des interruptions optionnelles, CTS et un
mode loopback.
Offset |
Adresse |
Registre |
Champs importants |
|---|---|---|---|
|
|
|
bit 0 EN, bit 1 BUSY, bit 2 TXIE, bit 3 RXIE, bit 4 CTSEN, bit 8 LOOPBACK. |
|
|
|
bits 13:4 partie entiere, bits 3:0 partie fractionnaire. |
|
|
|
Etats niveau/plein/vide/erreur des FIFO TX et RX. |
|
|
|
Une ecriture des bits 7:0 pousse un octet dans le FIFO TX. |
|
|
|
Une lecture des bits 7:0 renvoie et retire un octet du FIFO RX. |
FSTAT utilise les champs suivants :
7:0 TXLEVEL
8 TXFULL
9 TXEMPTY
10 TXOVER sticky, ecrire 1 pour effacer
11 TXUNDER sticky, ecrire 1 pour effacer
23:16 RXLEVEL
24 RXFULL
25 RXEMPTY
26 RXOVER sticky, ecrire 1 pour effacer
27 RXUNDER sticky, ecrire 1 pour effacer
Avec le sur-echantillonnage normal 8x, le registre diviseur est une valeur a virgule fixe avec quatre bits fractionnaires :
baud ~= sys_clk / (8 * DIV)
DIV_register = round((sys_clk * 16) / (baud * 8))
Le chemin de lecture actuellement genere dans uart_regs.v renvoie la valeur
de reset du diviseur plutot que la valeur programmee. Le logiciel ne doit donc
pas utiliser la lecture de DIV pour verifier l’ecriture du debit.
Transmission bloquante minimale :
#define UART_FSTAT MMIO32(0x40004008u)
#define UART_TX MMIO32(0x4000400cu)
#define UART_TXFULL (1u << 8)
static void uart_putc(char c)
{
while ((UART_FSTAT & UART_TXFULL) != 0u) {
}
UART_TX = (uint8_t)c;
}
GPIO - 0x40008000
Le bloc GPIO contient actuellement un seul registre de sortie 8 bits.
Offset |
Adresse |
Registre |
Description |
|---|---|---|---|
|
|
|
Les bits 7:0 pilotent |
Seul l’octet bas d’une ecriture est conserve :
MMIO32(0x40008000u) = 0x55u;
Le wrapper de carte determine ce que chaque bit gpio_out pilote reellement
sur une cible FPGA donnee.
SAO I2C/GPIO - 0x40009000
Le peripherique SAO combine un moteur I2C pilote par logiciel, deux GPIO SAO, l’etat brut des lignes, des registres d’identification et l’etat de propriete ESP32/Hazard3.
Offset |
Adresse |
Registre |
Description |
|---|---|---|---|
|
|
|
Ecrire une commande I2C bas niveau. |
|
|
|
Resultat I2C, lignes, GPIO et propriete. |
|
|
|
Octet utilise par une commande WRITE. |
|
|
|
Dernier octet recu. |
|
|
|
Diviseur de timing I2C 16 bits. |
|
|
|
Timeout clock-stretch en cycles d’horloge systeme. |
|
|
|
Sorties/OE GPIO SAO et etat des entrees synchronisees. |
|
|
|
Etat synchronise brut SDA, SCL, GPIO1 et GPIO2. |
|
|
|
|
|
|
|
Version actuelle |
|
|
|
bit 0 proprietaire ESP, bit 1 requete ESP. |
Valeurs de COMMAND :
1 START
2 STOP
3 WRITE
4 READ_ACK
5 READ_NACK
6 RECOVER
7 ABORT
Bits de STATUS :
0 BUSY
1 DONE
2 ACK
3 NACK
4 TIMEOUT
5 REJECTED
6 BUS_ACTIVE
7 SDA
8 SCL
9 GPIO1
10 GPIO2
11 RECOVERED
12 ESP_OWNER
13 ESP_REQUEST
DONE, TIMEOUT, REJECTED et RECOVERED sont sticky. Ecrire un 1
dans le bit correspondant de STATUS efface le drapeau sticky.
Le diviseur I2C de reset est choisi a partir de l’horloge systeme pour viser environ 100 kHz. Le timeout clock-stretch de reset est de 10 ms.
SPI micro-SD - 0x4000A000
Le peripherique micro-SD est un petit maitre SPI mode 0 pilote par logiciel. Il travaille MSB en premier et n’a volontairement ni FIFO ni DMA.
Offset |
Adresse |
Registre |
Description |
|---|---|---|---|
|
|
|
bit 0 = |
|
|
|
Diviseur de demi-periode SPI 16 bits. |
|
|
|
Ecrire l’octet bas lance un transfert; lire l’octet bas donne la donnee recue. |
|
|
|
bit 0 BUSY. |
Horloge SPI :
SCLK = sys_clk / (2 * (CLKDIV + 1))
A 50 MHz, la valeur de reset 124 donne 200 kHz pour l’initialisation. La fenetre
APB existe meme si SD_SPI_ENABLE vaut false; dans ce cas l’integration
desactivee renvoie zero et laisse les sorties SD inactives.
Exemple de transfert d’un octet :
static uint8_t sd_spi_xfer(uint8_t tx)
{
while ((MMIO32(0x4000a00cu) & 1u) != 0u) {
}
MMIO32(0x4000a008u) = tx;
while ((MMIO32(0x4000a00cu) & 1u) != 0u) {
}
return (uint8_t)MMIO32(0x4000a008u);
}
Ne lancez pas de transferts arbitraires lorsqu’un autre composant logiciel utilise la carte ou pendant la validation du partage SD ESP32/FPGA sur ULX3S.
HDMI/video - 0x4000C000
Le bloc APB video controle et rapporte l’etat du chemin HDMI/video. Les pixels du framebuffer ne resident pas dans cette fenetre APB; ils se trouvent dans la reservation video de la memoire externe documentee dans Cartographie mémoire.
Offset |
Adresse |
Registre |
Description |
|---|---|---|---|
|
|
|
Etat mode, framebuffer, DMA et capacites. |
|
|
|
Controle indexed/buffer/present/direct/resolution. |
|
|
|
Selection d’entree de palette. |
|
|
|
Donnee de palette. |
|
|
|
Compteur de trames. |
|
|
|
Compteur diagnostique de cycles DMA. |
|
|
|
Nombre de presentations terminees. |
|
|
|
Identifiant carte/build FPGA. |
|
|
|
Etat controleur/adaptateur de memoire externe. |
|
|
|
Identifiant du coeur memoire externe. |
|
|
|
Identifiant de l’adaptateur memoire Hazard3. |
|
|
|
Adresse/controle d’ecriture video directe. |
|
|
|
Donnee d’ecriture video directe. |
Bits importants de STATUS :
0 FRONT_BUFFER
1 PRESENT_PENDING
2 INDEXED
3 VBLANK
4 SDRAM_READY
5 FRAME_VALID
6 INTERNAL_BUFFER
7 DMA_BUSY
8 SWAP_PENDING
9 DIRECT_SUPPORTED
10 DIRECT_WRITE_BUSY
11 HIGH_RES_SUPPORTED
12 HIGH_RES_ACTIVE
13 GUI_RES_SUPPORTED
14 GUI_RES_ACTIVE
CONTROL utilise actuellement :
0 INDEXED
1 BUFFER1
2 PRESENT
3 DIRECT
4 HIGH_RES
5 GUI_RES
Utilisez doom/hazard3_video.h comme source de verite pour les bits video
visibles par logiciel et la disposition des framebuffers associes.
Exemples APB autonomes
Deux exemples bare-metal sont fournis dans examples/. Ils ne sont lies ni
au moniteur resident ni a Doom.
examples/apb-register-dumpInitialise l’UART et affiche un instantane non destructif des six peripheriques APB. Il ne lance aucune transaction SAO ou SD, ne modifie pas les sorties GPIO et ne change pas l’etat video.
examples/apb-uart-timerDemontre activement le timer et l’UART. Il active le timer, lit
mtime, attend un million de ticks d’une microseconde, affiche le temps ecoule puis passe en echo UART jusqu’a la reception deqouQ.
Les deux exemples partagent les definitions de registres et le demarrage minimal
dans examples/common/. Chaque exemple peut etre compile independamment.
Compiler les exemples
Depuis Bash ou WSL a la racine du depot :
make -C examples
Ou pour un seul exemple :
make -C examples/apb-register-dump
make -C examples/apb-uart-timer
Le build suppose par defaut une horloge systeme Hazard3 de 50 MHz et un UART a 115200 bauds. Pour une cible 40 MHz telle que les profils ULX4M-LD ou ULX3S 12F normaux :
make -C examples SYS_CLK_HZ=40000000
Les makefiles suivent les memes conventions de toolchain que le projet
principal. Ils honorent d’abord TOOLCHAIN_PREFIX, acceptent aussi
CROSS_COMPILE, reconnaissent l’ancien emplacement
/opt/riscv/bin/riscv32-unknown-elf- et utilisent sinon
riscv-none-elf-* dans PATH. L’installateur complet normal place le
compilateur xPack dans PATH. Une installation locale sous
bin/riscv-gcc reste disponible comme solution de compatibilite. Les outils
Windows .exe sont detectes automatiquement lorsque leur chemin est visible
depuis Bash/WSL; EXEEXT=.exe peut aussi etre defini explicitement.
Chaque exemple produit .elf, .bin, .map et .lst dans son
repertoire local build/. Ces fichiers generes ne doivent pas etre commits.
Execution avec OpenOCD/GDB
Les exemples sont lies a 0x20100000, debut normal de la fenetre executable
Doom. Cela les garde hors du moniteur resident et fonctionne avec les profils
logiciels 32 MiB et 64 MiB.
Le controleur de memoire externe doit deja etre initialise. Demarrez le moniteur resident normal, verifiez que la memoire externe est prete, lancez la session OpenOCD Hazard3 normale, puis connectez GDB sans reset de l’FPGA ou du hart.
Pour apb-register-dump :
riscv-none-elf-gdb examples/apb-register-dump/build/apb-register-dump.elf
(gdb) target extended-remote :3333
(gdb) monitor halt
(gdb) load
(gdb) set $pc = _start
(gdb) continue
Utilisez la meme sequence avec l’autre ELF. Comme l’exemple remplace
l’executable normal a 0x20100000, rechargez Doom avant de le relancer.
Important
N’effectuez pas de reset cible juste avant le chargement. Un reset peut ramener le systeme avant l’initialisation SDRAM/DDR alors que ces ELF s’executent en memoire externe.
Fichiers source de reference
Lors d’une modification du SoC, verifiez cette page et
examples/common/hazard3_apb.h par rapport aux implementations suivantes :
third_party/Hazard3/example_soc/soc/example_soc.v- decodeur APB.third_party/Hazard3/example_soc/soc/peri/hazard3_riscv_timer.v- timer.third_party/Hazard3/example_soc/libfpga/peris/uart/uart_regs.v- registres UART.third_party/Hazard3/example_soc/soc/apb_gpio.v- GPIO.third_party/Hazard3/example_soc/soc/apb_sao_bridge.v- SAO.third_party/Hazard3/example_soc/soc/apb_sd_spi.v- SPI SD.doom/hazard3_video.h- definitions video visibles par logiciel.