Comment passer des microcontrôleurs «de base» à ARM Cortex?

22

J'ai de nombreuses années d'expérience avec les cœurs 8 bits de divers fabricants - à savoir 8051, PIC et AVR - et j'ai maintenant un Cortex M0 à comprendre. Plus précisément celui-ci , mais j'espère que nous pourrons être plus généraux que cela.

Cela s'avère être un peu plus que ce que j'avais prévu, avec plusieurs documents qui décrivent différentes parties du système avec différents niveaux de détail et aucun vraiment que j'ai vu pour tout connecter ensemble. Cela par rapport à avoir une fiche technique qui explique tout. Je comprends avoir beaucoup plus de choses à documenter en premier lieu, mais le changement de format me lance pour une boucle.

Le site Web ci-dessus a un document qui donne un bon aperçu de chaque sous-système et périphérique isolément, et un autre qui décrit chaque registre en détail, et j'ai tout le code source de leur SDK, y compris les fichiers d'en-tête et quelques exemples complexes, mais je vois toujours rien qui décrit comment tout cela se connecte.

Existe-t-il une procédure pas à pas concise de l'architecture Cortex qui explique la fonction des choses que les petits contrôleurs n'ont tout simplement pas - comme plusieurs couches de bus du CPU aux périphériques, chacune avec son propre temporisateur de surveillance - et comment ils se connectent tous ensemble?

AaronD
la source
Je ne peux pas dire d'après ce que vous avez décrit si vous avez obtenu la fiche technique / le manuel d'utilisation du processeur du fabricant. Cela devrait vous donner une bonne image globale et des détails. D'après l'une des photos du site que vous avez lié, cela ressemble à un processeur NXP. Regardez le numéro de pièce du fabricant et recherchez la documentation du processeur sur leur site. Il y a aussi le site ARM arm.com/products/processors/cortex-m/cortex-m0.php .
DigitalNinja
Désolé pour le retard à y revenir; J'ai été occupé avec d'autres projets. Merci @Adam pour la voix de l'expérience.
AaronD
Et merci @Richard pour la vue d'ensemble de la façon d'y penser et la note sur l'impression de la configuration des broches. Je vous ai voté tous les deux.
AaronD
Vous ne reviendrez jamais, sauf si vous trouvez des exigences de prix extrêmes . Et même alors, vous serez tenté, car il existe un certain nombre de Cortex-M bon marché.
Ronan Paixão

Réponses:

40

J'ai travaillé sur des AVR ainsi que sur des microcontrôleurs ARM Cortex-M3 / M4 / R4. Je pense que je peux offrir quelques conseils généraux. Cela supposera que vous programmez en C, pas en assembleur.

Le CPU est en fait la partie facile. Les types de données C de base seront de tailles différentes, mais vous utilisez quand même uint8 / 16 / 32_t, non? :-) Et maintenant, tous les types entiers devraient être relativement rapides, 32 bits (int) étant le plus rapide. Vous n'avez probablement pas de FPU, continuez donc à éviter les flotteurs et les doubles.

Tout d'abord, travaillez sur votre compréhension de l'architecture au niveau du système. Cela signifie les E / S, la synchronisation, la mémoire, les réinitialisations et les interruptions. En outre, vous devez vous habituer à l'idée de périphériques mappés en mémoire. Sur AVR, vous pouvez éviter de penser à cela car les registres ont des noms uniques avec des variables globales uniques définies pour eux. Sur les systèmes plus complexes, il est courant de faire référence aux registres par une adresse de base et un décalage. Tout se résume à l'arithmétique des pointeurs. Si vous n'êtes pas à l'aise avec les pointeurs, commencez à apprendre maintenant.

Pour les E / S, déterminez comment le multiplexage périphérique est géré. Existe-t-il un contrôle central du multiplexeur pour sélectionner quelles broches sont des signaux périphériques et lesquelles sont des GPIO? Ou définissez-vous les broches en mode périphérique à l'aide des registres périphériques? Et bien sûr, vous devrez savoir comment configurer les GPIO en tant qu'entrées et sorties, et activer le mode à drain ouvert et les tractions / descentes. Les interruptions externes entrent généralement dans cette catégorie également. Les GPIO sont assez génériques, donc votre expérience devrait vous être utile ici.

Le chronométrage se résume à quelques choses. Vous commencez avec une source d'horloge, généralement un cristal ou un oscillateur RC interne. Ceci est utilisé pour créer un ou plusieurs domaines d'horloge au niveau du système. Les puces plus rapides utiliseront une PLL, que vous pouvez considérer comme un multiplicateur de fréquence. Il y aura également des diviseurs d'horloge à différents points. Ils doivent notamment prendre en compte la fréquence d'horloge de votre processeur et les débits dont vous avez besoin pour vos périphériques de communication. Habituellement, c'est assez flexible. Lorsque vous devenez plus avancé, vous pouvez en apprendre davantage sur des choses comme les modes basse consommation, qui sont généralement basés sur le déclenchement d'horloge.

La mémoire signifie flash et RAM. Si vous avez suffisamment de RAM, il est souvent plus rapide de conserver votre programme pendant les premiers développements afin de ne pas avoir à programmer le flash encore et encore. Le gros problème ici est la gestion de la mémoire. Votre fournisseur doit fournir des exemples de scripts de l'éditeur de liens, mais vous devrez peut-être allouer plus de mémoire au code, aux constantes, aux variables globales ou à la pile selon la nature de votre programme. Les sujets plus avancés incluent la sécurité du code et la programmation flash au moment de l'exécution.

Les réinitialisations sont assez simples. Habituellement, vous n'avez qu'à faire attention au minuteur de surveillance, qui peut être activé par défaut. Les réinitialisations sont plus importantes lors du débogage lorsque vous exécutez le même code encore et encore. Il est facile de rater un bogue en raison de problèmes de séquencement de cette façon.

Il y a deux choses que vous devez savoir sur les interruptions: comment les activer et les désactiver et comment configurer les vecteurs d'interruption. AVR-GCC fait ce dernier pour vous avec les macros ISR (), mais sur d'autres architectures, vous devrez peut-être écrire une adresse de fonction dans un registre manuellement.

Les périphériques des microcontrôleurs sont généralement indépendants les uns des autres, vous pouvez donc les apprendre un par un. Il peut être utile de choisir un périphérique et de l'utiliser pour apprendre une partie des éléments au niveau du système. Les périphériques de communication et les PWM sont bons pour l'horloge et les E / S, et les temporisateurs sont bons pour les interruptions.

Ne soyez pas intimidé par le niveau de complexité. Ces microcontrôleurs «de base» vous ont déjà appris une grande partie de ce que vous devez savoir. Veuillez me faire savoir si vous avez besoin de moi pour clarifier quoi que ce soit.

Adam Haun
la source
4
Bonne réponse. Une autre chose à surveiller est les périphériques DMA, qui ont tendance à avoir des interfaces compliquées et sous-documentées dans mon expérience.
Doug McClean
3
"Et maintenant, tous les types entiers devraient être également rapides." En fait, en raison des règles de promotion des nombres entiers en C, l'utilisation de types 8/16 bits peut entraîner beaucoup d'extension de signe / zéro et peut être un problème lorsque la mémoire Flash est faible. Donc, s'il y a de la mémoire RAM à épargner, il pourrait être avantageux d'utiliser plus de types 32 bits ou au moins de préférer int/ int_leastN_Ttypes pour les variables de pile.
user694733
J'ai fait une erreur sur mon commentaire. Je voulais dire; utilisez des int_fastN_ttypes, pas des int_leastN_ttypes.
user694733
@ user694733: Je souhaite que la norme C permette au code de demander un entier qui occupe une taille donnée en mémoire et peut opérer sur des valeurs dans une plage particulière, mais avec une sémantique vaguement spécifiée en dépassant cette plage. Sur quelque chose comme l'ARM, un int16_tsera souvent aussi rapide que int32_tpour les valeurs stockées en mémoire, mais la norme exige que sur les plates-formes où intest de 17 bits ou plus, int16_t x=32767; x+=2;doit être défini xsur -32767, nécessitant fréquemment des instructions d'extension de signe même si le code ne jamais utiliser le comportement d'habillage.
supercat
La norme @supercat C requiert un comportement d'habillage uniquement pour les types non signés. Pour les types signés, tout habillage est UB, en raison de différentes représentations possibles. Donc, avec x+=2, il serait légal d'utiliser des instructions pour les types 16 bits, car le compilateur peut supposer que la valeur ne sera pas bouclée, et donc son utilisation ne changerait pas le comportement observable. Mais je pense que ARM n'a pas d'instruction ADD 16 bits qui rendrait cela possible. (Je peux me tromper, mes connaissances sur le jeu d'instructions ARM ne sont pas bonnes.)
user694733
8

Il est utile de se rappeler qu'ARM détient la propriété intellectuelle du microprocesseur, mais ne fabrique pas réellement de pièces. Au lieu de cela, les fabricants concèdent sous licence les différentes versions de processeur ARM et produisent leurs propres pièces uniques avec des combinaisons individuelles de fonctionnalités et de périphériques.

Cela dit, si vous êtes nouveau dans l'architecture, il serait probablement judicieux de commencer avec la documentation d'ARM qui est, essentiellement, la documentation de base pour tous ces microprocesseurs.

Par exemple, le Cortex-M0 est décrit sur le site Web d'ARM .

Il existe également une liste de livres liés à l'ARM qui répondent à une grande variété de besoins et d'intérêts.

Enfin, il y a les fiches techniques des fabricants spécifiques. Pour le M0, Cypress, NXP et STMicroelectronics ne sont que trois des nombreux fabricants de pièces réelles basées sur le Cortex-M0.

(Et non, je ne travaille pas pour ARM et je ne l'ai jamais fait.)

Edward
la source
1
C'est une réponse assez générique qui ne fait pas beaucoup plus que des liens vers certains documents Cortex-M0, que je suis sûr que l'OP peut trouver par lui-même.
Jay Carlson
1
Il répond directement à la question qui demandait de l'aide pour trouver une documentation globale. Cette réponse répond directement à ce besoin et explique pourquoi les choses sont telles qu'elles sont.
Edward
8

Une grande différence est l'utilisation de bibliothèques fournies par le fournisseur. Pour les PIC, Atmels, etc., les bibliothèques de base (pour gpio, timers, adc, etc.) n'étaient pas beaucoup utilisées par la plupart des développeurs. D'après mon expérience, les gens les utiliseraient (tout au plus) comme guides lors de l'écriture de leur propre code.

Cependant, avec ARM, les bibliothèques sont presque toujours utilisées. Il existe une norme, «CMSIS», que les fabricants sont invités à suivre. La plupart le font. Il facilite la portabilité du code (entre les différents ARM et entre les fabricants) et fournit une méthode "standardisée" pour structurer votre code. Les gens s'habituent à voir et à comprendre les fonctions de la bibliothèque.

Bien sûr, certains développeurs accèdent directement aux registres, mais ce sont les valeurs aberrantes :)

Pour répondre à votre question, j'ai trouvé très utile de lire la documentation de la bibliothèque. ST a un code bien développé, avec un grand fichier d'aide créé par Doxygen. Vous pouvez voir quelles sont toutes les options pour chaque module matériel.

Pour utiliser GPIO comme exemple, la fonction d'initialisation gère:

  • Direction (entrée ou sortie)
  • pullups / pulldowns
  • collecteur ouvert / push-pull
  • vitesse de balayage
  • etc.

En regardant les options, vous pouvez voir ce qui est possible. Et, bien sûr, vous apprendrez comment passer ces options dans la fonction Init!

OK, maintenant que je l'ai dit, je vois que votre ARM spécifique n'a pas de bibliothèques compatibles CMSIS. Au lieu de cela, ils ont leur SDK propriétaire disponible en téléchargement. Je commencerais à regarder leurs documents SDK.

Si vous n'êtes pas marié avec ce produit spécifique, je pourrais vous recommander de trouver un autre fournisseur avec des bibliothèques plus conformes. Vous allez de toute façon grimper une courbe d'apprentissage, alors vous pourriez aussi bien rendre votre investissement plus portable ...

Les BRAS sont amusants! Je n'ai pas regardé en arrière.

bitsmack
la source
"Pour les PIC, Atmels, etc., les bibliothèques n'étaient pas beaucoup utilisées par la plupart des développeurs." Je ne sais pas d'où cela vient. Je n'ai utilisé que des PIC, pas des AVR, mais je ne voudrais certainement pas écrire ma propre bibliothèque, par exemple, pour l'interface hôte USB, la pile TCP ou le système de fichiers de la carte SD. Les bibliothèques de Microchip pour tout cela semblent tout à fait adéquates.
tcrosley
Ah, @tcrosley, vous avez certainement raison. J'essayais seulement de me référer aux fonctionnalités couvertes par les périphériques de base: gpio, timers, adc, etc.
bitsmack
Je suis d'accord, j'accède généralement au GPIO, aux minuteries, aux horloges et à l'UART R / W directement. J'utilise parfois leurs appels de bibliothèque pour la configuration I2C, SPI, ADC et UART mais pas toujours. Beaucoup de registres, que vous parliez PIC (et en particulier PIC32) ou ARM.
tcrosley
Je pense que cette réponse est la plus pragmatique répertoriée pour cette question, même si elle ne s'applique pas au contrôleur spécifique de l'OP. Je pense que vous pouvez faire un peu de bonne ingénierie embarquée sans comprendre l'AHB ou le NVIC.
Jay Carlson
@JayCarlson Merci! Votre modification de cette réponse a été rejetée, car nous ne sommes pas censés modifier les publications des autres de manière si significative. Mais c'était vraiment une bonne info! Je vous suggère de le poster en tant que votre propre réponse, donc cela aidera les gens et sera également voté :)
bitsmack
5

Bon moment pour bouger; les 8 bits meurent rapidement; lorsque vous pouvez acheter une carte à 5 $ avec (par exemple) un STM32F103 qui est un microcontrôleur ARM 32 bits plutôt capable (avec USB même!), il ne fait aucun doute que les temps ont changé.

Vous avez déjà eu d'excellentes réponses, mais je dirais principalement "oubliez l'assemblage" et presque "oubliez de vous soucier du fonctionnement du processeur à bas niveau" - un jour, il y aura un cas d'angle où vous devrez creuser (une optimisation spécifique ou pour le débogage) mais les cœurs ARM exécutent exceptionnellement bien le code C (par conception) et vous avez rarement besoin de vous aventurer profondément dans les tripes.

Cela signifie que vous passerez un certain temps à vous cogner la tête contre les problèmes avec les compilateurs (et en particulier les éditeurs de liens et les makefiles) qui vous font des erreurs obscures, mais ils sont tous surmontables.

Les entrailles du fonctionnement des ARM (c'est-à-dire les livres de processeurs ARM) sont denses et peu intéressantes jusqu'au jour où vous devez réellement les optimiser (et vous serez étonné de voir à quel point c'est rare lorsque vous avez des registres 32 bits et votre PLL '' d L'horloge du processeur est de l'ordre de 100 MHz).

Le jeu d'instructions ARM "old skool" est beaucoup plus facile à lire un désassemblage que le "Thumb2" beaucoup plus récent - qui est ce que vous trouverez sur la plupart des ARM modernes de niveau microcontrôleur (Cortex) - mais encore une fois les entrailles des instructions en langage assembleur se fondent généralement en arrière-plan; si vous avez le bon ensemble d'outils (en particulier un débogueur de niveau source décent avec des points d'arrêt / une seule étape, etc.), vous ne vous souciez pas trop du fait qu'il s'agisse d'ARM.

Une fois que vous êtes dans le monde des registres 32 bits et des largeurs de bus de données 32 bits et tout ce que vous avez toujours voulu disponible sur puce, vous ne voudrez plus jamais revenir à un processeur 8 bits; Fondamentalement, il n'y a souvent aucune pénalité pour "prendre les choses en douceur" et écrire du code pour être plus lisible qu'efficace.

Cependant ... périphériques ... oui et c'est le hic.

Vous avez certainement une tonne de choses à jouer avec les MCU modernes, et beaucoup d'entre elles sont assez chouettes; vous trouverez souvent un monde de sophistication bien au-delà des périphériques sur puce AVR, PIC et 8051.

Une minuterie programmable? Non, j'en ai huit! DMA? Que diriez-vous de 12 canaux avec priorité programmable et mode rafale et mode chaîné et auto-rechargement et .. et .. et ...

I2C? I2S? Des dizaines d'options de multiplexage de broches? Quinze façons différentes de reprogrammer le flash sur puce? Sûr!

On a souvent l'impression que vous êtes passé de la famine à la fête avec les périphériques et il est courant qu'il y ait des morceaux entiers d'une puce que vous admirerez mais que vous utiliserez à peine (d'où le déclenchement d'horloge).

La quantité de matériel sur puce (et les variations de celle-ci dans la gamme de puces d'un seul fournisseur) est aujourd'hui assez ahurissante. Un fournisseur de puces aura bien sûr tendance à réutiliser les blocs IP, donc une fois que vous vous serez familiarisé avec une certaine marque, cela deviendra plus facile, mais "merde fait de plus en plus de nos jours".

Si quoi que ce soit, les périphériques et leurs interactions (et DMA et interruptions et allocation de bus et et et ...) sont SI complexes (et, à l'occasion, pas exactement comme décrit dans les fiches techniques) que les ingénieurs ont souvent une gamme préférée de MCU ARM et ont tendance à vouloir s'y tenir simplement parce qu'ils connaissent les périphériques et les outils de développement.

De bonnes bibliothèques et des outils de développement (c'est-à-dire un cycle de compilation + débogage rapide avec un débogueur approprié) et un grand nombre d'exemples de projets de code de travail sont absolument cruciaux pour votre choix d'ARM MCU de nos jours. Il semble que la plupart des fournisseurs disposent désormais de cartes d'évaluation extrêmement bon marché (

Comme je suis sûr que vous l'avez remarqué, une fois que vous avez dépassé le niveau du microcontrôleur avec les ARM et dans le niveau SOC (par exemple, les SOC de style Raspberry Pi / etc.), les règles changent complètement et tout dépend de quel type de Linux vous allez pour courir, parce que - à quelques exceptions près - vous seriez en train d'aboyer fou pour essayer autre chose.

Fondamentalement; quel que soit le processeur qui a pu être présélectionné pour vous sur ce concert, achetez-vous une poignée de cartes d'évaluation basées sur Cortex super bon marché auprès de quelques fournisseurs différents (TI, STM, Freescale et plus viennent à l'esprit) et avoir un hack autour avec l'exemple de code fourni.

Dernier conseil; une fois que vous avez trouvé la page ou les trois dans la fiche technique qui décrit les options de multiplexage des broches pour la puce de numéro de pièce exacte avec laquelle vous travaillez, vous pouvez l'imprimer et la coller sur le mur. Découvrir tard dans un projet qu'une certaine combinaison de périphériques est impossible à cause du multiplexage des broches n'est pas amusant, et parfois cette information est tellement enfouie que vous jureriez qu'ils essaient de la cacher :-)

Richard Aplin
la source
un addenda rapide - si votre projet est bien plus que le contrôleur le plus simpliste, pensez à utiliser un RTOS - il y a quelque chose d'une courbe d'apprentissage avec tout ce que vous choisissez, mais même les plus petits ARM ont beaucoup de punch de nos jours pour exécuter un système d'exploitation multithread. Personnellement, j'ai trouvé que ChibiOS était un excellent mélange de Lean-pourtant capable (en particulier fonctionnant sur STM32 où il est livré avec une belle bibliothèque de périphériques), mais il y a un certain nombre de choix.
Richard Aplin
4

Je suis également venu d'AVR et maintenant je m'en tiens généralement à STM32 (Cortex-M). Voici ce que je recommande pour les débutants et reflète mes propres difficultés quand j'ai commencé:

  1. Obtenez une carte avec un débogueur, ou au moins un connecteur JTAG (puis achetez un débogueur JTAG). Il y en a beaucoup bon marché et vous économiserez beaucoup de temps en l'utilisant.

  2. Obtenez un bon IDE avec tout inclus. J'avais l'habitude de recommander le CooCox CoIDE il y a longtemps. Depuis lors, il a arrêté et redémarré le développement, donc je ne sais pas comment cela se passe maintenant. «Un bon IDE» vous permet de faire clignoter la LED Hello World de base en un rien de temps.

  3. "Un bon IDE" devrait configurer les en-têtes CMSIS du fabricant. Il s'agit essentiellement des mappes de registre qui permettent une écriture plus facile des programmes C / C ++, avec des noms de variables au lieu de nombres et pointeurs simples.

  4. Essayez d'utiliser les bibliothèques périphériques du fabricant, si vous n'avez pas besoin des meilleures performances absolues. En fait, vous ne le faites pas pour l'instant, puisque vous apprenez. Si, plus tard, vous constatez que vous devez en presser davantage, examinez le code de la bibliothèque pour voir comment il fait quoi. La bonne chose à propos des bibliothèques est également qu'elles vous permettent généralement d'utiliser de nombreuses puces différentes du même fabricant avec le même code.

  5. À la différence d'AVR, les puces ARM commencent avec des périphériques désactivés. Vous devez d'abord les activer. Une bonne bibliothèque de périphériques contiendra des exemples sur la façon d'utiliser correctement les périphériques, et vous pouvez obtenir plus d'informations dans la fiche technique de l'appareil. N'oubliez donc pas d'activer les horloges et les périphériques avant de les utiliser. Oui, même les ports d'E / S sont considérés comme des périphériques.

  6. Codez à mesure que vous apprenez. N'essayez pas de tout faire d'un coup, car c'est vraiment assez complexe. Je commencerais par apprendre l'arbre d'horloge (bus APB, AHB, etc.) et comment les horloges et les diviseurs d'horloge interagissent. Ensuite, je chercherais où l'IDE stocke les scripts de l' éditeur de liens et le code de démarrage pour votre appareil. Le script de l'éditeur de liens est à peu près la façon dont vous organisez la mémoire (où se trouvent la RAM, le flash, la table vectorielle ISR, etc.). Le script de démarrage configure votre programme (des choses comme la copie des initialiseurs de variables globales du flash vers la RAM). Certains IDE ont des scripts de démarrage dans ASM et d'autres en C. Parfois, vous pouvez en rechercher un autre dans la langue de votre choix.

  7. Obtenez le débogueur dès que possible. Il est assez courant de faire une erreur au début, en faisant certaines choses (généralement l'initialisation matérielle) dans un ordre différent de celui que vous devriez. Cela déclenche parfois une exception ISR qui vous met dans while(1);une boucle infinie (implémentation par défaut pour cet ISR) qui arrête votre programme et il est difficile de tracer même avec un débogueur. Imaginez sans débogueur.

  8. En parlant d'un débogueur, essayez également de faire fonctionner l'UART, puis utilisez un adaptateur série-USB pour lire cela. printf()le débogage est toujours utile :-)

Ronan Paixão
la source
3

Je n'ai pas beaucoup travaillé sur 8051, AVR ou PIC. Mais récemment, j'ai commencé à regarder la gamme de processeurs ARM Cortex MX. Par conséquent, je ne peux pas vous en dire beaucoup sur la transition de 8051, AVR ou PIC, mais surtout du point de vue d'un débutant.

Le processeur ARM®Cortex ™ -M4 est basé sur l'architecture Harvard, a donc des bus de données et d'instructions distincts. Ci-dessous, une image de haut niveau.

entrez la description de l'image ici

Cette semaine, des représentants de NXP visiteront nos installations. Je vérifierai avec eux les ressources NXP ARM-Cortex Mx et les posterai ici. Freescale a un microcontrôleur Kinetis Low Power 32 bits (MCU) basé sur les cœurs ARM® Cortex®-M , je comprends qu'ils ont également des guides similaires pour apprendre les processeurs ARM. Malheureusement, je ne les ai pas recherchés.


Les références:

Mahendra Gunawardena
la source