Why does the IDE compile fail when I include the following code?

I have a sketch that displays a slideshow of files (bmp) on a 320*480 TFT LCD.

It works perfectly. All pictures on the SD (using SdFat) display correctly.

As well as display the picture(s) I want to load them in PROGMEM.

....
unsigned short BackGround[0x25800] PROGMEM;
...
b = inputbuffer[buffidx++];
g = inputbuffer[buffidx++];
r = inputbuffer[buffidx++];
tft.drawPixel(col, row, tft.color565(r,g,b));//paints the pixel, all okay

//BackGround[col*320+row] = tft.color565(r,g,b);//This line causes errors
....

The code snippet as above compiles (doesn't work but compiles okay).
If I uncomment the "//BackGround[col..." I get these errors


Arduino: 1.6.8 (Windows 10), Board: "Arduino Due (Programming Port)"

c:/users/louis/appdata/local/arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld.exe: address 0x200bc940 of C:\Temp\Arduino/DigitalClock.ino.elf section .bss' is not within region ram'

c:/users/louis/appdata/local/arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld.exe: address 0x200bc940 of C:\Temp\Arduino/DigitalClock.ino.elf section .bss' is not within region ram'

c:/users/louis/appdata/local/arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld.exe: address 0x200bc940 of C:\Temp\Arduino/DigitalClock.ino.elf section .bss' is not within region ram'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino Due (Programming Port).

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.


I am a total newbie so I hope it is something simple and obvious :slight_smile:

I played with various formats to no avail.... Similar code in another sketch compiles okay? The only difference the "unasigned short" is also "extern".

Could someone please tell me how I'm going wrong :wink:

First of all, do you really have 307200 bytes of flash memory on your board to put BackGround[] in? Secondly, you are trying to access it as if it is in SRAM. You need to use a pgm_read_byte_near() or pgm_read_word_near()to read it. Third, lose the short datatypes. They are a Microsoft frankenstein monster.

PROGMEM is not writable by code unless one has added this change
https://forum.arduino.cc/index.php?topic=332191.0
Have not tried it myself.

Yes @aarg, it is a Due so there is a half a meg of PROGMEM. :smiley:

And no, @Delta_G I didn't know that PROGMEM was read only. :frowning:

Are you sure!? In another sketch I have a bmp picture setup as source (in PROGMEM) and I have copied bits of it into another bits of PROGMEM. Six bits totalling about 96Kb to be exact.

In other words I have a 307Kb "BackGround.c" file that is a 320*480 pixel file defined as an "extern unsigned short" array. I display a digital clock on this picture in TRANSPARENT mode in a LARGE font. Because of the TRANSPARENT I save bits of the picture under the semi colons and under the MM and SS to refresh under these numbers and this saving "writes" to PROGMEM..... And THAT sketch works as expected so "writes" to PROGMEM happen correctly there!?

I'm on my iPad away from home so I cannot paste THAT working code for perusal. :frowning:

Flash memory is page-based, so you can only write a whole page at a time.

Sorry, couldn't work out have to add code tags as an Edit to a previous message so just posting another message....

Snippets of a fully working sketch using "writing" arrays of PROGMEM from another array in PROGMEM.

....
extern unsigned short BackGround[0x25800];//Background picture
....
//Bits of the picture that would be under
//the minutes (MM) and seconds (SS) digits
//and the 4 dots making up the 2 semi colons.
unsigned short minutes[12800] PROGMEM;
unsigned short seconds[12800] PROGMEM;
unsigned short dot[64] PROGMEM;
unsigned short dottlhs[64] PROGMEM;
unsigned short dotblhs[64] PROGMEM;
unsigned short dottrhs[64] PROGMEM;
unsigned short dotbrhs[64] PROGMEM;
....
for(y=0; y<100; y++) for(x=0; x<128; x++) minutes[(y*128)+x]=BackGround[(y*480)+x+62576];//Save under minutes
for(y=0; y<100; y++) for(x=0; x<128; x++) seconds[(y*128)+x]=BackGround[(y*480)+x+62740];//Save under seconds
for(y=0; y<8; y++) for(x=0; x<8; x++) dottlhs[(y*8)+x]=BackGround[(y*480)+x+73111];//Save under dot tlhs
for(y=0; y<8; y++) for(x=0; x<8; x++) dotblhs[(y*8)+x]=BackGround[(y*480)+x+93751];//Save under dot blhs
for(y=0; y<8; y++) for(x=0; x<8; x++) dottrhs[(y*8)+x]=BackGround[(y*480)+x+73280];//Save under dot trhs
for(y=0; y<8; y++) for(x=0; x<8; x++) dotbrhs[(y*8)+x]=BackGround[(y*480)+x+93920];//Save under dot brhs
....

Sorry, wasn't 96Kb worth.... About 26Kb worth of transferred PROGMEM from the background picture array.

To repeat myself - the (working) sketch

  1. Compiles the BackGround array from the BackGround.c file.
  2. Copies the bits of the picture where the semi colons, the minutes and the seconds blocks from the BackGround PROGMEM array to the six other PROGMEM arrays.
  3. Paints the background picture.
tft.drawBitmap(0, 0, 480, 320, BackGround);
  1. Every second the sketch restores the bit of the picture under the seconds
tft.drawBitmap(340, 130, 128, 100, seconds);//Repaint BG behind transparent seconds
  1. Every minute, the bit under the minutes
tft.drawBitmap(176, 130, 128, 100, minutes);}//Repaint BG behind transparent Minutes

Like I keep saying, this is a working sketch where four tiny PROGMEM arrays and two 12.8Kb arrays are copied out of ONE large PROGMEM array. The six arrays start of as NULL!? So the transfer logic IS writing to them as expected and correctly. This suggests to me that PROGMEM IS writeable!?

The sketch works with the background picture loaded off an "extern" "file.c".

I wanted to make the background picture variable off the SD card rather than loaded off a "file.c".

This is the start of the "BackGround.c" file

// Generated by  : ImageConverter 565 v2.3
// Generated from: BackGround.bmp
// Time generated: 11/03/2016 4:33:57 PM
// Dimensions    : 480x320 pixels
// Size          : 307,200 Bytes

#include <avr/pgmspace.h>

const unsigned short BackGround[0x25800] PROGMEM ={
0xDDF8, 0xE619, 0xE619, 0xE619, 0xE619, 0xE619, 0xE619, 0xE619, 0xE....

Why does the compiler fail with the tiny change of logic?

MarkT:
Flash memory is page-based, so you can only write a whole page at a time.

With all due respect....

Four of my transferred arrays are 64 shorts (128 bytes) and 2 are 12,800 shorts (100 pages?). Nowhere does the transfer logic align to pages etc!? I transfer a short at a time.... Unless the compiler is doing it all for me????

JFI The upload process uploads about 1,700 pages and takes about 75 seconds to upload and about 70 seconds to verify. So each Compile/Upload takes almost 3 minutes....

I'm an abject newbie and I'm not challenging anybody, just want to know why one sketch compiles and works perfectly while another sketch won't even compile :frowning:

The working sketch is HUGE (about 400Kb, about 330Kb are PROGMEM arrays). Rather unwieldy, so I am going to transfer the clock logic into a slideshow (off an SD card) sketch. I am trying to change the slideshow sketch from just displaying pictures (a pixel at a time) off the SD card to also load PROGMEM and then drawBitmap from PROGMEM as a precursor to a digital clock with changing backgrounds rather than one fixed background picture compiled into the sketch.

I believe PROGMEM on Due is null, so it does do anything to your arrays at all, and they stay in RAM. ( unless they have "const", which puts them in flash on due, but not on avr. Using both const and PROGMEM would put them in flash on either.)

westfw:
I believe PROGMEM on Due is null, so it does do anything to your arrays at all, and they stay in RAM. ( unless they have "const", which puts them in flash on due, but not on avr. Using both const and PROGMEM would put them in flash on either.)

Again, with all due respect....

Are you suggesting that my transfers from the large (307Kb) PROGMEM array are actually going from PROGMEM to RAM?

I will play with this idea when I have had some sleep. It is feasible as the Due has 96Kb of RAM....

As a first step I recompiled the BIG sketch and it actually uploads a bit more....

"Write 416228 bytes to flash (1626 pages)"

The 416Kb suggests to me that the transfers ARE going from PROGMEM to PROGMEM rather than PROGMEM to RAM....

Wouldn't "const" defeat my purpose? Would "const" MAKE it "read only"?

Thanks for your reply :smiley:

I dunno - I didn't look at your code carefully enough to see exactly what it's doing.
I did check the Due definition of PROGMEM, and confirmed that it is null. So adding PROGMEM to a Due varaiable declaration does nothing at all. https://github.com/arduino/Arduino/blob/master/hardware/arduino/sam/cores/arduino/avr/pgmspace.h

There are no micros where writing to flash is as simple as saying "VariabeInFlash = value;" Flash is ALWAYS more complicated to write than that. Usually involves erasing, loading, and programming things in "page" sized chunks.

If you have initialized RAM arrays in your program, the flash size (uploaded) will have a copy of all those values as well (where do you think the RAM gets initialized FROM?) One of the reasons that PROGMEM is such a win on AVRs is that it eliminates RAM usage, but does NOT increase Flash usage at all - the data would have been in flash in either case.

Wouldn't "const" defeat my purpose?
[Copies the bits of the picture where the semi colons, the minutes and the seconds blocks from the BackGround PROGMEM array to the six other PROGMEM arrays.]

Your "purpose" of merging two images in flash is not achievable. That's not how it worked when the images were on an SD card, was it? You can theoretically merge images as you're copying to the display:

pixel = Background[x][y];  //get background
pixel |= ForeGround[x][y];  // merge (logical or) in the foreground image
display.write(x,y, pixel);

Thanks for your reply. :smiley:

Sorry, I'm not making my "purpose" clear.

I want to display HH:MM:SS on a background picture. I don't want the digits in rectangles of a background colour. I want the digits ON the original picture so I put the screen in TRANSPARENT mode.

This means I must repaint the picture background every second. It takes about 5 seconds to repaint the whole screen so I can't do that. I just repaint the rectangle behind the SS every second, the rectangle behind the MM every minute and the HH every hour. Forget the semi colons for the moment.... :slight_smile:

The extracted/copied backgrounds are 25.6Kb - no problem on a Due. Eventually I want the sketch on a Mega - only 8Kb RAM. :frowning:

This currently works under the suggestion that the copy is actually going into SRAM....

I'll try to turn on verbose compiler and see if I get more info??

Off to exercise more than my fingers for 3 hours (playing badminton). :slight_smile: