ARM C++ - how to put const members in flash memory

2019-06-28 07:55发布

I have this code

class IO {
 public:       
    IO(LPC_GPIO_TypeDef* port, int pin) : _pin(pin), _port(port) {};        

    const int _pin;
    LPC_GPIO_TypeDef* const _port;


    void test() {
        LPC_GPIO0->FIOSET = 0;
    }

};

IO led1(LPC_GPIO0, 5);

int main() {
    led1.test();

    return 0;
}

When i compile it i get

text       data     bss     dec     hex  filename
656        0          8     664     298  lpc17xx

I'd expect const _port and _pin variables be stored in flash since they are marked const and initialization values are known at compile time, but they are allocated in .bss section. Is there any way to make them reside in flash memory?

EDIT: I tried this:

struct IO {

    LPC_GPIO_TypeDef* port;
    int pin;

    void test() const {
        //_port->FIOSET = _pin;

        LPC_GPIO0->FIOSET = 0;
    }

};

const IO led1 = {LPC_GPIO0, 5};

text       data     bss     dec     hex filename
520        0          0     520     208 lpc17xx

seems to do the trick. Why doesn't it work with classes?

5条回答
爷、活的狠高调
2楼-- · 2019-06-28 08:07

Use a placement new to create an instance of the class in a specific memory location:

void * memPtr = 0x???????;
IO* ptrIO = new(memPtr) IO(LPC_GPIO0, 5);
查看更多
姐就是有狂的资本
3楼-- · 2019-06-28 08:09

The line IO led1(LPC_GPIO0, 5); does two things. It tells the compiler to allocate a read/write structure of length 8 bytes long and then call the intiailization function viz. the construcotr to initialize it to LPC_GPIO0 and 5 respectively in writable static memory. This initialization is done by the constructor which is run before calling your main function

Your second example does not involve an intialization function viz. a constructor but is a simple initialization of non-changable memory to `LPC_GPIO0 and 5 respectively and can therefore be placed directly into the text section.

Ultimately this is an optimization issue and since the constructor is inlined and trivial it could be done away with entirely. However this probably takes a degree on intelligence that your compiler does not have.

查看更多
够拽才男人
4楼-- · 2019-06-28 08:19

I think you will see that it does. The data section is empty which probably means that your constants were stored in the text section. The text section is read-only and may well reside in execute-in-place NOR ROM depending on how your ROM images are built and run. (The bss section does not count since this does not contain any data per-se but rather tell the loader how much extra memory is needed for 0 initialized variables.)

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-06-28 08:24

It doesn't work with classes because you're essentially initializing the const via a function call (ctor). That's similar to const int foo = rand() at global scope: const, but not an Integral Constant Expression.

The struct code doesn't invoke any ctor, neither for the struct itself nor for any member.

查看更多
霸刀☆藐视天下
6楼-- · 2019-06-28 08:30

The parameters to the constructor are variables, you are assigning a variable to a const, which is OK in a constructor, but while a smart optimiser might spot the occurrence of the constant expressions in the static instantiation, you are probably asking a lot, since the general case requires the constructor to accept variables, and the code will be generated for the general case.

You could probably achieve what you want using a template class, and pass the port/pin as template arguments rather than constructor arguments.

It may be compiler dependent, but in my experience you have to declare a variable as static const to force it into Flash, but that will not work for what you are trying to do.

查看更多
登录 后发表回答