Aller au contenu

La mémoire des systèmes embarqués

Introduction

Tout programme est stocké en mémoire avant son exécution. Il existe différentes options pour charger le programme en mémoire. Le processeur doit connaitre les adresses des différents éléments de programme. Pour cela il faut initialiser les registres pointant sur les différentes régions de code et de données dans l’espace mémoire du processeur. Ces éléments sont définis dans le modèle du programmeur du processeur.

Nous retrouvons deux grandes orientations dans l’utilisation de la mémoire:

  • les systèmes à un seul programme tel que les systèmes embarqués qui peuvent se contenter d’un modèle mémoire simple,

  • les systèmes multi-programmes tels que nos ordinateurs équipés d’un système d’exploitation. Ces systèmes se caractérisent par l’utilisation d’un système de fichiers qui stocke le binaire des programmes qu’il faut charger en mémoire avant leur exécution. Comme plusieurs programmes peuvent se trouver simultanément en mémoire, il est nécessaire de disposer d’une translation d’adresses pour faire le lien entre mémoire physique et la mémoire de programme.

Les différentes mémoires des systèmes

La mémoire à disposition implique un compromis entre vitesse, taille et prix.

Memory Pyramid

Pyramide des mémoires (source cours TechInfo Luc De Mey)

Dans les systèmes à mémoire dynamique (DRAM), la mémoire cache permet une nette augmentation des performances. Dans un système embarqué à mémoire statique rapide (SRAM), la mémoire cache perd de son intérêt, car elle est de même conception que la mémoire principale.

La gestion mémoire

Dans les systèmes à multi-programmes, nous retrouvons un système de gestion de la mémoire dont les principales tâches consistent à:

  • fournir une couche d’abstraction pour le programmeur,
  • allouer efficacement de la mémoire aux différents programmes,
  • optimiser les performances.

Ceci se fait à l’aide de plusieurs mécanismes comme:

  • l’adressage physique et virtuel,
  • le partitionnement, la pagination ou la segmentation mémoire.

L’unité de gestion mémoire (MMU - Memory Management Unit) permet la translation entre adresses virtuelles et adresses physiques.

Memory Management Unit

Unité de gestion mémoire

Note

Ceci permet d’avoir plusieurs programmes aux mêmes adresses virtuelles, mais placées dans des adresses physiques différentes et donc de mettre en parallèle plusieurs programmes en mémoire.

La pagination permet de découper la mémoire en zones de tailles identiques qui sont partagées entre les différents programmes.

Memory Pagination

Pagination mémoire

Lorsque la mémoire physique implémentée est insuffisante par rapport aux programmes en exécution, il peut être nécessaire de faire des échanges de mémoire (memory swap) pour placer temporairement les programmes qui ne sont pas exécutés sur le disque dans une zone temporaire d’échange.

Les systèmes embarqués disposent d’interfaces mémoire flash qui sont connectées en SPI. De par sa structure et de ses limites de ces cycles d’écritures, la mémoire flash n’est pas idéale pour implémenter une mémoire swap.

Memory Swap

Swap mémoire

Note

Dans le cadre de ce cours, nous ne traiterons pas plus avant des problématiques de mémoire multi-programmes comme la virtualisation, la pagination ou le swap!

Les fichiers binaires

Le programme compilé est enregistré dans un fichier binaire avant d’être chargé en mémoire. Il existe deux types de fichiers binaires:

  • les fichiers binaires purs (.bin - binary) sans réorganisation ni relocalisation de la mémoire avec des instructions explicites à charger à une adresse mémoire spécifique,

  • les fichiers binaires re-positionables (.elf - Executable Linkable Format) qui peuvent être chargés à n’importe quelle adresse mémoire. Ils disposent de sections qui sont placées à diverses adresses au moment du chargement en mémoire.

Les systèmes avec MMU tel que Linux, peuvent utiliser des fichiers .bin alors que dans les systèmes embarqués, nous recourons principalement aux fichiers .elf. Il est à noter que les fichiers .elf sont admis depuis 2000 sur l’ensemble des systèmes Unix compatibles, car ils permettent une meilleure adaptation entre les différentes plateformes.

Simplifications dans les systèmes embarqués

Les systèmes embarqués à simple programme permettent des simplifications fort agréables comme:

  • un plan mémoire unifié qui évite la virtualisation,
  • une gestion dynamique des espaces mémoire sans ramasse-miettes1,
  • La possibilité de ne pas implémenter les destructeurs d’objets2.

Le principe de base de la programmation embarqué consiste à démarrer un programme qui ne s’arrête jamais tant que le processus reste actif. Ceci nécessite bien évidemment une robustesse à toute épreuve. Il est important de suivre les règles de programmation afin d’assurer cette qualité. Par exemple Mbed OS définit des règles de programmation pour ses API.

Dans ce chapitre, nous étudions

  • la mémoire du STN32F412 de nos cibles de laboratoire,
  • les modes de démarrage du processeur et l’initialisation mémoire,
  • l’utilisation de la mémoire dynamique, analyse et optimisation,
  • la protection mémoire,
  • la structure des fichiers binaires .elf.

  1. Le ramasse-miettes (garbage collector) permet d’éliminer automatiquement par le système d’exploitation les parties mémoire qui ne sont plus utilisées (référencées) et de re-compacter ces zones de mémoire disjointes pour obtenir des espaces mémoire libres de grande taille sur le tas (heap). 

  2. Comme le programme ne termine jamais et que les objets construits ne sont jamais détruits, nous pouvons nous passer des destructeurs d’objets.