My Teensy 2.0 project is running low on RAM.
The project contains many arrays of const objects.
And there is more than enough flash on Teensy 2.0 to use PROGMEM.
The following example sketch compiles in Arduino 1.6.5-r5 with C++11, and runs on Teensy 2.0
(How I added C++11 to Arduino for Teensy 2.0 is explained in: https://forum.pjrc.com/threads/30474-User-Name )
When USE_PROGMEM is defined, the sketch compiles with the objects in PROGMEM.
The sketch was compiled and run twice; once with PROGMEM, and once without PROGMEM.
Using PROGMEM saves 24 bytes of RAM, which seems about right.
But the const PROGMEM objects prints the wrong values.
The example sketch:
Using PROGMEM, the objects output the wrong values:
Not using PROGMEM, the objects output the correct values:
I tried putting the object in arrays, but the problem was not with the array.
The problem was with getting the objects to work in PROGMEM.
I am using Teensy 2.0 because the PCB for the project was already done for Teensy 2.0 before Teensy LC came out.
The project doesn't use strings, so the F("string") macro wouldn't help.
How to to use class objects in PROGMEM?
Compiler verbose output when USE_PROGMEM is defined:
The project contains many arrays of const objects.
And there is more than enough flash on Teensy 2.0 to use PROGMEM.
The following example sketch compiles in Arduino 1.6.5-r5 with C++11, and runs on Teensy 2.0
(How I added C++11 to Arduino for Teensy 2.0 is explained in: https://forum.pjrc.com/threads/30474-User-Name )
When USE_PROGMEM is defined, the sketch compiles with the objects in PROGMEM.
The sketch was compiled and run twice; once with PROGMEM, and once without PROGMEM.
Using PROGMEM saves 24 bytes of RAM, which seems about right.
But the const PROGMEM objects prints the wrong values.
The example sketch:
Code:
//comment or uncomment the #define to toggle PROGMEM
#define USE_PROGMEM
// return amount of free RAM, code copied from http://web-engineering.info/node/30
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;
//compute and return amount of free RAM
uint16_t getFreeRAM()
{
uint8_t newVariable;
// if heap is empty, use bss as start memory address
if ((uint16_t)__brkval == 0)
{
return (((uint16_t)&newVariable) - ((uint16_t)&__bss_end));
}
// else use heap end as the start of the memory address
else
{
return (((uint16_t)&newVariable) - ((uint16_t)__brkval));
}
};
class Num
{
private:
const uint16_t num;
public:
//"constexpr" to evaluate the value at compile time
constexpr Num( const uint16_t n ) : num(n) {}
void print() const
{
Keyboard.print("num=");
Keyboard.println( num );
}
};
#ifdef USE_PROGMEM
const PROGMEM Num n_1(1);
const PROGMEM Num n_2(2);
const PROGMEM Num n_3(3);
const PROGMEM Num n_4(4);
const PROGMEM Num n_5(5);
#else
const Num n_1(1);
const Num n_2(2);
const Num n_3(3);
const Num n_4(4);
const Num n_5(5);
#endif
void setup()
{
Keyboard.begin();
delay(1000);
//print heading
#ifdef USE_PROGMEM
Keyboard.println("\nUsing PROGMEM");
#else
Keyboard.println("\nNot using PROGMEM");
#endif
Keyboard.print("Free RAM = ");
Keyboard.println( getFreeRAM() );
//print the object values
n_1.print();
n_2.print();
n_3.print();
n_4.print();
n_5.print();
}
void loop() {}
Using PROGMEM, the objects output the wrong values:
Code:
Using PROGMEM
Free RAM = 2467
num=0
num=0
num=0
num=0
num=0
Not using PROGMEM, the objects output the correct values:
Code:
Not using PROGMEM
Free RAM = 2453
num=1
num=2
num=3
num=4
num=5
I tried putting the object in arrays, but the problem was not with the array.
The problem was with getting the objects to work in PROGMEM.
I am using Teensy 2.0 because the PCB for the project was already done for Teensy 2.0 before Teensy LC came out.
The project doesn't use strings, so the F("string") macro wouldn't help.
How to to use class objects in PROGMEM?
Compiler verbose output when USE_PROGMEM is defined:
Code:
/opt/arduino-1.6.5-r5/hardware/tools/avr/bin/avr-g++ -c -Os -g -Wall -ffunction-sections -fdata-sections -MMD -fno-exceptions -felide-constructors -std=c++11 -mmcu=atmega32u4 -DTEENSYDUINO=125 -DARDUINO=10605 -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DUSB_HID -DLAYOUT_US_ENGLISH -I/opt/arduino-1.6.5-r5/hardware/teensy/avr/cores/teensy /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp -o /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/malloc.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/pins_teensy.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/keylayouts.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/usb.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/wiring.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/WInterrupts.c.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/Stream.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/usb_api.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/IPAddress.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/new.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/HardwareSerial.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/WMath.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/Print.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/Tone.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/WString.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/yield.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/main.cpp.o
Using previously compiled file: /tmp/build7492478963666243005.tmp/core.a
/opt/arduino-1.6.5-r5/hardware/tools/avr/bin/avr-gcc -Os -Wl,--gc-sections,--relax -mmcu=atmega32u4 -o /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.elf /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.o /tmp/build7492478963666243005.tmp/core.a -L/tmp/build7492478963666243005.tmp -lm
/opt/arduino-1.6.5-r5/hardware/tools/avr/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.elf /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.eep
/opt/arduino-1.6.5-r5/hardware/tools/avr/bin/avr-objcopy -O ihex -R .eeprom /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.elf /tmp/build7492478963666243005.tmp/PROGMEM_objects.cpp.hex
/opt/arduino-1.6.5-r5/hardware/tools/teensy_post_compile -file=PROGMEM_objects.cpp -path=/tmp/build7492478963666243005.tmp -tools=/opt/arduino-1.6.5-r5/hardware/tools -board=TEENSY2
Sketch uses 4,218 bytes (13%) of program storage space. Maximum is 32,256 bytes.
Global variables use 113 bytes (4%) of dynamic memory, leaving 2,447 bytes for local variables. Maximum is 2,560 bytes.
Last edited: