Question:
où sont stockées les variables constantes dans le microcontrôleur?
Arun Joe Cheriyan
2017-01-20 13:25:49 UTC
view on stackexchange narkive permalink

Conformément à la configuration de la mémoire du programme C, les variables constantes sont stockées dans le segment de données initialisé de la RAM.Mais selon certaines dispositions de la mémoire du microcontrôleur, les variables const sont stockées dans la mémoire FLASH. J'ai également vu que la taille du fichier BIN de mon code augmente lorsque je change const variables aux définitions de macro?Aidez-moi à dissiper cette ambiguïté.J'ai utilisé le Nuc2240 Cortex M0 .

La RAM dans la plupart des micros est volatile, donc les constantes sont stockées en flash et peuvent (ou non) être copiées dans la RAM lors de l'initialisation (cela dépend du micro).La «disposition de la mémoire du programme C» que vous référencez n'est pas un standard en tant que tel, beaucoup de ces types de détails dépendent de l'implémentation.C lui-même n'est que le langage de haut niveau, l'utilisation de la mémoire sera déterminée par le compilateur et l'éditeur de liens, avec une certaine connaissance de la plate-forme cible.Je ne vois aucune «ambiguïté» là-dedans, sauf si j'ai mal compris votre préoccupation?
Copie possible de [Que réside dans les différents types de mémoire d'un microcontrôleur?] (Http://electronics.stackexchange.com/questions/237740/what-resides-in-the-different-memory-types-of-a-microcontroller).
Plusieurs schémas différents sont discutés dans les réponses ici (chargez la constante à partir de la mémoire flash ou de la RAM, ou encodez-la dans l'instruction).Vous pouvez voir ce que fait votre chaîne d'outils dans divers cas en affichant une liste de désassemblage du programme et en suivant les instructions de l'assembleur.De nombreux IDE permettent de générer des listes de désassemblage ou vous pouvez utiliser un programme autonome.
Cinq réponses:
Neil_UK
2017-01-20 14:47:01 UTC
view on stackexchange narkive permalink

Si vous écriviez un assembleur, vous décideriez quels emplacements sont utilisés pour contenir quelles constantes ou variables, via org ou des directives similaires.

Lorsque vous écrivez C, la chaîne d'outils C que vous utilisez stockera les éléments là où ils ont été programmés.Les variables ont évidemment tendance à aller dans la RAM, les constantes peuvent aller dans la RAM ou Flash, le programme a tendance à aller dans Flash.

Tout dépend de la façon dont l'outil pour ce processeur cible particulier a été conçu, d'où il obtient ses instructions d'où placer les choses.Tout cela peut être intégré au code, auquel cas vous n'avez pas votre mot à dire, il va là où les créateurs de la chaîne d'outils ont choisi de l'envoyer.Il peut prendre des directives quelque part (code source, ligne de commande, make file, variable d'environnement) afin que vous puissiez rebaser des choses.

Lisez votre documentation spécifique.Ce n'est pas de la physique, tout dépend du caprice de l'homme.

Ce n'est pas la tâche du compilateur mais du générateur de code et de l'éditeur de liens de placer des segments avec des constantes à un emplacement à l'intérieur de l'EPROM, du FLASH ou de la RAM tamponnée par batterie.Mais les constantes peuvent également être placées dans la RAM volatile si elles sont initialisées au démarrage du programme par un code spécial généré par le compilateur.
ouais, le compilateur, c'est moi qui suis paresseux, la chaîne d'outils.
Jon
2017-01-20 20:15:05 UTC
view on stackexchange narkive permalink

La réponse à votre question est spécifique à l'architecture particulière que vous utilisez. Puisque vous avez mentionné ARM, je vais vous donner une réponse basée sur ceci.

ARM Cortex est une conception basée sur des registres, donc fondamentalement tous les opérandes (const ou non) doivent se frayer un chemin dans l'un des registres internes avant de pouvoir être utilisés par les instructions du programme. Ceci est essentiel pour répondre à votre question, car l'architecture permet de le faire de différentes manières.

Pour les petites constantes (généralement inférieures à 8 ou 10 bits), la valeur peut être encodée directement dans certaines instructions. Par exemple, il existe une instruction ADD #imm qui ajoutera une valeur de 12 bits codée dans le mot d'instruction à un registre. Cela peut être utilisé pour spécifier directement une constante dans votre programme. Si vous ajoutiez la même constante à différents endroits dans votre code et que la valeur était de 12 bits ou moins, le compilateur utiliserait simplement une instruction ADD #imm partout où votre constante était requise. En d'autres termes, le const réel sera répliqué à plusieurs endroits dans tout le code stocké dans FLASH.

Si la constante est grande, cela ne fonctionnera pas, donc la valeur devra être stockée dans son propre emplacement mémoire FLASH dédié. La puce a une autre instruction, appelée LDR, qu'elle utilise pour déplacer une valeur d'un emplacement de mémoire dans les registres internes où elle peut être utilisée. Cette instruction ne se soucie pas de savoir si la valeur est physiquement stockée dans FLASH ou RAM, elle extrait simplement la valeur d'une adresse spécifique en mémoire et la met dans un registre. Notez que par rapport à la situation avec de petites constantes, cela nécessite un cycle d'instructions supplémentaire, mais si la constante est utilisée à plusieurs reprises dans un bloc de code, le compilateur la mettra en cache en la mettant dans un registre de réserve s'il en existe un.

Mais maintenant, nous rencontrons un problème potentiel. Sur la plupart des puces Cortex, la mémoire FLASH fonctionne à la même vitesse ou plus lentement que le cœur du processeur. Si nous tentons d'exécuter une instruction LDR à partir d'un emplacement FLASH, cette opération de lecture de la mémoire physique doit concurrencer la lecture de l'instruction suivante. Cela crée un goulot d'étranglement qui oblige le processeur à se bloquer jusqu'à ce que les données aient été lues. Pire encore, sur de nombreuses implémentations, le FLASH fonctionne très lentement et un cache pipeline est utilisé pour fournir des instructions au processeur plus rapidement. Dans ces appareils, la lecture, par exemple, d'un tableau de valeurs constantes peut exposer le goulot d'étranglement fondamental de l'accès FLASH causant de graves pertes de performances.

Pour cette raison, de nombreux compilateurs chercheront à copier toutes les données constantes dans des emplacements de RAM de réserve si possible. Cela évitera de tels problèmes, et étant donné que l'accès à la RAM est normalement plus rapide que FLASH, cela peut éviter de nombreux goulots d'étranglement des performances. S'il y a de toute façon de la RAM inutilisée dans votre programme, alors il n'y a pratiquement pas de surcharge pour le compilateur pour faire cela.

Il y a donc certainement une logique dans la façon dont le compilateur alloue des données constantes à la mémoire physique, mais heureusement, dans la plupart des situations, les concepteurs de puces et de compilateurs ont fait tout ce dur travail pour vous, et vous pouvez simplement être sûr qu'il fait tout convient le mieux à votre code et à votre niveau d'optimisation.

dim
2017-01-20 14:48:50 UTC
view on stackexchange narkive permalink

Le lien que vous avez fourni explique ce qui se passe sur les ordinateurs classiques, qui chargent tout (y compris le code) en RAM, de toute façon (car c'est la seule chose disponible, mais il y en a beaucoup). Cela ne s'applique pas à la programmation intégrée, où vous disposez également de flash. Donc, si vous utilisez un script d'éditeur de liens approprié pour la programmation intégrée (qui devrait être la valeur par défaut pour les IDE intégrés), les données constantes finissent en fait en flash, comme il se doit.

Maintenant, si vous utilisez des définitions de macro, c'est complètement différent. Les macros sont remplacées dans le code source par le préprocesseur, ce qui signifie que la constante sera recompilée indépendamment chaque fois que vous l'utiliserez dans votre code. Et, si vous l'utilisez plusieurs fois, en effet, le code sera plus gros. Ceci, bien sûr, ne devrait pas être le cas pour les constantes entières simples. Pour les constantes de chaîne, les bons compilateurs essaieront de fusionner plusieurs valeurs identiques pour réduire cet effet et garder une petite taille, mais cela n'est pas garanti et peut dépendre du fait que les chaînes ne sont utilisées que dans la même unité de compilation (fichier source .c) ou à travers plusieurs unités de comilation. Pour les structures / objets constants, les compilateurs ne font généralement pas beaucoup d'optimisation.

Les réponses seraient plus pertinentes pour votre cas spécifique si vous fournissiez des extraits de votre code source et indiquez quel compilateur / IDE vous utilisez.

dannyf
2017-01-20 18:33:51 UTC
view on stackexchange narkive permalink

la réponse dépend de votre définition de "variable constante" et du compilateur utilisé.

s'il s'agit bien d'une "variable constante", la plupart des compilateurs la stockeront comme dans Flash.

s'il est déclaré via une macro, il ne peut pas s'agir d'une variable constante - c'est une constante.il est généralement stocké en flash et copié sur RAM.

Ronan Paixão
2017-01-20 20:58:03 UTC
view on stackexchange narkive permalink

On dirait que vous confondez constantes avec variables . Ceci est particulièrement important si vous utilisez C et non C ++.

En C, ce que vous appelez une variable constante (comme un const int ) sera en fait jeté dans la RAM. C'est ainsi que le compilateur gère la nécessité de référencer parfois l'adresse de la variable (pointeurs).

S'il s'agit d'une variable globale, le compilateur la placera dans la section données initialisées , ce qui signifie que les valeurs vont clignoter dans la section .etext et sont copiées à la section .sdata (partie de .data ) par le script de démarrage . S'il s'agit d'une variable locale, le code de démarrage de la fonction fera cela comme n'importe quelle autre variable.

Cependant, si vous utilisez une macro, la "variable" n'obtient pas d'espace d'adressage. Cela signifie qu'il est chargé comme un immédiat , soit par l'instruction même que vous utilisez (si la valeur est suffisamment petite et que l'instruction prend en charge les immédiats), soit chargé dans un registre juste avant l'instruction qui utilise le valeur. Cela n'utilisera que de l'espace Flash, en supposant que vous exécutez du code à partir de Flash.

D'un autre côté, si vous utilisez C ++, le compilateur utilise la valeur directement depuis Flash pour les optimisations. Cela n'est pas fait en C par conception. Consultez cette réponse pour plus d'informations.

Au fait, c'est en fait ainsi que le Cortex-M3 que j'utilise fait les choses dans GCC.


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 3.0 sous laquelle il est distribué.
Loading...