Quand je compile ce croquis pour le Yún:
int led = 7;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH);
}
Je reçois:
Sketch utilise 5 098 octets (17%) d'espace de stockage de programme.
Le maximum est de 28 672 octets. Les variables globales utilisent 153 octets (5%) de mémoire dynamique, laissant 2407 octets pour les variables locales. Le maximum est de 2 560 octets.
Même lorsque je compile l'esquisse BareMinimum:
void setup() {
// setup
}
void loop() {
// loop
}
Je reçois:
Sketch utilise 4 548 octets (15%) d'espace de stockage de programme.
Le maximum est de 28 672 octets. Les variables globales utilisent 151 octets (5%) de mémoire dynamique, laissant 2409 octets pour les variables locales. Le maximum est de 2 560 octets.
Pourquoi une simple esquisse occupe-t-elle 15% de l'espace de stockage de programme alloué? Et pourquoi un croquis très simple occupe-t-il 17% de l'espace de stockage du programme? Selon le site Arduino :
Il est facile de tout utiliser en ayant beaucoup de chaînes dans votre programme. Par exemple, une déclaration comme:
char message[] = "I support the Cape Wind project.";
met 33 octets dans SRAM (chaque caractère prend un octet, plus le terminateur '\ 0').
Cependant, aucune chaîne n'est déclarée dans aucune de ces esquisses.
Il semble qu'ils pourraient importer ou utiliser d'autres bibliothèques / classes que je ne spécifie pas. Peut-être qu'il importe une bibliothèque par défaut du système? Ou s'agit-il d'autre chose?
la source
Vous avez déjà de très bonnes réponses. Je poste ceci uniquement pour partager certaines statistiques que j'ai faites un jour, je me suis posé le même genre de questions: qu'est-ce qui prend autant de place sur un croquis minimal? Quel est le minimum requis pour obtenir la même fonctionnalité?
Vous trouverez ci-dessous trois versions d'un programme minimal clignotant qui fait basculer la LED sur la broche 13 chaque seconde. Les trois versions ont été compilées pour un Uno (pas d'USB impliqué) en utilisant avr-gcc 4.8.2, avr-libc 1.8.0 et arduino-core 1.0.5 (je n'utilise pas l'IDE Arduino).
Tout d'abord, la méthode Arduino standard:
Cela compile à 1018 octets. En utilisant les deux
avr-nm
et le démontage , j'ai décomposé cette taille en fonctions individuelles. Du plus grand au plus petit:Dans la liste ci-dessus, la première colonne est la taille en octets, et la deuxième colonne indique si le code provient de la bibliothèque principale Arduino (A, 822 octets au total), du runtime C (C, 148 octets) ou de l'utilisateur (U , 48 octets).
Comme on peut le voir dans cette liste, la fonction la plus importante est la routine d'entretien de l'interruption de débordement du temporisateur 0. Cette routine est responsable du suivi du temps, et il est nécessaire par
millis()
,micros()
etdelay()
. La deuxième plus grande fonction estinit()
, qui définit les temporisations matérielles pour PWM, active l'interruption TIMER0_OVF et déconnecte l'USART (qui a été utilisé par le chargeur de démarrage). Cette fonction et la fonction précédente sont définies dans<Arduino directory>/hardware/arduino/cores/arduino/wiring.c
.Vient ensuite la version C + avr-libc:
La répartition des tailles individuelles:
Cela représente 132 octets pour le runtime C et 26 octets de code utilisateur, y compris la fonction intégrée
_delay_ms()
.Il peut être noté que, puisque ce programme n'utilise pas d'interruptions, la table des vecteurs d'interruption n'est pas nécessaire, et un code utilisateur régulier pourrait être mis à sa place. La version d'assemblage suivante fait exactement cela:
Celui-ci est assemblé (avec
avr-gcc -nostdlib
) en seulement 14 octets, dont la plupart sont utilisés pour retarder les basculements afin que le clignotement soit visible. Si vous supprimez cette boucle de retard, vous vous retrouvez avec un programme de 6 octets qui clignote trop vite pour être vu (à 2 MHz):la source
J'ai écrit un article sur Pourquoi faut-il 1000 octets pour clignoter une LED? .
La réponse brève est: "Il ne faut pas 2000 octets pour faire clignoter deux LED!"
La réponse la plus longue est que les bibliothèques Arduino standard (que vous n'avez pas besoin d'utiliser si vous ne le souhaitez pas) ont de belles fonctionnalités pour vous simplifier la vie. Par exemple, vous pouvez adresser les broches par numéro lors de l'exécution, où la bibliothèque convertit (disons) la broche 8 en un port et un numéro de bit corrects. Si vous codez en dur l'accès au port, vous pouvez économiser cette surcharge.
Même si vous ne les utilisez pas, les bibliothèques standard incluent du code pour compter les "ticks" afin que vous puissiez trouver le "temps" actuel (en appelant
millis()
). Pour ce faire, il doit ajouter la surcharge de certaines routines de service d'interruption.Si vous simplifiez (sur l'Arduino Uno) à cette esquisse, vous réduisez l'utilisation de la mémoire du programme à 178 octets (sur IDE 1.0.6):
OK, 178 octets, ce n'est pas tant que ça, et les 104 premiers octets sont les vecteurs d'interruption matérielle (4 octets chacun, pour 26 vecteurs).
Donc, sans doute, il ne faut que 74 octets pour faire clignoter une LED. Et de ces 74 octets, la plupart sont vraiment le code généré par le compilateur pour initialiser la mémoire globale. Si vous ajoutez suffisamment de code pour faire clignoter deux LED:
Ensuite, la taille du code augmente à 186 octets. Par conséquent, vous pourriez faire valoir qu'il ne faut que des
186 - 178 = 8
octets pour faire clignoter une LED.Donc, 8 octets pour faire clignoter une LED. Cela me semble assez efficace.
Au cas où vous seriez tenté d'essayer cela à la maison, je dois souligner que bien que le code affiché ci-dessus clignote deux LED, il le fait très rapidement. En fait, ils clignotent à 2 MHz - voir capture d'écran. Le canal 1 (jaune) est la broche 12, le canal 2 (cyan) est la broche 13.
Comme vous pouvez le voir, les broches de sortie ont une onde carrée avec une fréquence de 2 MHz. La broche 13 change d'état 62,5 ns (un cycle d'horloge) avant la broche 12, en raison de l'ordre de basculement des broches dans le code.
Donc, à moins d'avoir des yeux bien meilleurs que les miens, vous ne verrez aucun effet clignotant.
Comme extra amusant, vous pouvez réellement basculer deux broches dans la même quantité d'espace de programme que basculer une broche.
Cela se compile en 178 octets.
Cela vous donne une fréquence plus élevée:
Nous sommes maintenant à 2,66 MHz.
la source
init()
(comme d'habitudemain()
), le fichier câblage.c (qui s'y trouveinit
) n'était pas lié. Par conséquent, le traitement des gestionnaires d'interruption (pourmillis()
,micros()
etc.) a été omis. Il n'est probablement pas particulièrement pratique de l'omettre, sauf si vous n'avez jamais besoin de chronométrer les choses, mais le fait est que l'esquisse grandit en fonction de ce que vous y mettez. Par exemple, si vous utilisez Serial, la mémoire du programme et la RAM prennent un coup.