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).

NomDébutTailleTypeDescription
RAM0x000000000x00000000RWXMémoire générale du système, utilisée pour les instructions et les données.
GPIO80x000008000x00000010RW-Registres de configuration des entrées et sorties génériques.
UART0x000008400x00000020RW-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.

NomDécalageTailleDescription
ENO0x000x01Registre de sélection (0: entrée, 1: sortie).
IN0x040x01Registre de lecture des entrées.
OUT0x080x01Registre 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:

  1. Configurer le bit correspondant du registre ENO (0 pour une entrée, 1 pour une sortie),
  2. Lire l’entrée (avec IN) ou écrire la sortie (avec OUT) 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.

NomDécalageTailleDescription
CONFIG0x000x04Registre de configuration.
NCYCLE0x040x04Registre de configuration du baud rate (nombre de cycles par bit).
STATUS0x080x04Registre de statut
RX0x100x01Registre de lecture d’un octet.
TX0x140x01Registre 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:

  1. La configuration globale du périphérique qui est effectuée une seule fois au départ,
  2. La réception d’un octet, où il est nécessaire de vérifier qu’un octet est bien disponible avant de le lire,
  3. 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;
  }