DMA, cache et script de liens
Déplacer des buffers entre DDR, OCM et BRAM, maintenir la cohérence du cache et placer les sections ELF dans la bonne mémoire.
Pourquoi utiliser un DMA
Une copie réalisée par le processeur consomme des instructions pour chaque mot. Un Direct Memory Access Controller, ou DMA, déplace directement un bloc de données entre deux adresses. Le processeur prépare le transfert, puis peut exécuter une autre tâche ou attendre l'interruption de fin.
Pour rendre les effets de la mémoire et du cache mesurables, nous proposons dans ce cours un benchmark DMA. Ce programme compare quatre chemins.
| Source | Destination | Frontière traversée |
|---|---|---|
| DDR | DDR | Mémoire du PS |
| BRAM | BRAM | Mémoire de la PL |
| DDR | BRAM | PS vers PL |
| BRAM | DDR | PL vers PS |
Le code répète des blocs de 4096 mots et mesure le nombre de cycles avec un timer TTC. Il vérifie ensuite chaque mot du buffer destination. Une mesure sans vérification peut masquer une erreur d'adresse ou de cache.

Préparer un transfert
Le processeur initialise la source et la destination, construit le descripteur, configure le canal DMA puis lance l'opération.
for (u32 i = 0; i < word_count; i++) {
source[i] = 0x10000000U + i;
destination[i] = 0U;
}
Xil_DCacheFlushRange((UINTPTR)source, word_count * sizeof(u32));
start_dma(source, destination, word_count);
wait_for_dma_done();
Xil_DCacheInvalidateRange((UINTPTR)destination, word_count * sizeof(u32));Les fonctions start_dma et wait_for_dma_done dépendent du contrôleur. Zynq-7000 peut utiliser le PL330 avec le pilote XDmaPs. Zynq UltraScale+ MPSoC fournit d'autres moteurs, dont ZDMA avec XZDma. La logique de cohérence reste la même.
Le problème du cache
Le processeur et le DMA peuvent voir deux versions d'un même buffer. Une opération de flush écrit en mémoire les lignes modifiées du cache. Une invalidation supprime au contraire les anciennes copies afin que la prochaine lecture récupère les données présentes en mémoire.
| Opération DMA | Action du processeur |
|---|---|
| DMA lit un buffer produit par le CPU | Nettoyer ou vider la source vers la mémoire |
| DMA écrit un buffer que le CPU va lire | Invalider la destination après la fin |
| DMA et CPU partagent une zone cohérente | Respecter les attributs et le port cohérent choisis |
Désactiver tout le cache peut aider à isoler un défaut. Ce n'est pas une solution de production. La pénalité de performance peut être importante.
Alignement et limites
Les buffers doivent respecter l'alignement demandé par le contrôleur et la largeur du bus. Une taille non multiple du mot ou une adresse non alignée peut demander un mode spécifique. Les plages de maintenance du cache doivent couvrir toutes les lignes touchées, y compris les extrémités partielles.
Une application robuste distingue trois adresses. L'adresse C sert au processeur. L'adresse physique sert au DMA. L'adresse vue par le maître AXI dépend de la carte mémoire et du port PS utilisé. En standalone simple, elles coïncident souvent, mais il ne faut pas généraliser ce cas à Linux avec une MMU.
Comprendre le fichier ELF
Le compilateur classe le programme dans des sections.
| Section | Contenu |
|---|---|
.text | Instructions |
.rodata | Constantes en lecture seule |
.data | Variables initialisées |
.bss | Variables non initialisées |
| heap | Allocations dynamiques |
| stack | Variables locales et contexte d'appel |
Le script de liens est le plan de placement du programme. Il associe chaque section ELF à une région mémoire. Il peut, par exemple, garder le programme principal en DDR et placer une ISR critique en OCM.
MEMORY
{
psu_ddr : ORIGIN = 0x00100000, LENGTH = 0x1FF00000
psu_ocm : ORIGIN = 0xFFFC0000, LENGTH = 0x00040000
}
SECTIONS
{
.text : { *(.text*) } > psu_ddr
.fast_isr : { *(.fast_isr*) } > psu_ocm
}Le code C peut sélectionner la section avec un attribut de compilation.
void __attribute__((section(".fast_isr"))) dma_isr(void *ref)
{
dma_done = 1U;
}L'adresse doit appartenir à une mémoire initialisée et accessible au processeur ciblé. Il faut aussi réserver assez d'espace pour le code, les données, le heap et la stack.
Mesurer correctement
Une comparaison CPU contre DMA doit inclure le coût de configuration, la maintenance du cache et l'attente de fin. Le DMA devient intéressant pour des transferts assez grands ou répétés. Pour quelques mots, son coût fixe peut être supérieur à une copie CPU.
Il faut réaliser plusieurs mesures, vérifier la fréquence du timer et éviter que l'affichage UART ne se trouve dans la zone chronométrée.
Références officielles
Le Zynq-7000 Technical Reference Manual UG585 décrit les mémoires et le contrôleur DMA du PS. La documentation officielle du pilote AXI DMA complète ce chapitre pour un DMA placé dans la PL.
À retenir
Le DMA déplace les données mais ne rend pas automatiquement les caches cohérents. Le logiciel prépare les buffers, lance le transfert, traite la fin et maintient le cache. Le script de liens contrôle la mémoire qui reçoit chaque section du programme.
Tester mes connaissances - Quiz du chapitre