Quando eu compilar esse esboço para o Yún:
int led = 7;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH);
}
Eu recebo:
O Sketch usa 5.098 bytes (17%) do espaço de armazenamento do programa.
O máximo é 28.672 bytes. As variáveis globais usam 153 bytes (5%) de memória dinâmica, deixando 2.407 bytes para variáveis locais. O máximo é de 2.560 bytes.
Mesmo quando eu compilo o esboço BareMinimum:
void setup() {
// setup
}
void loop() {
// loop
}
Eu recebo:
O Sketch usa 4.548 bytes (15%) do espaço de armazenamento do programa.
O máximo é 28.672 bytes. As variáveis globais usam 151 bytes (5%) de memória dinâmica, deixando 2.409 bytes para variáveis locais. O máximo é de 2.560 bytes.
Por que um esboço mínimo desencapado ocupa 15% do espaço de armazenamento do programa alocado? E por que um esboço muito simples ocupa 17% do espaço de armazenamento do programa? De acordo com o site do Arduino :
É fácil usar tudo isso, tendo muitas strings no seu programa. Por exemplo, uma declaração como:
char message[] = "I support the Cape Wind project.";
coloca 33 bytes na SRAM (cada caractere recebe um byte, mais o terminador '\ 0').
No entanto, não há nenhuma sequência declarada em nenhum desses esboços.
Parece que eles podem importar ou usar outras bibliotecas / classes que não especifico. Talvez ele importe uma biblioteca padrão do sistema? Ou é outra coisa?
fonte
Você já tem respostas perfeitamente boas. Estou postando isso apenas para compartilhar algumas estatísticas que fiz um dia e me fiz o mesmo tipo de pergunta: O que está ocupando tanto espaço em um esboço mínimo? Qual é o mínimo necessário para alcançar a mesma funcionalidade?
Abaixo estão três versões de um programa intermitente mínimo que alterna o LED no pino 13 a cada segundo. Todas as três versões foram compiladas para um Uno (sem USB envolvido) usando o avr-gcc 4.8.2, avr-libc 1.8.0 e o arduino-core 1.0.5 (não uso o IDE do Arduino).
Primeiro, a maneira padrão do Arduino:
Isso compila para 1018 bytes. Usando ambos
avr-nm
e desmontagem , eu dividi esse tamanho em funções individuais. Do maior para o menor:Na lista acima, a primeira coluna é o tamanho em bytes, e a segunda coluna informa se o código é proveniente da biblioteca principal do Arduino (A, 822 bytes no total), do tempo de execução C (C, 148 bytes) ou do usuário (U , 48 bytes).
Como pode ser visto nesta lista, a maior função é a rotina de manutenção da interrupção de estouro do timer 0. Essa rotina é responsável pelo rastreamento do tempo e é necessária por
millis()
,micros()
edelay()
. A segunda maior função éinit()
, que define os temporizadores de hardware para o PWM, permite a interrupção do TIMER0_OVF e desconecta o USART (que foi usado pelo carregador de inicialização). Tanto esta como a função anterior são definidas em<Arduino directory>/hardware/arduino/cores/arduino/wiring.c
.A seguir está a versão C + avr-libc:
A discriminação dos tamanhos individuais:
São 132 bytes para o tempo de execução C e 26 bytes de código do usuário, incluindo a função embutida
_delay_ms()
.Pode-se observar que, como esse programa não usa interrupções, a tabela de vetores de interrupção não é necessária e o código do usuário comum pode ser colocado em seu lugar. A seguinte versão do assembly faz exatamente isso:
Isso é montado (com
avr-gcc -nostdlib
) em apenas 14 bytes, a maioria dos quais é usada para atrasar as alternâncias para que o piscar fique visível. Se você remover esse loop de atraso, você terminará com um programa de 6 bytes que pisca rápido demais para ser visto (a 2 MHz):fonte
Eu escrevi um post sobre Por que são necessários 1000 bytes para piscar um LED? .
A resposta breve é: "Não são necessários 2000 bytes para piscar dois LEDs!"
A resposta mais longa é que as bibliotecas padrão do Arduino (que você não precisa usar se não quiser) têm algumas funcionalidades agradáveis para simplificar sua vida. Por exemplo, você pode endereçar pinos por número no tempo de execução, onde a biblioteca converte (digamos) o pino 8 na porta e no número de bits corretos. Se você codificar o acesso à porta, poderá salvar essa sobrecarga.
Mesmo que você não as use, as bibliotecas padrão incluem código para contar "ticks" para que você possa descobrir a "hora" atual (ligando
millis()
). Para fazer isso, é necessário adicionar a sobrecarga de algumas rotinas de serviço de interrupção.Se você simplificar (no Arduino Uno) este esboço, o uso da memória do programa é reduzido para 178 bytes (no IDE 1.0.6):
OK, 178 bytes não são muito, e dos primeiros 104 bytes são os vetores de interrupção de hardware (4 bytes cada, para 26 vetores).
Então, sem dúvida, existem apenas 74 bytes necessários para piscar um LED. E desses 74 bytes, a maioria é realmente o código gerado pelo compilador para inicializar a memória global. Se você adicionar código suficiente para piscar dois LEDs:
Em seguida, o tamanho do código aumenta para 186 bytes. Portanto, você pode argumentar que são necessários apenas
186 - 178 = 8
bytes para piscar um LED.Então, 8 bytes para piscar um LED. Parece bastante eficiente para mim.
Caso você esteja tentado a fazer isso em casa, devo salientar que, embora o código postado acima pisque dois LEDs, ele o faz muito rapidamente. De fato, eles piscam a 2 MHz - veja a captura de tela. O canal 1 (amarelo) é o pino 12, o canal 2 (ciano) é o pino 13.
Como você pode ver, os pinos de saída têm uma onda quadrada com uma frequência de 2 MHz. O pino 13 muda de estado 62,5 ns (um ciclo de relógio) antes do pino 12, devido à ordem de alternância dos pinos no código.
Portanto, a menos que você tenha olhos muito melhores que os meus, não verá nenhum efeito piscante.
Como um extra divertido, você pode realmente alternar dois pinos na mesma quantidade de espaço do programa que alternar um.
Isso é compilado em 178 bytes.
Isso fornece uma frequência mais alta:
Agora estamos com 2,66 MHz.
fonte
init()
(como o normal,main()
faz), então o wiring.c arquivo (que teminit
nele) não estava ligada. Como resultado, o processamento para os manipuladores de interrupção (paramillis()
,micros()
etc.) foi omitido. Provavelmente não é particularmente prático omití-lo, a menos que você nunca precise cronometrar as coisas, mas o fato é que o esboço cresce em tamanho dependendo do que você coloca nele. Por exemplo, se você usar Serial, a memória do programa e a RAM serão afetadas.