Klaus
Klaus

Reputation: 25623

c++11 generalized attributes with avr __progmem__

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

Answers (1)

Klaus
Klaus

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

Related Questions