PROGMEM structures on 128K device

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

So if I have a:

const uint8_t PROGMEM MsgCRCM[]={'c','R','c','M', 0,0,0,    0,0,};

On a 128K ATMEGA1284P, should this be a 16 bit pointer?

 

I know the flash is 64K 16bit words, but accessing the structure the flash in C is done in bytes not words...

 

If I try this:

 

    if (!testcrc(0,(uint32_t)MsgCRCM))

I get a warning:

 

Severity    Code    Description    Project    File    Line

Warning        cast from pointer to integer of different size [-Wpointer-to-int-cast]    SKCipherX3    C:\Data\SA Development\Enigma\AVR Based\SKCipherX3\firmware2\main.c    4131

 

If I intentionally cast it to uint16_t first, the warning goes away:

 

    if (!testcrc(0,(uint32_t)(uint16_t)MsgCRCM))

Shouldn't MsgCRCM be a larger sized pointer than 16 bits?  What if it is located past the first 64K?

 

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

Nevermind, searching shows that PROGMEM pointers are always 16 bit...

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

Why are you using PROGMEM in 2019? If you want "wide" pointers then use __memx (23 bit pointer plus 1 bit to indicate RAM/flash)

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

Alan,

 

Perhaps this is the thread to discuss __flash and __memx? Probably best to start by reading the manual:

 

https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html#AVR-Named-Address-Spaces-1

 

As you will see there __flash is a modifier that can be applied (always with const) to a pointer in GCC to say "dereference this with LPM not LD/LDS" but such a pointer is still 16 bit so in devices with more than 64KB of flash there exists __flash1, __flash2 etc and it's your responsibility to know where the data resides and which one to use.

 

__memx is a "generic pointer". Things like IAR have had these previously. It's a special kind of pointer that should be able to cater for both RAM and flash. The pointers are 24 bit with bit 23 saying whether it is flash or RAM and the other 23 bits (bits 22..bit 0) being the actual data address. Because there is 23 bits of address the bottom 16 bits are effectively the offset into the current 64KB then bits 22 to bit 16 are the "page selector" which is used in RAMPZ. As the manual notes:

  • Reading across the 64 KiB section boundary of the __flash or __flashN address spaces shows undefined behavior. The only address space that supports reading across the 64 KiB flash segment boundaries is __memx.

That's quite a strong argument (IMHO) for using __memx over __flash on "large flash" devices.

 

Also because __memx can point to both flash and RAM you can make generic routines such as uart_printstring() that take a __memx pointer to data then handle thedereference differently depending on whether bit 23 is set or not. As noted on this page in the manual:

 

https://gcc.gnu.org/onlinedocs/gcc/AVR-Built-in-Functions.html#AVR-Built-in-Functions

 

There is __builtin_avr_flash_segment() which will return -1 if the passed __memx address points to RAM not flash. Or, if it points to flash it might be used to manually set RAMPZ.

 

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

Are there issues with the forum?  I know I responded to #3, but it isn't here.  I got a notification that someone responded to this thread and it also isn't here.

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

A spammer attacked this thread so I deleted it (he mentioned "PROGMEM" but then linked to a site selling power tools). It's just vaguely possible that in the instant I was doing that it took your post with it. Apologies if that occurred.

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

No worries clawson - thanks!