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.
Chargement…
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.
Un DMA déplace les données pendant que le processeur peut faire autre chose. Son intérêt se mesure avec les coûts de préparation, de cache et de fin de transfert, pas seulement avec le débit du bus.
Le benchmark proposé traite des blocs de 4096 mots et compare ces 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 timer TTC mesure des ticks. Convertissez-les avec sa fréquence et son préscaler, et gérez son rebouclage ; ce ne sont pas automatiquement des cycles CPU. Après chaque copie, comparez tous les mots de destination.
for (u32 i = 0; i < word_count; i++) {
source[i] = 0x10000000U + i;
destination[i] = 0U;
}
Xil_DCacheFlushRange((UINTPTR)source, word_count * sizeof(u32));
Xil_DCacheFlushRange((UINTPTR)destination, word_count * sizeof(u32));
start_dma(source, destination, word_count);
wait_for_dma_done();
Xil_DCacheInvalidateRange((UINTPTR)destination, word_count * sizeof(u32));Le CPU a écrit source et destination. Leur nettoyage empêche des lignes sales de rester en cache avant le DMA. Après la fin, l'invalidation de destination force les prochaines lectures à récupérer les nouvelles données.
start_dma et wait_for_dma_done sont à implémenter pour le contrôleur : PL330/XDmaPs sur Zynq-7000 ou, selon le design MPSoC, ZDMA/XZDma. Ajoutez contrôle d'erreur et limite d'attente.
| 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 | Traiter les lignes modifiées avant le DMA, puis invalider après la fin |
| DMA et CPU partagent une zone cohérente | Respecter les attributs et le port cohérent choisis |
Les buffers occupent des lignes alignées et réservées. Le CPU ne les modifie pas pendant le transfert. La maintenance doit couvrir toutes les lignes touchées ; une extrémité partagée avec des données voisines crée un risque de corruption.
Désactiver le cache peut isoler un défaut, mais change fortement les performances. Choisissez ensuite une politique correcte plutôt que de conserver ce contournement.
Respectez l'alignement du contrôleur et du bus ; les accès non alignés peuvent exiger un mode spécifique. Distinguez adresse C, adresse physique DMA et adresse visible depuis le maître AXI. Elles coïncident souvent dans un standalone simple, mais pas nécessairement avec Linux et une MMU.
| Section | Contenu |
|---|---|
.text | Instructions |
.rodata | Constantes en lecture seule |
.data | Variables initialisées |
.bss | Stockage initialisé à zéro, sans contenu initial dans le fichier ELF |
| heap | Allocations dynamiques |
| stack | Variables locales et contexte d'appel |
Le script de liens affecte les sections aux régions mémoire. Cette portion illustre un code principal en DDR et une routine rapide 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
}Ce n'est pas un script complet : conservez aussi les sections de démarrage, données, heap et stack nécessaires. Les adresses proposées doivent être accessibles et initialisées sur la cible.
void __attribute__((section(".fast_isr"))) dma_isr(void *ref)
{
dma_done = 1U;
}L'attribut place la fonction dans .fast_isr. Son rôle ici est de signaler la fin ; la routine réelle doit également effectuer l'acquittement exigé par le DMA.
Incluez configuration, maintenances et attente. Pour quelques mots, le coût fixe DMA peut dépasser une copie CPU ; pour de grands blocs répétés, il peut devenir avantageux. Répétez les mesures, vérifiez l'horloge du timer et sortez l'affichage UART de la zone chronométrée.
UG585 décrit le DMA et les mémoires Zynq-7000 ; le pilote AXI DMA concerne les transferts d'un DMA placé dans la PL.
Tester mes connaissances - Quiz du chapitre