Como realmente encolher um esboço

9

Quero fazer um esboço o menor possível, para fins de teste. O problema é que, quando compilo o esboço BareMinimum (com uma configuração e um loop vazios), recebo 466 bytes para o Uno e 4.242 para o Leonardo. Existe alguma maneira de escrever seu próprio código que não possui funções extras (ou seja, Timer0 para millis()e delay()). Eu também gostaria de poder desativar as funções de teclado / mouse para o Leonardo.

O médico
fonte
4
Isso não deveria ser marcado como leonardo e não uno (e focar em uma placa)? Estas são perguntas separadas.
asheeshr
Estou apenas apontando que um espaço em branco compilado esboço é grande para um monte de placas, especialmente os baseados em USB nativas
TheDoctor
Eu também gostaria de poder desativar as funções de teclado / mouse para o Leonardo. é a segunda pergunta.
asheeshr

Respostas:

3

Você deve poder criar sua própria definição de placa com um arquivo boards.txt personalizado, conforme https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . A meu ver, existem vários recursos USB na definição de Leonardo. Eu espero que a inclusão de compilação do 4K seja baseada nesses sinalizadores e não no tipo de processador.

Onde o boards.txt usaria o upload, as seções do carregador de inicialização do Leonardo e a compilação do uno.

Isso tudo pressupõe que a compilação da biblioteca principal não use sinalizadores específicos do processador para incluir funções USB.

Se você conseguir esse trabalho. postar de volta, tenho certeza que outros estariam interessados ​​em tal.


Recentemente, deparei com essa limitação usada em 4K em uma demonstração da biblioteca que chegou ao máximo da ONU e teve que colocar um

#if !defined(__AVR_ATmega32U4__)
...

em torno de um grande pedaço de recursos extras no esboço para caber no Leonardo.

Eu tinha assumido (errado) que esse 4K era porque eu ainda incluía o Serial.print, que quando estava sobre o CDC do USB no Leo. Mas vejo que, depois de um despejo de memória de um esboço vazio, eles ainda estão lá.

C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst

O que faz sentido. Como o Leonardo ainda exige que o cliente USB-CDC (o 4K) detecte a conexão de 1200 Baud do AVR-DUDE para acionar a reinicialização remota.


Portanto, criar um boards.txt personalizado sem USB na compilação também precisa ter

leonardo.upload.use_1200bps_touch=true

removido.

Uma vez carregado no destino, isso exigiria que o upload fosse sincronizado com uma redefinição manual do destino. Como a capacidade de reinicialização remota é perdida.

mpflaga
fonte
atualizado sobre o motivo pelo qual o 4K ainda é compilado, mesmo que o Serial.print seja omitido.
mpflaga
3

Recentemente, eu queria fazer exatamente isso. Como não há uma maneira legal de fazer isso, acabei escrevendo um patch para o plug-in Stino Arduino de texto sublime para fazer exatamente isso. Ele foi aceito posteriormente e, portanto, deve estar em qualquer instalação atualizada do Stino.

Isso adiciona uma nova opção ao Stino:

insira a descrição da imagem aqui

O uso desse modo produz resultados de compilação como os seguintes:

Para uma Uno:

Tamanho do esboço binário: 172 bytes (máximo de 32256 bytes, 0,53 por cento).
Uso estimado da memória: 0 bytes (máximo de 1024 bytes, 0,00%).

Para um leonardo

Tamanho do esboço binário: 240 bytes (máximo de 28672 bytes, 0,84 por cento).
Uso estimado da memória: 0 bytes (máximo de 2560 bytes, 0,00%).

Programar realmente o leonardo com a saída compilada acima provavelmente é uma má idéia, pois pode interromper a funcionalidade de redefinição automática, mas você poderia , se quiser. Gorjeta para mpflaga por notar isso em sua resposta.

Observe que os relatórios de memória estão realmente incorretos, mas esse é um problema separado .

O código usado para o acima é:

int main()
{
    while (1)
    {

    }
}

Algumas notas:

  • Você não está escrevendo um "esboço" mais, não que você nunca realmente não escrever um esboço. Você escreve programas . Período. Não me importo com o que os wackos do Arduino querem dizer, eles não conseguem redefinir os termos.
  • Todo o gerenciamento de interrupções é manual. Isso significa não milis()ou similar.
  • Você ainda pode usar as bibliotecas seriais do arduino e assim por diante, se desejar. Você precisa #include <Arduino.h>.
  • Você define main. Você nunca volta de main. Se você quiser coisas de configuração, isso será anterior ao while (1).
Connor Wolf
fonte
@jfpoilpret Você chama isso de IDE? Mais como bloco de notas com macros ...
Ron
@ Ron-E Eu não chamo isso de IDE, o IDE do Arduino é o seu nome, então apenas o usei, mesmo que não valha esse nome.
Jfpoilpret
2
@FakeName Linguagem incorreta não é permitida nos sites Stack Exchange (consulte: stackoverflow.com/help/behavior ). Eu o editei neste caso, mas tente evitar o uso de palavrões neste site no futuro. Obrigado.
Peter Bloomfield
2

Embora dependa do seu esboço, você pode diminuir um pouco o tamanho reutilizando o código com os métodos.

Pegue este código:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  val = digitalRead(10);
}

1.322 bytes no Arduino Uno. Agora vamos diminuir um pouco:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  for(uint8_t i = 0; i < 8; i++) {
    blink(HIGH);
    blink(LOW);
  }    
  val = digitalRead(10);
}

void blink(uint8_t state) {
  digitalWrite(led, state);   // turn the LED to the right state
  delay(1000);                // wait for a second
}

1.194 bytes. Isso representa uma queda de 10%!

De qualquer forma, apesar de não encolher muito um rascunho, às vezes pode ser a rota mais fácil quando você está com dois bytes acima do limite ou apenas deseja criar um rascunho mais compacto para começar, sem perder nenhuma funcionalidade. Não é para todas as situações, mas às vezes acho útil.

Pinguim anônimo
fonte
Geralmente, se você colocar o código em funções, o compilador fará o trabalho duro e fará o resto certo para você.
Cybergibbons
@ Cyybibbons Você pode definir isso [para usuários que não estão familiarizados com isso]?
Anonymous Penguin
3
Se você dividir o código em uma função e ela não for eficiente, geralmente o compilador o alinhará para você. No entanto, um compilador nunca dividirá o código em funções. Portanto, é quase sempre melhor escrever mais funções.
Cybergibbons
11
Além disso, colocar o código em funções torna muito mais fácil de ler e entender
Usando o acesso direto à porta, o tamanho é reduzido para 646 bytes. Usando apenas avr-libc (sem núcleo Arduino), ele reduz os 220 bytes.
Edgar Bonet
0

@annonomus pinguim, com certeza podemos Embora o código seja compilado em 1180 bytes de flash + 13 bytes de RAM para uma unidade no meu computador, podemos aprimorá-la :) para que o desafio do golfe seja aceito e também algumas dicas úteis, pois estamos no negócio de Aprendendo.

Etapa 1: diminuir os requisitos variáveis. Usar um int para uma porta led parece um pouco exagerado, certamente não temos 65535 portas de E / S endereçáveis ​​no arduino :) Portanto, alteramos para um byte apenas para diversão. Mudaremos para um #define mais tarde, mas para mostrar o impacto do uso de tipos de variáveis ​​muito grandes.

byte led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Compila em 1172 bytes + 13 bytes de RAM. Isso economiza 8 bytes de flash devido a menos operações necessárias para o byte, em vez de um número inteiro. Eu esperaria 12 bytes de ram, mas tudo bem. Não muito, mas cada byte salvo é bom.

Etapa 2: alterar a variável para define quando faz sentido. Por exemplo, o byte liderado não é necessário, o pino não será dessoldado.

#define LED 13
int val;

void setup() {                
  pinMode(LED, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Compila em 1142 bytesflash + 11 bytes de ram. Já 38 bytes salvos. Isso ocorre devido a menos operações de registro necessárias para buscar o valor int. Também salvamos 2 bytes da RAM. (ainda me perguntando por que o byte não foi compilado em menos 1 byte de ram .....)

Etapa 3: otimizar o código. Eu vejo dois atrasos. Gostaria de saber se eu alterá-lo para 1 atraso economizaria espaço, mas eu tenho que descobrir o valor do pino de LED e alternar (inverter). Podemos fazer isso com digitalRead (), mas isso economizará espaço?

#define LED 13
int val;
void setup() {                
  pinMode(LED, OUTPUT);     
}
void loop() {
  blink();
  val = digitalRead(10);
}
void blink() {
  digitalWrite(LED, !digitalRead(LED));   // toggle the led based on read value
  delay(1000);               // wait for a second and spare yourself the other delay
}

Compila em 1134 bytes + 11 bytes de RAM. Yay! outros 8 bytes. Isso totaliza 46 bytes e menos 2 linhas de código.

Também outra dica geral sobre como diminuir o tamanho do código. Não use a classe String. É ENORME, aprenda a lidar com matrizes de caracteres, strcpy (), strcmp (). Se tudo o que você tem são algumas operações básicas de string, o uso da classe String está apenas desperdiçando espaço no flash e na RAM.

Patrick Deelman
fonte