Go Down

Topic: minimalistic mode for smaller memory (Read 2378 times) previous topic - next topic

AdamOutler

I wrote a simple sketch to be run with the ArduinoTiny project.  The target is an ATTiny2313.   The simple sketch came out to be 4200Bytes. When written in C code, its only 800.  

I'd like to suggest a checkbox that will compile a sketch in minimalistic mode.  

Here is the code which I am talking about.

Code: [Select]
/*
Barnes and Nobel Nook Tablet Mod Chip
Copyright 2011 Adam Outler - hkvc

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
-Adam Outler  adamoutler, gmail.com

*/

boolean Position[3]={true,true,true};//Place holders for operation
int inByte; //current byte
String Message=""; //current string of bytes
//begin sketch

void setup() {
 Serial.begin(115200); //Initialize UART and set baud for serial
 Serial.println("I are your god now");
 }
void loop() {
 if (Serial.available()) {
   inByte = Serial.read();
   if ( inByte == 10 ){
     Message="";
   }
   else {
     Message=Message +(char)inByte; //dump char into string
     if (Message == "OMAP44XX SDP # "){
       if ( Position[1]){
         Serial.println("O hai Nook Im in ur memory");
         Serial.println("mmcinit 0; fatload mmc 0:1 0x81000000 new.flashing_boot.img;");
         Serial.println("Mai kernel is ur kernel");
         Position[1]=(!Position[1]);
         return;

       } else if ( Position[2]){
         Serial.println("Ur Security is my target");
         Serial.println("mw.l 80e84794 e1a00000; mw.l 80e847fc e1a00000; mw.l 80e84808 e1a00000; mw.l 80e847a0 e1a00000;");
         Serial.println("Ur Security is neutralized");
         Position[2]=(!Position[2]);
         return;
       }
       else if ( Position[3]){
         Serial.println("boot mai kernel now");
         Serial.print("booti 0x81000000");
         Serial.println("k thx bai");
         Position[3]=(!Position[3]);
         return;
       }
     }  
   }
 }
 if (millis()>=60000){
   lockup;
 }
}
void lockup(){
 while(true){
   delay(50000);//program cannot end, only sleep
 }
}


The basic gist of this program is to monitor for a string, then respond with one of 3 strings.  I added some extra stuff into it as well.    

The problem is that this compiles over 4K and it does not need to be more than 1K.  Here's a similar program written in all C.

Code: [Select]
#include <avr/io.h>
#include <avr/pgmspace.h>

// Use a 3.6864MHz clock
#define F_CPU   3686400UL
#define BAUD   115200UL

// Must be loaded after defines above
#include <util/setbaud.h>

// These strings won't fit in RAM
char LOADMMC[] PROGMEM = "mmcinit 0; fatload mmc 0:1 0x81000000 new.flashing_boot.img;";
char OPCODES[] PROGMEM = "mw.l 80e84794 e1a00000; mw.l 80e847fc e1a00000; mw.l 80e84808 e1a00000; mw.l 80e847a0 e1a00000;";
char BOOTCMD[] PROGMEM = "booti 0x81000000";

void uart_putchar(char c) {
  // Wait until transmitter ready
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;
}

void uart_puts_progmem(char *s) {
  char b;
  // While the byte read from flash isn't a null byte, keep sending
  while ('\0' != (b = pgm_read_byte(s++))) {
     uart_putchar(b);
  }
}

void init_uart() {
  // Set baud rate using setbaud macros
  UBRRH = UBRRH_VALUE;
  UBRRL = UBRRL_VALUE;
  #if USE_2X
  UCSRA |= _BV(U2X);
  #else
  UCSRA &= ~_BV(U2X);
  #endif
 
  // Enable receiver/transmitter
  UCSRB = _BV(RXEN) | _BV(TXEN);
 
  // TxD pin PD1 set to output
  DDRD |= _BV(PD1);
  // RxD pin PD0 set to input
  DDRD &= ~_BV(PD0);
}

void send_string(int i) {
  switch (i) {
     case 0:
        uart_puts_progmem(BOOTCMD);
        break;
     case 1:
        uart_puts_progmem(OPCODES);
        break;
     case 2:
        uart_puts_progmem(LOADMMC);

        // Disable interrupts and put the micro to sleep - it will never wake up ( :( )
        asm("CLI");
        MCUCR |= _BV(SM1) | _BV(SM0) | _BV(SE);
        asm("SLEEP");
        break;
  }
}

int main(void)
{
  char c;
  int state, i;
 
  // Turn off peripherals we aren't using
  PRR |= _BV(PRTIM1) | _BV(PRTIM0) | _BV(PRUSI);

  init_uart();
 
   while(1)
   {
     // Use a state machine to detect the prompt
       if (UCSRA & _BV(RXC)) {
        c = UDR;
        switch (state) {
           case 0:
              if (c == 'S') state++;
              break;
           case 1:
              if (c == 'D') state++;
              else state = 0;
              break;
           case 2:
              if (c == 'P') state++;
              else state = 0;
              break;
           case 3:
              if (c == ' ') state++;
              else state = 0;
              break;
           case 4:
              if (c == '#') state++;
              else state = 0;
              break;
           case 5:
              if (c == ' ') send_string(i++);
              state = 0;
              break;
        }
     }
   }
}


It seems to me that size would be a concern when prototyping.  

Thanks for reading and considering this proposal for a minimalistic compilation option.

PaulS

Quote
I wrote a simple sketch to be run with the ArduinoTiny project.  The target is an ATTiny2313.   The simple sketch came out to be 4200Bytes. When written in C code, its only 800. 

I'd like to suggest a checkbox that will compile a sketch in minimalistic mode.

That would preclude this:
Code: [Select]
String Message=""; //current string of bytes
No wonder the sketch was smaller in C.
The art of getting good answers lies in asking good questions.

AdamOutler

What are you pointing out there?

I didn't bother troubleshooting past removing all lines of code. serial.begin makes the sketch take up around 1K of the available memory.   It does not seem like it should be that large.  UART is a very simple protocol.

PaulS

Quote
What are you pointing out there?

That you are comparing apples and water buffaloes. The String class is horribly inefficient, compared to char arrays.

Quote
I didn't bother troubleshooting past removing all lines of code. serial.begin makes the sketch take up around 1K of the available memory.

Flash or SRAM?

Quote
UART is a very simple protocol.

Sure. But there are input and output buffers, and interrupts to minimize the impact of the input and output of data on the rest of the sketch. They take up SRAM memory.

The art of getting good answers lies in asking good questions.

mromani


What are you pointing out there?

I didn't bother troubleshooting past removing all lines of code. serial.begin makes the sketch take up around 1K of the available memory.   It does not seem like it should be that large.  UART is a very simple protocol.


Using Arduino APIs is more about convenience than code size. Don't forget the primary audience of the arduino platform.
This doesn't mean the devs should carelessly produce bloated code, nor that the current core libs are unimprovable, but saying "it doesn't seem like it should be that large" is like implying they're putting useless fancy routines into Serial for no reason. Instead of accusing the Arduino team of being incompetent, you should probably take a look at the source code of Serial and discuss here how it could be improved.


Quote
UART is a very simple protocol.


I thought UART was a device, not a protocol.

http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter

mromani

Ok that was enough for a useless polemical comment :-)


Back IT, I think there can be no "minimalistic" mode. How can a compiler or even a more complex piece of software convert the first of the two examples you wrote into the second ?

One could probably identify some convenience functions that Arduino core classes provide and that can be selectively "turned off" to save space if one is willing to loose some functionality or ease of use (IIRC there is a recurring argument like this one about digitalWrite vs. direct port manipulation). Provided this makes sense, it can probably be implemented via conditional compilation (#ifdefs in the libraries, #defines in the sketch).

Go Up