Partager via


Gérer la mémoire et la latence

Important

Il s’agit de la documentation Azure Sphere (héritée). Azure Sphere (hérité) prend sa retraite le 27 septembre 2027 et les utilisateurs doivent migrer vers Azure Sphere (intégré) pour l’instant. Utilisez le sélecteur de version situé au-dessus du TOC pour afficher la documentation Azure Sphere (intégrée).

Cette rubrique décrit les considérations relatives à la mémoire et à la latence pour les applications en temps réel qui s’exécutent sur la puce MT3620.

Remarque

Pour plus d’informations sur la configuration de la mémoire ou DMA, consultez la feuille de données MT3620 publiée à partir de MediaTek . Si des questions restent, vous pouvez demander la « feuille de données MT3620 M4 » d’Avnet par e-mail Azure.Sphere@avnet.com.

Disposition de mémoire sur les cœurs en temps réel

Le tableau suivant récapitule la mémoire disponible sur les cœurs en temps réel :

Type de mémoire Adresse de base
TCM 0x00100000
Flash XIP 0x10000000
SYSRAM 0x22000000

Chaque cœur en temps réel dispose de 192 Ko de mémoire TCM (tightly-coupled memory), avec mappage dans trois banques de 64 Ko commençant à 0x00100000. Les accès à la mémoire TCM sont rapides, mais seul le cœur en temps réel peut y accéder. La mémoire TCM ne peut pas être partagée avec une application générale ou une application en temps réel (RTApp) qui s'exécute sur un autre cœur.

Chaque cœur en temps réel dispose également de 64 Ko de SYSRAM, avec mappage commençant à 0x22000000. Le contrôleur DMA peut également cibler SYSRAM pour permettre aux périphériques d'y accéder. Les accès à SYSRAM à partir du cœur en temps réel sont plus lents que les accès à la mémoire TCM. Comme avec la mémoire TCM, SYSRAM ne peut pas être partagée avec une autre application.

La mémoire flash d’exécution sur place (XIP) est partagée avec les applications générales. Une fenêtre dans le mappage XIP de la mémoire flash est visible pour chaque cœur à l’adresse 0x10000000. Le système d’exploitation configure le mappage XIP avant de démarrer l’application si le fichier ELF de cette dernière contient un segment présentant les propriétés suivantes :

  • L'adresse de chargement (comme indiqué dans la colonne VirtAddr de l’en-tête de programme) est égale à 0x10000000
  • Le décalage et la taille de fichier (comme indiqué dans les champs FileSiz et MemSiz de l’en-tête de programme) sont adaptés au fichier ELF de l'application.

Si un en-tête de programme doté de ces propriétés est présent dans le fichier ELF de l’application, la fenêtre XIP est positionnée de manière à ce que le segment soit visible à 0x10000000. Le fichier ne peut contenir plus d'un segment XIP et doit pointer vers 0x10000000 ; il ne peut spécifier une autre adresse.

Déploiement ELF

Les images RTApp doivent correspondre à des fichiers ELF. L’image ELF est encapsulée dans un package d’image Azure Sphere et déployée en tant qu’application. Pour charger l’application, le système d’exploitation Azure Sphere démarre un chargeur ELF qui s’exécute sur le cœur en temps réel. Le chargeur traite chaque segment LOAD dans le fichier ELF et les charge dans le type de mémoire indiqué par l’adresse virtuelle de l’en-tête de programme.

Utilisez arm-none-eabi-readelf.exe -l (avec un « l » minuscule), qui fait partie de la chaîne d’outils GNU Arm Embedded pour afficher les en-têtes de programme pour votre application. La colonne d’adresse virtuelle (VirtAddr) qui s’affiche dans l’en-tête indique l’adresse de destination pour le segment de chargement. Cela ne signifie pas que le processeur effectue une translation supplémentaire. Le chargeur ELF Azure Sphere n’utilise pas l’adresse physique (PhysAddr).

Prenons cet exemple :

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000098 0x00100000 0x00100000 0x00000 0x00e78 RW  0x8
  LOAD           0x0000a0 0x10000000 0x10000000 0x03078 0x03078 RWE 0x10
  LOAD           0x003118 0x00100e78 0x10003078 0x000f0 0x000f0 RW  0x4
  • Le segment à 0x00100000 est ciblé sur la mémoire TCM. Le chargeur copie les données à partir du package d’image dans la RAM ou initialise la mémoire TCM en fonction des besoins.

  • Le segment à 0x10000000 est mappé à la fenêtre XIP pour le cœur. Au moment de l’exécution, les accès à 0x10000000 + offset sont translatés vers <address-of-XIP-segment-in-flash> + offset lorsqu’ils quittent le cœur en temps réel.

  • Le segment de données à l’adresse virtuelle 0x00100e78 est mappé à la mémoire TCM.

Considérations relatives au runtime ELF

Le chargeur ELF effectue certaines tâches qu’une binaire brute (ou chargeur de démarrage chaîné) exécuterait au démarrage. Plus précisément, il initialise les données BSS (block-started-by-symbol) et copie les données initialisées mais mutables de la mémoire flash en lecture seule vers la RAM, selon les en-têtes de programme. Ensuite, l’application démarre et exécute ses propres fonctions d’initialisation. Dans la plupart des cas, il n'est pas nécessaire de modifier les applications existantes. La mise à zéro des données BSS dans l’application est inutile mais sans conséquence, compte tenu du fait que le chargeur a déjà remis à zéro la mémoire.

La copie de données mutables d’un flash vers la RAM peut dans certaines circonstances entraîner des problèmes, selon la façon dont le fichier ELF est disposé. Le chargeur ELF traite les en-têtes de programme de manière séquentielle, sans modifier la disposition globale des segments du fichier. Il mappe ensuite le segment XIP à 0x10000000, de même que les segments suivants dans l’ordre. Si les segments du fichier ELF se présentent dans un ordre séquentiel sans alignement ou écarts, le code de démarrage du système d’exploitation peut utiliser l'arithmétique du pointeur pour rechercher le début du segment de données. Si le fichier ELF présente une disposition différente, l'arithmétique du pointeur ne permet pas d'obtenir l'adresse qui convient, et dès lors, le code de démarrage d’application ne doit pas essayer de copier la section de données. Cela peut entraîner des problèmes si l’application ou le RTO utilise un chargeur de démarrage chaîné ou doit configurer un contrôle de validité de pile avant de mettre à zéro les données BSS ou d'initialiser les données mutables.

Cibles de mémoire

Vous pouvez cibler le code au niveau de la mémoire TCM, flash XIP ou SYSRAM en modifiant le script linker.ld correspondant à votre application. Les exemples d’applications Azure Sphere s'exécutent à partir de la mémoire TCM, mais le fichier de script linker.ld pour chaque application explique comment cibler plutôt la mémoire flash XIP. Comme le montre l’exemple suivant, vous pouvez modifier un exemple à des fins d’exécution sur XIP en utilisant un alias CODE_REGION et RODATA_REGION FLASH plutôt que la valeur par défaut TCM :

REGION_ALIAS("CODE_REGION", FLASH);
REGION_ALIAS("RODATA_REGION", FLASH);

Pour savoir si une application compilée s’exécute à partir de la mémoire TCM ou flash XIP, utilisez arm-none-eabi-readelf.exe, qui fait partie de la chaîne ARM GNU incorporée. Exécutez-la sur le fichier .out, qui se trouve dans le même répertoire que le package d’image, et spécifiez l’indicateur -l (un « l » minuscule) pour voir où le code et les données en lecture seule ont été placés. Le code et les données en lecture seule stockés dans la mémoire flash sont chargés à l’adresse 0x10000000 ; le code et les données stockés dans la mémoire TCM sont chargés dans la région TCM.

L’exemple suivant illustre une application qui s’exécute à partir de la mémoire flash.

arm-none-eabi-readelf.exe -l UART_RTApp_MT3620_BareMetal.out

Elf file type is EXEC (Executable file)
Entry point 0x10000000
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000074 0x00100000 0x00100000 0x00284 0x003c0 RW  0x4
  LOAD           0x000300 0x10000000 0x10000000 0x013b9 0x013b9 R E 0x10

 Section to Segment mapping:
  Segment Sections...
   00     .data .bss
   01     .text .rodata

Emplacement de la table des vecteurs

Sur les appareils ARMv7-M, la table des vecteurs doit être alignée sur une limite égale à une puissance de deux qui est d’au moins 128 octets, et égale ou supérieure à la taille de la table, comme indiqué dans le Manuel de référence de l’architecture ARMv7-M. Chaque cœur RT d’E/S sur le MT3620 prend en charge 100 interruptions externes. Ainsi, en incluant le pointeur de pile et 15 exceptions standard, la table a 116 entrées de 4 octets, soit une taille totale de 464 octets, qui est arrondie à 512 octets.

Quand le code est exécuté à partir d’une mémoire flash XIP, la table des vecteurs doit être placée à 0x10000000 et doit être alignée sur une limite de 32 octets dans le fichier ELF. Quand le code n’est pas exécuté à partir d’une mémoire flash XIP, la table est généralement placée au début de TCM0, qui est 0x100000. Dans les deux cas, pour garantir que l’adresse virtuelle de la table est correctement alignée, placez la table des vecteurs dans une section dédiée et définissez CODE_REGION sur l’adresse appropriée.

Les exemples MT3620 BareMetal dans le dépôt des exemples Azure Sphere montrent comment effectuer cette opération. La déclaration de la table des vecteurs dans main.c définit son attribut section sur .vector_table. Le script de l’éditeur de liens crée un alias de CODE_REGION défini sur le début de TCM ou de XIP, et l’attribut ALIGN définit l’alignement de la section texte dans le fichier ELF comme suit :

SECTIONS
{
    .text : ALIGN(32) {
        KEEP(*(.vector_table))
        *(.text)
    } >CODE_REGION
...
}

Considérations relatives au temps réel et à la latence

Les applications en temps réel et générales entrent en concurrence pour accéder à la mémoire flash, même si elles ne communiquent pas entre elles. Ainsi, les applications en temps réel en cours d’exécution à partir de la mémoire flash XIP peut être confrontées à une latence aussi élevée qu'imprévisible. Les écritures vers la mémoire flash, lors d'une mise à jour par exemple, peuvent impliquer des pics de latence jusqu'à plusieurs centaines de millisecondes. Selon les exigences de votre application, vous pouvez gérer cela de plusieurs façons :

  • Placez le code et les données dans la mémoire TCM. Le code qui s’exécute à partir de la mémoire TCM n’est pas vulnérable à la contention pour la mémoire flash.

  • Fractionnez le code en sections critiques et non critiques, et exécutez le code non critique à partir de la mémoire flash. Le code présentant des exigences en temps réel, minuteur de surveillance par exemple, ne doit pas être exécuté lorsqu'un autre code accède à la mémoire flash. Cibles de mémoire explique comment cibler la mémoire flash XIP plutôt que la mémoire TCM.

  • Utilisez le cache. Une application peut utiliser les 32 Ko les plus bas de la mémoire TCM en tant que cache XIP. Cette approche n'offre pas de garanties en termes de temps réel en cas d'échec du cache, mais améliore le niveau de performance type sans qu'il vous soit nécessaire de déplacer l'intégralité du code dans la RAM. Reportez-vous à la « feuille de données MT3620 M4 » pour plus d’informations sur la configuration du cache XIP.