PROGMEM problem

Hi,

I’m having issues with PROGMEM.
Does a PROGMEM array have a limit in size?

Here is my code, which fails to execute and keeps rebooting my unit.
I had to shorten the array because it exceed the max length allowed per post.
The array is 24095 in size

#include <avr/pgmspace.h>


const prog_uchar logo[] PROGMEM = {
0xDA, 0x36, 0x05, 0x02, 0x0, 
.
.
.
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

void setup()
{
  Serial.begin(57600);
  MemPrint(logo);
}

void loop()
{
}

void MemPrint(const prog_uchar *iPtr)
{
	Serial.println(pgm_read_byte_near(iPtr),DEC);
}

newhobby:
Does a PROGMEM array have a limit in size?

Of course. The size of program memory. Taking into account that your program (sketch) will use some of that.

This slightly adapted version (since I don’t have all your data) runs without rebooting:

#include <avr/pgmspace.h>

const prog_uchar logo[24095] PROGMEM = {
0xDA, 0x36, 0x05, 0x02, 0x0};

void setup()
{
  Serial.begin(115200);
  Serial.println ("beginning.");
  MemPrint(logo);
}

void loop() {}

void MemPrint(const prog_uchar *iPtr)
{
	Serial.println(pgm_read_byte_near(iPtr),DEC);
}

It prints:

beginning.
218

… which is correct.

Well, 24095 + whatever I have on the code doesn't go above the flash memory size. Besides, I'm using Mega2560. It runs just fine when I reduce the size of the PROGMEM array, but it doesn't run after a certain size, which I didn't try to find out yet. So, yes... The code you posted works for me too. Try increasing the size of the array.

@Nick If you store a hex value in PROGMEM, why write it out in DEC form, and have to use a calculator (or brain power) to see if the values match. Write it out in HEX form and save the gray cells for important stuff.

True, but that's not the point of the problem... I just put DEC because I copied and pasted from the entire code I'm working on and although the array is in hex, for my application it is easier to know the value in DEC. The array is actually a picture and the values I'm trying to read are the height and width of that picture.

PaulS: @Nick If you store a hex value in PROGMEM, why write it out in DEC form, and have to use a calculator (or brain power) to see if the values match. Write it out in HEX form and save the gray cells for important stuff.

Quite right. I was just too lazy to backspace over DEC and type in HEX. Unfortunately my laziness hit me when I had to reach for my hex calculator to verify the number. ;)

newhobby: So, yes... The code you posted works for me too. Try increasing the size of the array.

Er, yes but you said:

The array is 24095 in size.

Can you give the size that doesn't work?

the array in 24095 in size does not work :(

Ok, so here is what else I found out.
This issue only happens on the ATMEGA2560.
I loaded the code on a Duemilanove w/ optiboot and the code works just fine…
Weird… :drooling_face:
I can’t paste the code, but I attached this time.

PROGMEM_Test.pde (141 KB)

Right. Well I can't upload your sketch onto my Uno:

Binary sketch size: 26172 bytes (of a 32256 byte maximum)
avrdude: verification error, first mismatch at byte 0x0100
         0xff != 0x00
avrdude: verification error; content mismatch

It should fit, and it certainly shouldn't fail at address 0x0100.

Nor can I upload it to my Mega2560:

Binary sketch size: 27010 bytes (of a 258048 byte maximum)
avrdude: verification error, first mismatch at byte 0x0483
         0x9e != 0xff
avrdude: verification error; content mismatch

That's odd, considering my earlier version (without the explicit array values) would upload.

There's more to this than meets the eye.

I can upload my test sketch to the Mega2560:

Binary sketch size: 27010 bytes (of a 258048 byte maximum)

(Done uploading).

So, do you think something in the array is causing a hiccup on avrdude?

It's a working hypothesis, certainly. I'll have to try programming the chip another way I think.

All the _P progmem convenience functions require the data to have been located in the lower 64Kb by the linker because they use the LPM instruction to access memory. You can still get access to your data if the linker has put it above the lower 64Kb by using the 'far' functions that use the ELPM instruction for access.

Read progmem.h for details, and inspect your linker map file for evidence of where your data ends up.

[quote author=Nick Gammon link=topic=76291.msg576351#msg576351 date=1319251287] Nor can I upload it to my Mega2560:

Binary sketch size: 27010 bytes (of a 258048 byte maximum)
avrdude: verification error, first mismatch at byte 0x0483
         0x9e != 0xff
avrdude: verification error; content mismatch

[/quote] Thanks for the explanation, but even with very little program size, it still has issues. The total size of the sketch is 27010, which is below the 64K you mentioned. Does what you stated still apply even though the size is less than 64K?

I notice a long sequence of 0xff in your constant data. It looks like you might be suffering from this problem:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1244377959

Does it upload if you (temporarily) replace the long runs of 0xff with different values?

Ah-ha!!! I think you nailed!!! I don't have any board to test, but I'm pretty sure this is the issue. Thanks a lot!!

Filling program memory with long runs of 0xFF is probably not very efficient use of limited memory. You could try to run-length encode it (via some pre-processing step) which would considerably reduce its size, and at the same time work around this issue.