Why PROGMEM attribute ignored?

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to store a bunch of string in program memory + an array of pointers to those strings for easy retrieval, I wrote the following code:

static const char ESP_RST[] PROGMEM = "AT+RST\r\n";
static const char ESP_ATE[] PROGMEM = "ATE1\r\n";
static const char ESP_CWMODE[] PROGMEM = "AT+CWMODE=2\r\n";
static const char ESP_CWSAP[] PROGMEM = "AT+CWSAP=\"HotSpot\",\"12345\",5,0\r\n";
static const char ESP_CIPMUX[] PROGMEM = "AT+CIPMUX=0\r\n";
static const char ESP_CIPSERVER[] PROGMEM = "AT+CIPSERVER=1,80\r\n";
static const char ESP_CIFSR[] PROGMEM = "AT+CIFSR\r\n";
	
PGM_P ESP_CMNDS[7] PROGMEM = {
	ESP_RST,
	ESP_ATE,
	ESP_CWMODE,
	ESP_CWSAP,
	ESP_CIPMUX,
	ESP_CIPSERVER,
	ESP_CIFSR	
};

After compiling, I get a warning that the PROGMEM attribute for the array is ignored. Why is that and what is the correct way to write this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

slow_rider wrote:
I get a warning that the PROGMEM attribute for the array is ignored.
Is the array global or local? It has to be global to go into .progmem

 

BTW if you are writing new code then why PROGMEM and not the __flash that the compiler now supports? It makes life much easier as you don't need the pgm_read stuff.

Last Edited: Fri. Jul 12, 2019 - 10:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code is inside a procedure... any other way to achieve the same thing? My goal is to have a bunch of strings with init commands etc that I can send out by a for() loop so I need an array for easy access using an index.

 

I'll take a look at the documentation, honestly I had no idea this was updated - is this on IAR only? I see the documentation for AVR LIBC is the same.

Last Edited: Fri. Jul 12, 2019 - 10:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

slow_rider wrote:
I see the documentation for AVR LIBC is the same.
__flash has nothing to do with libc. It's part of the compiler itself and, as such, is documented in the compiler manual:

 

https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Named-Address-Spaces.html

 

(that's 4.9.2 but there's similar in all the recent issues of the manual). The point is that previously you did:

#include <avr/pgmspace.h>

const uint8_t PRGMEM data[] = { 1, 17, 26, 54 };

int main(void) {
    for (int i = 0; i < 4; i++) {
        PORTB = pgm_read_byte(&data[i]);
    }
}

Now you do:

#include <avr/pgmspace.h>

const __flash uint8_t data[] = { 1, 17, 26, 54 };

int main(void) {
    for (int i = 0; i < 4; i++) {
        PORTB = data[i];
    }
}

It is FAR simpler. The compiler "knows" that data[] is in flash so in the PORTB write it already knows it has to LPM the data - no need for pgm_read_byte() style helpers to force an LPM access any more.

 

Note __flash is only added to the C compiler, not the C++ compiler.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What would be the best way to update this under studio 7? Seems like I have an old version of the compiler that does not recognize the directive.

Seems Atmel gallery is also broken, it download microchip extension that installs and does nothing. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Did you do some kind of "project import"? if yes then it will likely have set up a "toolchain flavour" to also use the old compiler. That needs to be switched to use the "native" option (meaning the compiler that came with AS7):

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

No import... the only toolchain version I have available is the native. Can a new version be installed from inside Studio or I need to download from the GCC site and update the path or create a new flavor?

 

 

Last Edited: Fri. Jul 12, 2019 - 11:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to be clear is the C or C++? as I say __flash is only in the C compiler not the C++ compiler.

 

Also what version? In the build output you will see something like:

		Invoking: AVR8/GNU C Compiler : 5.4.0

I think __flash first appeared around 4.6

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

It's a C project

 

I did not find any mentioning of the compiler version at the build output however going to Tools -> Options

 

And checked what's in the path:

 

UPDATE - found it in the makefile outputs @echo Invoking: AVR/GNU C Compiler : 5.4.0

downloaded 9.1 and created a flavor for it and now I need to figure out how to config everything for it

 

 

 

Last Edited: Fri. Jul 12, 2019 - 12:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Inside a function, ESP_CMDS is auto.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so now I should have a bunch of strings that are held in flash and an array of pointers, also stored in flash. So far this is good, just what I wanted.

 

I have the following function to send strings over UART:

void UARTSendString (const char *data)
{
	while (*data != '\0')
		UARTSendChar (*data++);
}

When I call it like so:

UARTSendString("AT+RST\r\n");

No problems, all works fine. Now I have that string stored in RAM:

static const char ESP_RST[] = "AT+RST\r\n";

Sending it using the following command works as expected:

UARTSendString (ESP_RST);

Now I am storing the string into flash:

static const __flash char ESP_RST[] = "AT+RST\r\n";

Now sending does not work using the above command. So what have changed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want your 

UARTSendString

 to work on both __flash and ram strings, add __memx to it. This pointer type can distinguish between the two types.

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

meolsen wrote:

If you want your 

UARTSendString

 to work on both __flash and ram strings, add __memx to it. This pointer type can distinguish between the two types.

 

Ahhhh.... otherwise it can't address the flash memory. Thanks!