Pages: [1]   Go Down
Author Topic: PROGMEM confusion  (Read 691 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 163
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was just running a wee little test on PROGMEM and I'm a little bit surprised at the results.

Code:

#include <avr/pgmspace.h>

void loop()
{
}

void setup()
{
   Serial.begin(9600);
   //prog_char PROGMEM myStr[] = {"This is how much memory I have left: "};
   //Serial.print(myStr);
   Serial.print( "This is how much memory I have left: " );
   Serial.println( availableMemory() );
}

int availableMemory() {
 int size = 1024;
 byte *buf;
 while ((buf = (byte *) malloc(--size)) == NULL);
 free(buf);
 return size;
}


The code above reports 875 bytes free. However if I comment out the Serial.print() call which has the literal string and uncomment the PROGMEM string and corresponding Serial.print() call I am seeing 837 bytes free.

Does anyone have any insight into this?
Logged

Connecticut, US
Offline Offline
Edison Member
*
Karma: 2
Posts: 1036
Whatduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Read through this:  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1231801806

Short answer:  calling malloc() is not a robust way of measuring available heap space.  There is an overhead to a heap allocator that is not accounted for in this sketch, and the overhead is hard to quantify in bigger sketches.
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

fjornir--

I have been working a lot with PROGMEM recently, and your problem stems from the fact that your syntax is not quite correct.  If your string were really stored in flash memory, you couldn't use Serial.print() to print it.  The fact that Serial.print() works for your example is a clue that the declaration of myStr is not actually placing the string in flash.  Adding "static const" fixes the problem.  Try this example:

Code:
void printStr(const prog_char *p)
{
  while (1)
  {
    char c = pgm_read_byte(p++);
    if (!c) break;
    Serial.print(c);
  }
}

void setup()
{
   Serial.begin(9600);
   static const char PROGMEM myStr[] = "This is how much memory I have left: ";
   printStr(myStr);
   //Serial.print( "This is how much memory I have left: " );
   Serial.println( availableMemory() );
}

Mikal
« Last Edit: January 26, 2009, 02:22:25 pm by mikalhart » Logged

SF Bay Area
Offline Offline
Edison Member
*
Karma: 11
Posts: 1244
Arduino Ninja
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Part of the fix (half of the memory recovery) in mikalhart's code is that he's reading the data out of flash one byte at a time. If you store data in flash and then eventually put the entire string into a print command, then that much memory has to be reserved. If you have a lot of strings to store in flash, then that's still a significant memory savings...if you only have one string, then mikalhart's bytewise method saves the most RAM.
Logged

Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@macegr--

Can you help me understand your comment a little better?  It sounds like you are saying the bytewise reading trick is effective for one flash string, but not so much for lots?

Mikal
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 163
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mikalhart - Got it. Thanks!
Logged

SF Bay Area
Offline Offline
Edison Member
*
Karma: 11
Posts: 1244
Arduino Ninja
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

mikalhart: I'm saying that if you have a lot of strings, not bothering to deal with things bytewise is still a significant RAM savings.
Logged

Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

Pages: [1]   Go Up
Jump to: