Un test plus approfondi de l’interface de transmission série haute vitesse HSTX du Raspberry Pi RP2350

Un examen plus approfondi de l'interface de transmission série haute vitesse HSTX du Raspberry Pi RP2350

Le microcontrôleur Raspberry Pi RP2350 ajoute une interface HSTX (High-Speed ​​Serial Transmit) qui ajoute les PIO (Programmable IOs) introduits sur le Raspberry Pi RP2040 il y a trois ans. Le MCU RP2350 dispose désormais de trois PIO et d’une interface HSTX sur 8x GPIO. Essayons donc de mieux comprendre ce qu’est exactement HSTX, à quoi il sert et en quoi il diffère des PIO. Nous découvrirons également quelques exemples de programmation en C et MicroPython.

L’interface de transmission série haute vitesse (HSTX) est détaillée dans la fiche technique du RP2350 à partir de la page 1118 où il est écrit « L’interface de transmission série haute vitesse (HSTX) diffuse les données du domaine d’horloge système vers jusqu’à 8 GPIO à un débit indépendant de l’horloge système ». En poursuivant notre lecture, nous apprenons également qu’elle fonctionne à 150 MHz, ce qui permet jusqu’à 300 Mbps par broche avec un fonctionnement en sortie DDR, ou un débit combiné de 2 400 Mbps sur 8 broches si j’ai bien compris…

Interface HSTX pour Raspberry Pi RP2530
Schéma fonctionnel du Raspberry Pi RP2530 HSTX

Voici un peu plus de description de la fiche technique

Le HSTX est asynchrone par rapport au reste du système. Un FIFO de 32 bits de large fournit un accès à large bande passante à partir du DMA du système. L’extenseur de commandes effectue une manipulation simple du flux de données et le registre à décalage de sortie répartit les données 32 bits sur des cycles d’horloge HSTX successifs, permutés par le crossbar de bits. Les sorties sont à double débit de données : jusqu’à deux bits par broche par cycle d’horloge.

Le HSTX transmet les données via les GPIO à l’aide de registres de sortie DDR pour transférer jusqu’à deux bits par cycle d’horloge par broche. Le HSTX équilibre tous les retards vers les sorties GPIO dans les 300 picosecondes, minimisant ainsi les composants en mode commun lors de l’utilisation de GPIO voisins comme pilote pseudo-différentiel. Cela permet également de maintenir la configuration de destination et le temps de maintien lorsqu’une horloge est pilotée parallèlement aux données de sortie.

La fréquence maximale de l’horloge HSTX est de 150 MHz, soit la même que celle de l’horloge système. Avec un fonctionnement en sortie DDR, le débit de données maximal est de 300 Mb/s par broche. Il n’y a aucune limite au rapport de fréquence des horloges système et HSTX. Cependant, chaque horloge doit être suffisamment rapide individuellement pour maintenir le débit requis. Des fréquences d’horloge système très basses associées à des fréquences HSTX très élevées peuvent entraîner des limitations de bande passante DMA du système, car le DMA est limité à une écriture FIFO HSTX par cycle d’horloge système.

Sur le Raspberry Pi RP2350, les GPIO 12 à 19 sont compatibles HSTX. Notez que le HSTX est uniquement en sortie, il n’est donc pas aussi flexible que les PIO qui permettent aux utilisateurs de créer toutes sortes d’interfaces à haut débit (ou non). J’ai modifié le schéma de brochage du Raspberry Pi Pico 2 pour mettre en évidence les GPIO compatibles HSTX.

Diagramme de brochage du Raspberry Pi Pico 2 HSTX
Diagramme de brochage du Raspberry Pi Pico 2 avec GPIO prenant en charge HSTX

À quoi peut servir HSTX ?

Le HSTX est capable de transférer des données à haut débit, mais ne peut que transmettre des données et non les recevoir. Il semble donc particulièrement utile pour les sorties vidéo et les interfaces d’affichage. Cependant, il ne conviendrait pas aux transferts bidirectionnels, par exemple, vous ne pourriez pas émuler une interface Ethernet.

Les PIO du Raspberry Pi RP2040 ont été utilisés pour créer des sorties vidéo DVI, VGA et composite, mais dans la carte RP2350, les blocs d’E/S programmables peuvent être libérés et l’interface HSTX utilisée à la place. Bien que vous puissiez utiliser le Raspberry Pi Pico 2 pour jouer avec l’interface HSTX, vous aurez à faire quelques soudures, et un moyen plus pratique de commencer est d’obtenir une carte comme le RP2xxx Stamp Carrier XL en combinaison avec le module Stamp R2350 car il expose l’interface HSTX via un port micro HDMI.

Sortie vidéo HSTX du Raspberry Pi RP2350

La photo ci-dessus montre la carte RP2xxx Stamp Carrier XL connectée à un clavier et à un écran affichant l’interface CircuitPython REPL, et arturo182 a confirmé qu’elle utilise HSTX sur X. Je n’ai pas encore trouvé de code spécifique pour cela, ou peut-être que l’image CircuitPython par défaut fonctionne déjà de cette façon [Update: yes, and the code can be found @ https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c].

D’autres cartes d’Adafruit, Pimoroni et d’autres seront bientôt disponibles avec des sorties vidéo et/ou des écrans avec prise en charge HSTX.

Exemples de code HSTX pour RP2350 en C

Raspberry Pi fournit deux exemples de code HSTX dans le SDK Raspberry Pi Pico C/C++ :

  • dvi_out_hstx_encoder – Cet exemple génère une sortie DVI à l’aide de l’expandeur de commandes et de l’encodeur TMDS dans HSTX. La résolution du tampon d’image est définie sur 640 × 480. Cet exemple nécessite un connecteur vidéo numérique externe connecté aux GPIO 12 à 19 avec des résistances de limitation de courant appropriées, par exemple 270 ohms. Cet exemple peut être utilisé directement avec la carte Pico DVI Sock qui peut être soudée sur un Raspberry Pi Pico 2.
  • spi_lcd – Cet exemple pilote un écran LCD SPI ST7789 à l’aide du HSTX. La fréquence d’horloge SPI est totalement indépendante de l’horloge système (et peut être plus rapide que celle-ci). Il a été testé à une résolution de 240 × 240 à l’aide d’un module WaveShare ST7789 de 1,3 pouce.

Les deux exemples sont trop longs pour être intégrés dans cet article, je vais donc montrer le code lié à HSTX à partir des exemples SPI LCD :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

#include « hardware/structs/hstx_ctrl.h »

#include « hardware/structs/hstx_fifo.h »

// Il peut s’agir de n’importe quelle permutation de broches compatibles HSTX :

#définir PIN_DIN 12

#define PIN_SCK 13

#define PIN_CS 14

#define PIN_DC 15

// Il peut s’agir de n’importe quelle broche :

#définir PIN_RESET 16

#define PIN_BL 17

#define FIRST_HSTX_PIN 12

#si PIN_DIN < PREMIER_PIN_HSTX || PIN_DIN >= PREMIER_PIN_HSTX + 8

#error « Doit être une broche compatible HSTX : DIN »

#elif PIN_SCK < PREMIER_PIN_HSTX || PIN_SCK >= PREMIER_PIN_HSTX + 8

#error « Doit être une broche compatible HSTX : SCK »

#elif PIN_CS < PREMIER_PIN_HSTX || PIN_CS >= PREMIER_PIN_HSTX + 8

#error « Doit être une broche compatible HSTX : CS »

#elif PIN_DC < PREMIER_PIN_HSTX || PIN_DC >= PREMIER_PIN_HSTX + 8

#error « Doit être une broche compatible HSTX : DC »

#finsi

statique en ligne void hstx_put_word(uint32_t données) {

pendant que (hstx_fifo_hw->stat & HSTX_FIFO_STAT_FULL_BITS)

;

hstx_fifo_hw->fifo = données;

}

statique en ligne void lcd_put_dc_cs_data(bool dc, bool csn, uint8_t données) {

hstx_put_word(

(uint32_t)données |

(csn ? 0x0ff00000u : 0x00000000u) |

// Notez que DC est inversé à l’intérieur de HSTX :

(cc ? 0x00000000u : 0x0003fc00u)

);

}

Deux fichiers d’inclusion sont nécessaires, les broches 12 à 17 sont affectées à des signaux spécifiques pour l’affichage, et il existe des macros pour vérifier que les broches SPI sélectionnées sont effectivement des broches compatibles HSTX. La première fonction en ligne charge les données 32 bits dans le tampon FIFO lorsqu’il est disponible/vide, et la seconde envoie les données vers l’écran LCD SPI.

La fonction principale contient davantage de code lié à HSTX :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

int main() {

stdio_init_all();

// Basculez HSTX vers USB PLL (probablement 48 MHz) car clk_sys est probablement

// fonctionne un peu trop vite pour cet exemple — 48 MHz signifie 48 Mbps sur

// PIN_DIN. Il faut réinitialiser le changement de mux autour de l’horloge, car le mux AUX peut

// introduire des impulsions d’horloge courtes :

réinitialiser_bloc(RÉINITIALISER_RÉINITIALISER_HSTX_BITS);

hw_write_masked(

&clocks_hw->clk[clk_hstx].ctrl,

HORLOGES_CLK_HSTX_CTRL_AUXSRC_VALEUR_CLKSRC_PLL_USB << HORLOGES_CLK_HSTX_CTRL_AUXSRC_LSB,

HORLOGES_CLK_HSTX_CTRL_AUXSRC_BITS

);

unreset_block_wait(RÉINITIALISER_RÉINITIALISER_HSTX_BITS);

gpio_init(RÉINITIALISATION_PIN);

gpio_init(PIN_BL);

gpio_set_dir(RÉINITIALISATION_PIN, SORTIE_GPIO);

gpio_set_dir(PIN_BL, GPIO_OUT);

gpio_put(RÉINITIALISATION_PIN, 1);

gpio_put(PIN_BL, 1);

hstx_ctrl_hw->bit[PIN_SCK – FIRST_HSTX_PIN] =

HSTX_CTRL_BIT0_CLK_BITS;

hstx_ctrl_hw->bit[PIN_DIN – FIRST_HSTX_PIN] =

(7u << HSTX_CTRL_BIT0_SEL_P_LSB) |

(7u << HSTX_CTRL_BIT0_SEL_N_LSB);

hstx_ctrl_hw->bit[PIN_CS – FIRST_HSTX_PIN] =

(27u << HSTX_CTRL_BIT0_SEL_P_LSB) |

(27u << HSTX_CTRL_BIT0_SEL_N_LSB);

hstx_ctrl_hw->bit[PIN_DC – FIRST_HSTX_PIN] =

(17u << HSTX_CTRL_BIT0_SEL_P_LSB) |

(17u << HSTX_CTRL_BIT0_SEL_N_LSB) |

(HSTX_CTRL_BIT0_INV_BITS);

// Nous avons emballé des champs de 8 bits, donc décalons vers la gauche de 1 bit/cycle, 8 fois.

hstx_ctrl_hw->csr =

HSTX_CTRL_CSR_FR_BITS |

(31u << HSTX_CTRL_CSR_SHIFT_LSB) |

(8u << HSTX_CTRL_CSR_N_SHIFTS_LSB) |

(1u << HSTX_CTRL_CSR_CLKDIV_LSB);

gpio_set_function(PIN_SCK, 0/*GPIO_FUNC_HSTX*/);

gpio_set_function(PIN_DIN, 0/*GPIO_FUNC_HSTX*/);

gpio_set_function(PIN_CS, 0/*GPIO_FUNC_HSTX*/);

gpio_set_function(PIN_DC, 0/*GPIO_FUNC_HSTX*/);

L’exécution du HSTX à 150 MHz serait trop rapide pour l’écran LCD, c’est pourquoi ils utilisent à la place l’horloge USB plus lente de 48 MHz. Pour référence, la démonstration de sortie DVI repose sur l’horloge par défaut (125 MHz) qui sera suffisante pour 640 × 480 à 60 FPS.

Une partie du code modifie le registre de configuration de la barre transversale de bits qui contrôle quels bits du registre à décalage de sortie apparaissent sur quels GPIO pendant la première et la deuxième moitié de chaque cycle d’horloge HSTX avec les paramètres suivants :

  • BITx.SEL_P sélectionne le bit de registre à décalage (0 à 31) qui est émis pour la première moitié de chaque cycle d’horloge HSTX
  • BITx.SEL_N sélectionne le bit de registre à décalage (0 à 31) qui est émis pour la seconde moitié de chaque cycle d’horloge
  • BITx.INV inverse la sortie (NOT logique)
  • BITx.CLK indique que cette broche doit être connectée au générateur d’horloge plutôt qu’au registre à décalage de sortie

Le code ci-dessus désactive le comportement DDR en définissant SEL_N égal à SEL_P sur trois broches et connecte le signal CLK au générateur d’horloge. La broche DC a également son signal inversé.

Le SDK MicroPython a été mis à jour pour RP2350, mais lorsque je consulte la dernière documentation, je constate qu’il n’y a pas encore de support pour HSTX, mais l’image CircuitPython (Alpha) pour le Raspberry Pi Pico 2 – et d’autres cartes RP2350 – peut déjà gérer HSTX « pour générer des signaux de sortie haute fréquence comme la sortie d’affichage DVI ». Notez que HSTX n’est implémenté que dans CircuitPython 9.2.0, actuellement en Alpha.

Retrouvez l’histoire de Raspberry Pi dans cette vidéo :

YouTube video

  • Adafruit Feather RP2350 avec port HSTX et Raspberry Pi RP2350 6000
  • RP2350 Can Carte de Développement Basée sur RP2350 Microcontrôleur à Double Cœur et à Double Architecture, Contrôleur Can XL2515 Intégré, Compatible avec Raspberry Pi Pico Modules