Reputation: 25623
The following code compiles as expected with avr-g++ 4.8.1: (code must split in different translation units to see any result, because the optimizer will remove all effects while inlining the instructions)
x.h:
struct X
{
uint8_t a;
};
x.cpp:
extern const X x __attribute__ ((__progmem__)) = { 1 };
main.cpp:
#include "x.h"
extern const X x __attribute__ (( __progmem__ ));
int main()
{
PORTB = pgm_read_byte(& (x.a));
return 0;
}
results in (objdump -d):
0000001a <x>:
1a: 01 00 ..
...
2e: ea e1 ldi r30, 0x1A ; 26
30: f0 e0 ldi r31, 0x00 ; 0
32: c8 95 lpm
the result is fine.
Q: Why is it not possible to write in c++11:
extern const X x [[__progmem__]] = { 1 };
this results in a warning "x.cpp:8:32: warning: 'progmem' attribute directive ignored [-Wattributes]" and the code is broken because the var x is stored to ram instead of flash.
Next question comes with using of class methods which must handle the data members different regarding the storage in flash or ram.
a.h:
class A
{
private:
uint8_t a;
public:
constexpr A( uint8_t _a): a(_a) {}
void Store() const; // Q:should be something like const __attribute__((__PROGMEM__)) ???
void Store();
};
a.cpp:
#include "a.h"
void A::Store() const
{
PORTB=pgm_read_byte(&a);
}
void A::Store()
{
PORTB=a;
}
extern const A a_const PROGMEM ={ 0x88 };
A a_non_const={ 0x99 };
main.cpp:
extern const A a_const;
extern A a_non_const;
int main()
{
a_const.Store();
a_non_const.Store();
return 0;
}
The code works fine, but breaks if the var declarations is:
extern const A a_const_non_flash={ 0x11 };
Because the qualifier const to "void Store() const" is not enough to decide that the var is stored in flash/ram. Is there any trick for this?
Upvotes: 2
Views: 649
Reputation: 25623
The solution for the first part of my question is quite simple:
extern const X x __attribute__ ((__progmem__)) = { 1 };
extern const X x [[gnu::__progmem__]] = { 1 };
The problem was the missing gnu:: before the attribute.
Upvotes: 1