Re: [avr-gcc-list] PROGMEM on compound-literal arrays

2016-11-06 Thread Paul "LeoNerd" Evans
On Sun, 30 Oct 2016 20:17:51 +0100
Georg-Johann Lay  wrote:

> Well, code like
> 
> i2c_write (
>  #include "data.def"
> );
> 
> where data.def contains
> 
> 4, (const uint8_t[]){0x10, 0x20, 0x30, 0x40}
> 
> might be in order for auto generated code, but solutions that first 
> define a variable and then use it by its name is superior.  One
> reason is that multiple uses of the same ad hoc data don't generate
> different instances.

Ahyes, multiple references. Given as these are image bitmaps for an
OLED display, perhaps it would be best for me to put them in some
variables after all.

-- 
Paul "LeoNerd" Evans

leon...@leonerd.org.uk  |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] PROGMEM on compound-literal arrays

2016-10-30 Thread Georg-Johann Lay

Paul "LeoNerd" Evans schrieb:

((TLDR: PROGMEM on compound-literal arrays is silently ignored.
  Please either implement or make it a noisy warning/error.))



If I define a function that takes a byte array, e.g.

  void i2c_write(size_t len, const uint8_t *data);

I find it nice to be able to call that with compound-literal arrays
inline:

  i2c_write(4, (const uint8_t[]){0x10, 0x20, 0x30, 0x40});

((The reason I'm using this inline notation rather than a static
  declaration made elsewhere is that my data in fact comes from a
  build-time translation step, and most of the arguments to the function
  call are embedded with an #include directive to embed the data in the
  source code.))


Well, code like

i2c_write (
#include "data.def"
);

where data.def contains

4, (const uint8_t[]){0x10, 0x20, 0x30, 0x40}

might be in order for auto generated code, but solutions that first 
define a variable and then use it by its name is superior.  One reason 
is that multiple uses of the same ad hoc data don't generate different 
instances.



If I want to store the data in PROGMEM instead and write a _P version,
then this syntax won't do:

  i2c_write_P(4, (const PROGMEM uint8_t[]){0x10, 0x20, 0x30, 0x40});

While it does parse and compile successfully, the data doesn't end in
in PROGMEM, so the pgm_read_byte() function doesn't find it, and
returns junk. There's no compile-time warning or error that it hasn't
honoured it though, so debugging this failure can be hard.

The following syntax does work as an alternative:

  i2c_write_P(4, ({
static const PROGMEM uint8_t data[] = {0x10, 0x20, 0x30, 0x40};
data;
  }));

I.e. a statement-expression that embeds a static PROGMEM declaration
and yields it.

Would it be possible to make the former syntax work though?


No, PROGMEM (same for __flash et al.) only work for data in static 
storage.  That's because sections are used to locate such data.  Data of 
automatic storage duration like in your 1st example lives on the stack.


Note that your 2nd example will not work with automatic data because its 
lifetime ends at the end of the enclosing block, hence using its address 
after the end of the block is undefined behaviour (using a dangling 
reference to a declined local).


Johann


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list