Plateforme CALF: Organisation mémoire
Adresses
Au sein de la plateforme CALF, les adresses émises par le processeur sont utilisées pour rediriger les requêtes. Ainsi, selon les valeurs, certaines sont envoyées vers la mémoire RAM, les registres GPIO8, l’UART etc. La table ci-dessous présente les valeurs définies par défaut. Celles-ci peuvent être modifiées lors de la configuration du matériel (aussi bien dans la version VHDL que Chisel).
| Nom | Début | Taille | Type | Description |
|---|---|---|---|---|
| RAM | 0x00000000 | 0x00000000 | RWX | Mémoire générale du système, utilisée pour les instructions et les données. |
| GPIO8 | 0x00000800 | 0x00000010 | RW- | Registres de configuration des entrées et sorties génériques. |
| UART | 0x00000840 | 0x00000020 | RW- | Registres de configuration de l’UART. |
Mémoire
Périphériques
GPIO8
GPIO8 est un périphérique basique permettant de contrôler l’état de 8 entrées/sorties.
Pour cela, il utilise 3 registres de 8 bits: ENO, IN et OUT.
Chaque bit b de ces registres correspond à l’entrée/sortie b.
| Nom | Décalage | Taille | Description |
|---|---|---|---|
| ENO | 0x00 | 0x01 | Registre de sélection (0: entrée, 1: sortie). |
| IN | 0x04 | 0x01 | Registre de lecture des entrées. |
| OUT | 0x08 | 0x01 | Registre de configuration des sorties. |
Utilisations
2 utilisations principales sont possibles avec ce périphérique: lire une entrée ou écrire une sortie. Chacune de ces opérations s’effectue en deux étapes:
- Configurer le bit correspondant du registre
ENO(0pour une entrée,1pour une sortie), - Lire l’entrée (avec
IN) ou écrire la sortie (avecOUT) correspondante.
Lecture de l’entrée 4 (Langage C)
volatile uint8_t *GPIO8_ENO = ADDR_GPIO8_BASE + 0x00;
volatile uint8_t *GPIO8_OUT = ADDR_GPIO8_BASE + 0x08;
*GPIO8_ENO &= ~(1 << 4);
uint8_t input = (*GPIO8_ENO >> 4) & 0b1;
Écriture de la sortie 5 (Langage C)
uint8_t output;
volatile uint8_t *GPIO8_ENO = ADDR_GPIO8_BASE + 0x00;
volatile uint8_t *GPIO8_OUT = ADDR_GPIO8_BASE + 0x08;
*GPIO8_ENO |= (1 << 5);
*GPIO8_ENO |= ((output & 0b1) << 5);
UART
UART est un périphérique permettant de contrôler une communication UART avec un composant extérieur.
Pour cela, 3 registres de 32 bits et 2 de 8 bits sont utilisés: CONFIG, NCYCLE, STATUS, RX et TX.
| Nom | Décalage | Taille | Description |
|---|---|---|---|
| CONFIG | 0x00 | 0x04 | Registre de configuration. |
| NCYCLE | 0x04 | 0x04 | Registre de configuration du baud rate (nombre de cycles par bit). |
| STATUS | 0x08 | 0x04 | Registre de statut |
| RX | 0x10 | 0x01 | Registre de lecture d’un octet. |
| TX | 0x14 | 0x01 | Registre d’écriture d’un octet. |
Registres
CONFIG est utilisé pour la configuration globale de la communication UART.
Actuellement, ce registre est connecté à 0x00000000: une écriture à son adresse n’aura aucun effet.
NCYCLE est utilisé pour configurer le débit (ou baud rate) de la communication.
La valeur stockée dans le registre correspond au nombre de cycles utilisés pour chaque bit lors de l’émission ou de la réception.
Par exemple, si le processeur est cadencé avec une horloge de 25MHz, pour obtenir un débit de 9600 baud, il faut stocker la valeur 25.000.000 / 9600 = 2604 dans le registre NCYCLE.
STATUS est utilisé pour connaître l’état globale de la communication et du périphérique.
Le champ rx_valid (bit 0) indique si un octet a été reçu et est disponible à la lecture.
Il est remis à zéro lors d’une lecture du registre RX jusqu’à ce qu’un nouvel octet soit disponible.
Le champ tx_ready (bit 4) indique si le périphérique est prêt à envoyer un nouvel octet.
Il est remis à zéro lors d’une écriture du registre TX jusqu’à ce que l’octet soit transmis.
RX permet de lire le dernier octet reçu.
TX permet d’envoyer un nouvel octet.
Utilisations
3 principales utilisations des registres sont possibles:
- La configuration globale du périphérique qui est effectuée une seule fois au départ,
- La réception d’un octet, où il est nécessaire de vérifier qu’un octet est bien disponible avant de le lire,
- L’émission d’un octet, où il est nécessaire de vérifier que le périphérique est prêt à émettre avant d’écrire.
Configuration globale (Langage C)
volatile uint8_t *UART_NCYCLE = ADDR_UART_BASE + 0x04;
UART_NCYCLE = CPU_FREQ / BAUD_RATE;
Réception d’un octet (Langage C)
volatile uint8_t *UART_NCYCLE = ADDR_UART_BASE + 0x04;
volatile uint8_t *UART_STATUS = ADDR_UART_BASE + 0x08;
volatile uint8_t *UART_RX = ADDR_UART_BASE + 0x10;
if ((UART_STATUS >> 0) & 0b1) {
input = *UART_RX;
}
Envoi d’un octet (Langage C)
volatile uint8_t *UART_NCYCLE = ADDR_UART_BASE + 0x04;
volatile uint8_t *UART_STATUS = ADDR_UART_BASE + 0x08;
volatile uint8_t *UART_TX = ADDR_UART_BASE + 0x14;
if ((UART_STATUS >> 4) & 0b1) {
*UART_RX = output;
}
