Le mois dernier, j'ai passé beaucoup de temps à faire fonctionner UART (pour MIDI) avec une STM (STM32F103C8T6) en utilisant des interruptions, sans grand succès.
Cependant, ce soir, en utilisant DMA, cela a fonctionné assez rapidement.
Dans la mesure où je lis DMA est plus rapide et soulage le CPU, pourquoi ne pas toujours utiliser DMA en faveur des interruptions? D'autant plus que sur le STM32 il semble y avoir pas mal de problèmes.
J'utilise STM32CubeMx / HAL.
uart
dma
stm32cubemx
stm32f103c8t6
Michel Keijzers
la source
la source
Réponses:
Bien que DMA soulage le processeur et puisse ainsi réduire la latence des autres applications déclenchées par interruption fonctionnant sur le même cœur, il y a des coûts associés:
Il n'y a qu'une quantité limitée de canaux DMA et il y a des limites sur la façon dont ces canaux peuvent interagir avec les différents périphériques. Un autre périphérique sur le même canal peut être plus adapté à une utilisation DMA.
Par exemple, si vous avez un transfert I2C en vrac toutes les 5 ms, cela semble être un meilleur candidat pour DMA qu'une commande de débogage occasionnelle arrivant sur UART2.
La mise en place et la maintenance de DMA est un coût en soi. (Normalement, la configuration de DMA est considérée comme plus complexe que la configuration d'un transfert par interruption normal par caractère, en raison de la gestion de la mémoire, du nombre de périphériques impliqués, de l'utilisation de DMA elle-même et de la possibilité que vous ayez besoin d'analyser les premiers caractères en dehors de DMA de toute façon, voir ci-dessous.)
Le DMA peut utiliser une puissance supplémentaire , car c'est encore un autre domaine du cœur qui doit être cadencé. D'un autre côté, vous pouvez suspendre le processeur pendant le transfert DMA, si le cœur le prend en charge.
Le DMA nécessite des tampons de mémoire pour fonctionner (à moins que vous ne fassiez du DMA périphérique à périphérique), il y a donc un coût de mémoire associé.
(Le coût de la mémoire peut également être présent lors de l'utilisation d'interruptions par caractère, mais il peut également être beaucoup plus petit ou disparaître du tout si les messages sont interprétés immédiatement à l'intérieur de l'interruption.)
Le DMA produit une latence car le CPU n'est averti que lorsque le transfert est terminé / à moitié terminé (voir les autres réponses).
Sauf lors du streaming de données vers / depuis un tampon en anneau, vous devez savoir à l'avance la quantité de données que vous recevrez / envoyez.
Cela peut signifier qu'il est nécessaire de traiter les premiers caractères d'un message à l'aide d'interruptions par caractère: par exemple, lors de l'interface avec un XBee, vous devez d'abord lire le type et la taille du paquet, puis déclencher un transfert DMA dans un tampon alloué.
Pour d'autres protocoles, cela peut ne pas être possible du tout, s'ils n'utilisent
'\n'
que des délimiteurs de fin de message: par exemple, des protocoles basés sur du texte qui utilisent comme délimiteur. (Sauf si le périphérique DMA prend en charge la correspondance sur un caractère.)Comme vous pouvez le voir, il y a beaucoup de compromis à considérer ici. Certains sont liés à des limitations matérielles (nombre de canaux, conflits avec d'autres périphériques, correspondance sur les caractères), certains sont basés sur le protocole utilisé (délimiteurs, longueur connue, tampons mémoire).
Pour ajouter quelques preuves anecdotiques, j'ai fait face à tous ces compromis dans un projet de loisir qui utilisait de nombreux périphériques différents avec des protocoles très différents. Il y avait quelques compromis à faire, principalement basés sur la question "combien de données est-ce que je transfère et à quelle fréquence vais-je le faire?". Cela vous donne essentiellement une estimation approximative de l'impact d'un simple transfert déclenché par interruption sur le processeur. J'ai donc donné la priorité au transfert I2C susmentionné toutes les 5 ms par rapport au transfert UART toutes les quelques secondes qui utilisait le même canal DMA. Un autre transfert UART se produisant plus souvent et avec plus de données d'autre part a la priorité sur un autre transfert I2C qui se produit plus rarement. Ce sont tous des compromis.
Bien sûr, l'utilisation de DMA présente également des avantages, mais ce n'est pas ce que vous avez demandé.
la source
L'utilisation de DMA signifie généralement que vous ne prenez plus d'interruption sur chaque caractère, mais uniquement après qu'un "tampon plein" de caractères a été reçu (ou transmis). Cela augmente la latence du traitement de ces caractères - le premier caractère n'est traité qu'après réception du dernier caractère du tampon.
Cette latence peut être une mauvaise chose, en particulier dans une application sensible à la latence telle que le MIDI, où quelques ms ici et là peuvent ajouter de sérieux problèmes de jouabilité pour les performances live.
la source
Le DMA ne remplace pas les interruptions - elles sont généralement utilisées ensemble! Si vous utilisez DMA pour envoyer des données via un UART, par exemple, vous avez toujours besoin d'une interruption pour vous dire quand l'envoi est terminé.
la source
L'utilisation de DMA introduit des questions et des défis intéressants au-delà de toutes les autres considérations relatives à l'utilisation des périphériques UART. Je vais vous donner quelques exemples: Supposons que votre uC se trouve sur un bus RS485 (ou autre) avec d'autres appareils. Il y a beaucoup de messages sur le bus, certains sont destinés à votre uC, d'autres non. Supposons en outre que ces voisins de bus parlent tous un protocole de données différent, ce qui implique que les longueurs de message sont différentes.
Certaines questions qui ne se posent que lors de l'utilisation de DMA sont:
Quoi qu'il en soit, juste matière à réflexion.
la source
Du côté de la réception (si je me souviens bien) DMA se termine soit sur une correspondance de caractères ou sur le nombre de terminaux. Certains protocoles et de nombreuses applications interactives ne s'intègrent pas facilement dans ce modèle et vous devez vraiment gérer les choses caractère par caractère. Les techniques DMA peuvent également être fragiles si la liaison de communication n'est pas fiable, la perte d'un seul caractère dans le flux peut facilement gâcher votre machine d'état DMA.
la source
J'ai utilisé le STM32CubeMx / HAL sur quelques projets maintenant et j'ai constaté que le logiciel de gestion UART qu'il génère présente des défauts certains du côté de la réception.
Lors de la transmission, vous souhaiterez normalement envoyer un bloc de données ou une ligne de texte. Dans ce cas, vous savez à l'avance la durée du transfert de données et l'utilisation du DMA est donc une solution évidente. Vous obtenez une interruption une fois le transfert terminé et pouvez utiliser la fonction de rappel complet UART TX pour indiquer à votre code principal que la transmission est terminée et vous pouvez envoyer un autre bloc de données.
En ce qui concerne la réception des données, les fonctions fournies par ST supposent toutes que vous savez combien de caractères le périphérique émetteur vous donnera avant de commencer à envoyer. Normalement, cela n'est pas connu. La fonctionnalité d'interruption place les données reçues dans une mémoire tampon et indique uniquement qu'il y a des données disponibles lorsque le nombre prédéfini de caractères a été reçu. Si vous essayez d'utiliser le DMA ou d'interrompre la fonctionnalité pour recevoir des données en configurant des transferts séquentiels à un seul caractère, le temps de configuration de chacun d'eux signifie que vous perdrez des caractères à autre chose que les débits de données les plus lents (le débit en bauds que vous commencer à perdre des données dépendra de la vitesse d'horloge de votre processeur) et chargera le processeur de manière excessive, ne laissant aucun cycle d'instruction pour tout autre traitement
Pour contourner cela, j'ai écrit ma propre fonction de gestionnaire d'interruption qui stocke les données dans un petit tampon circulaire local et définit un décompte qui est lu par le code principal (un sémaphore de comptage RTOS) pour indiquer qu'il y a des données reçues prêtes. Le code principal peut alors collecter les données de ce tampon à loisir, peu importe s'il y a un certain retard dans la collecte des données à condition que le tampon local ne déborde pas avant que les données ne soient collectées.
la source