Question:
Traitement du résultat de la conversion ADC: DMA vs registres de processeur
Firat.Berk.Cakar
2019-04-23 20:24:04 UTC
view on stackexchange narkive permalink

J'ai une conversion ADC périodique (toutes les 50 micro-secondes) et j'utilise le résultat pour faire d'autres calculs et mettre à jour les registres de charge PWM. L'ADC est déclenché par le compteur ascendant du PWM matériel et doit être effectué exactement à ce moment-là. J'utilise un Teensy 3.2 (ARM M4) et bien que ce soit une bête, je dois être aussi rapide que possible avec l'ADC pour pouvoir saisir le reste des calculs avant le début du prochain cycle de service.

L'idée générale d'opérer plus rapidement semble être d'utiliser DMA qui transfère les résultats de conversion directement dans la mémoire système sans impliquer le processeur, ce qui ressemble à

ADC_result -> DMA -> SRAM,

Mais après cela, je dois récupérer le résultat de la SRAM pour le traiter, ce qui ressemble à:

ADC_result -> DMA -> SRAM -> CPU -> enfin traité.

Bien sûr, ne pas impliquer le DMA est beaucoup plus lent:

ADC_result -> CPU -> SRAM -> CPU -> enfin traité.

Ma question est, puisque je dois mettre le résultat de la conversion dans le processeur pour être traité de toute façon, ne puis-je pas simplement le stocker directement dans les registres du processeur sans impliquer du tout DMA ou SRAM et le processus est immédiat?

ADC_result -> CPU -> enfin traité.

Je voudrais faire quelques remarques pour clarifier davantage la nature de mon problème et tester les éventuelles lacunes dans ma compréhension.

Premièrement, d'après ce que j'ai compris, le DMA est principalement utilisé lorsqu'il y a une véritable journalisation à faire et que nous utiliserions le processeur en parallèle, surtout si les données fournissant le périphérique sont considérablement plus rapides / plus lentes que le processeur. Ce n'est pas mon cas, car tous les calculs suivants dépendent du résultat de la conversion ADC et j'ai très peu de données envoyées toutes les 50 micro-secondes plutôt que d'énormes morceaux.

Deuxièmement, il n'y a aucune garantie que je pourrai utiliser librement les registres du processeur, car ils sont soumis à l'optimisation du compilateur et pourraient être totalement ignorés (en utilisant le mot-clé register en C).

Je serais ravi d'entendre vos commentaires à ce sujet, surtout si ma compréhension est quelque peu imparfaite ou tout simplement fausse.

Vous écrivez dans un commentaire que vous * "implémentez un algorithme de contrôle de moteur." * Dans presque toutes les circonstances que j'ai connues, cela a nécessité une synchronisation échantillon-sortie très soigneusement conçue.J'aurai tendance à garder le cycle de mesure échantillon à échantillon exact de l'un à l'autre (cela peut être réalisé avec DMA ou, assez souvent, sans DMA) et aussi garder le temps de l'échantillon à la sortie aussi proche du cycle-exact que je peux réaliser.Cela signifie presque toujours "un certain assemblage" mélangé avec C. Sinon, le contrôle en boucle fermée n'est pas assez compétitif et échouera finalement à mes parieurs sur le marché.
J'aurais dû ajouter ceci: je garde également l'échantillon à la sortie aussi court que possible.** Court ** est même * plus important * qu'un * timing cohérent *, bien que les deux soient importants.Un algorithme de contrôle peut accepter une certaine incohérence dans le délai, si le délai est très court.Mais les longs retards - et en particulier les longs délais avec variabilité pour eux - sont une mort certaine.Gardez les choses aussi serrées et proches que possible et gardez la variabilité aussi minimale que possible.Le reste suivra, si vous pouvez le faire.
Quel est le pôle dominant du moteur?
Cinq réponses:
TimWescott
2019-04-23 20:39:58 UTC
view on stackexchange narkive permalink

Si vous écrivez simplement une fonction qui lit le résultat ADC dans une variable, fait des calculs dessus, puis écrit le résultat dans PWM, et si vous utilisez un compilateur décent avec une optimisation activée, les données critiques seront probablementfinir dans un registre que vous le vouliez ou non.Ce n'est vraiment pas si différent de configurer DMA juste pour que vous puissiez récupérer un emplacement mémoire et faire la même chose.

Là où j'utiliserais DMA pour ce genre de chose, c'est si j'allais faire quelque chose comme récupérer plusieurs échantillons ADC par cycle du contrôleur (ce que je fais souvent) - le DMA économise beaucoup par rapport à la surcharge d'unISR pour collecter les données d'un ADC.

merci pour la perspicacité, mais j'implémente un algorithme de contrôle du moteur qui nécessite un échantillonnage à des moments très spécifiques afin de mesurer le courant lorsque les 3 commutateurs du côté haut sont allumés.Donc, je ne peux vraiment pas utiliser une fonction et interroger l'ADC.
@Firat.Berk.Cakar Je pense que beaucoup de choses à propos d'un système de commande de moteur seraient si bas que rien de tout cela ne serait nécessaire
Je n'ai pas dit d'utiliser une fonction pour interroger l'ADC.Je viens de dire que vous pouvez lire le registre ADC, le gérer et écrire dans PWM.Vous devez configurer votre ADC pour déclencher une minuterie, sans aucun doute.
@ScottSeidman, si l'OP contrôle le courant du moteur, il veut un contrôle cycle par cycle, ou presque cycle par cycle (le dernier que j'ai fait, je me suis débrouillé en itérant la boucle de contrôle tous les 2 cycles PWM, mais je ne le fais pasprétendre être très fier de cela).Pour cela, vous voulez pouvoir avoir un délai faible et prévisible.
pgvoorhees
2019-04-23 20:45:20 UTC
view on stackexchange narkive permalink

Ma question est, puisque je dois mettre le résultat de la conversion dans le processeur pour être traité de toute façon, ne puis-je pas simplement le stocker directement dans les registres du processeur sans impliquer du tout DMA ou SRAM et le processus est immédiat?

Non, ce n'est pas possible dans un Cortex-M4. De plus, vous ne voudriez pas que cela soit possible. Pour clarifier pourquoi: Si vous écrivez votre programme en "non assemblé", alors vous allez utiliser un compilateur. Les compilateurs respectent généralement l'ABI ARM qui leur permettra d'utiliser des registres pour le traitement des données. Ce que vous suggérez entraînera le compilateur et l'ADC à utiliser le même emplacement à des fins différentes en même temps. Votre programme se comportera mal. Vous n'aurez aucun moyen de dire à un compilateur qu'un certain registre est interdit.

Bien sûr, ne pas impliquer le DMA est beaucoup plus lent:

ADC_result -> CPU -> SRAM -> CPU -> enfin traité.

Ce n'est ni tout à fait correct ni incorrect. C'est spécifique à l'application. Une interruption peut charger le résultat ADC du registre de données ADC directement dans un registre CPU si la fonction utilise uniquement ces données localement et est "courte". il est possible que les données ne soient jamais stockées dans SRAM.

Maintenant, que vous utilisiez DMA ou une interruption pour transférer vos données, les interruptions sont certainement plus faciles à comprendre du point de vue du flux de données. En outre, les interruptions vous permettent de répondre échantillon par échantillon, ce qui peut être nécessaire pour votre application. L'inconvénient est que cela vous oblige à absorber les frais généraux liés à l'entrée et à la sortie d'une interruption. Cela peut être important pour votre application ou non.

Si vous devez faire autant de traitement, que ce temps est précieux et que vous ne pouvez pas vous permettre d'opérer sur un échantillon à la fois, DMA peut vous sortir de cette contrainte.DMA vous permet d'amortir les coûts d'entrée / sortie d'interruption sur de nombreux échantillons (en fonction de votre délai).De plus, il existe certains algorithmes mathématiques qui sont beaucoup plus efficaces lorsqu'ils sont exécutés sur des tampons plutôt que échantillon par échantillon lorsqu'ils arrivent.Encore une fois, cela dépendra de votre application.

À moins que vous ne précisiez les exigences de vos applications, il est impossible de dire quelle est la meilleure approche.

Merci pour la réponse longue et complète.Tout d'abord, je dois commencer la conversion à un moment très précis (voir mon commentaire sur une autre réponse) et j'ai également édité le premier paragraphe de ma question.Donc, en substance, la conversion doit être lancée par l'interruption et maintenant la question est plutôt de sauvegarder cette valeur avec ou sans DMA.Si j'utilise le DMA, cela ne peut-il pas entraîner des problèmes de concurence?Par exemple, lorsque je commence la conversation dans l'interruption (avec DMA) et que je passe directement à la traiter avec dans l'interruption, n'est-il pas possible que les données ne soient pas toujours là?
FWIW, si vous avez vraiment besoin d'une synchronisation exacte, lorsque vous lisez attentivement le manuel de référence, vous verrez que l'ADC peut être déclenché par le matériel du PDB qui peut être déclenché par le Flex Timer.Si vous configurez correctement votre matériel, vous n'aurez pas besoin d'interrompre pour démarrer la conversion.
Adam Haun
2019-04-23 21:44:56 UTC
view on stackexchange narkive permalink

Il y a trois événements qui comptent ici:

  1. Début de la conversion ADC
  2. Fin de la conversion ADC
  3. Date limite de mise à jour du cycle de service PWM

Votre début de conversion doit être déclenché par le matériel. Il semble que votre PWM le fasse déjà.

Vous devez effectuer le traitement entre la fin de la conversion et la date limite. La meilleure façon de procéder est que la fin de la conversion déclenche une interruption du processeur. Votre ADC devrait pouvoir le faire. Dans l'ISR, le CPU peut effectuer le traitement et mettre à jour le cycle de service.

Si vous écrivez du code C, vous n'avez pas à vous soucier de la SRAM et des registres. Lisez simplement le résultat ADC dans une variable entière. Voici un pseudo-code:

  void ADC_EOC_ISR (void)
{
    uint16_t adc_result = * ADC_RESULT_REG_ADDR;
    uint16_t new_duty_cycle_value = compute_new_duty_cycle (adc_result);
    * PWM_DUTY_CYCLE_REG = new_duty_cycle_value;
}

uint16_t compute_new_duty_cycle (commentaires uint16_t)
{
    ... // Traitez ici
}
 

La méthode exacte pour accéder au résultat ADC et aux registres de cycle d'utilisation PWM dépend du MCU que vous utilisez et des fichiers d'en-tête / pilotes fournis.

Simon Richter
2019-04-24 00:51:31 UTC
view on stackexchange narkive permalink

L'utilisation de DMA transforme votre problème hard realtime (traiter l'échantillon avant que l'échantillon suivant ne soit écrasé) en un problème soft realtime (traiter les échantillons plus rapidement qu'ils ne s'accumulent dans le tamponet avant que le tampon ne soit plein).

Les problèmes de temps réel difficiles sont ennuyeux à gérer, vous avez généralement besoin d'une source d'interruption synchrone avec l'ADC (soit une interruption "conversion terminée" de l'ADC, soit une interruption de minuterie périodique qui démarre également la conversion ADC), ce qui signifie quevotre CPU passera beaucoup de temps à entrer et sortir des gestionnaires d'interruptions.

Cela peut être une conception valide si l'horloge ADC est suffisamment lente pour que le gestionnaire d'interruption se termine avant l'arrivée de l'interruption suivante, et c'est l'interruption de priorité la plus élevée (donc les autres gestionnaires d'interruption n'arrêtent pas le traitement des données), mais c'est uncompromis d'ingénierie: la conception basée sur DMA est plus simple, donc à moins que le retard et la gigue aient besoin d'être étroitement contrôlés, c'est probablement le meilleur choix.

Dmitry Grigoryev
2019-04-24 13:02:31 UTC
view on stackexchange narkive permalink

Je suis presque sûr que vous n'avez pas besoin de faire ce que vous voulez (et à la place de consommer le résultat ADC directement dans l'interruption comme le suggère @AdamHaun), mais une astuce qui fonctionne généralement est d'utiliser les registres FPU .Vous devrez vérifier la documentation de votre compilateur, mais avec la plupart des compilateurs que j'ai vus, si vous n'utilisez aucun calcul flottant dans votre code, le compilateur ne touchera pas les registres FPU (D0-D15), et vous pouvez utiliserles vous-même comme stockage temporaire rapide.



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 4.0 sous laquelle il est distribué.
Loading...