ARM C++ - 如何将常量成员放入闪存?
我有这段代码,
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;
}
当我编译它时,我希望
text data bss dec hex filename
656 0 8 664 298 lpc17xx
const _port 和 _pin 变量存储在闪存中,因为它们被标记为 const 并且初始化值在编译时已知,但它们分配在 .bss 部分中。有什么办法让它们驻留在闪存中吗?
编辑: 我尝试过这个:
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
似乎可以解决问题。为什么它不适用于课程?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
构造函数的参数是变量,您将变量分配给 const,这在构造函数中是可以的,但是虽然智能优化器可能会发现静态实例化中常量表达式的出现,但您可能会问很多,因为一般情况要求构造函数接受变量,并且将为一般情况生成代码。
您可能可以使用模板类来实现您想要的目标,并将端口/引脚作为模板参数而不是构造函数参数传递。
它可能与编译器相关,但根据我的经验,您必须将变量声明为 static const 才能将其强制进入 Flash,但这对您想要执行的操作不起作用。
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.
使用placement new 在特定内存位置创建类的实例:
Use a placement new to create an instance of the class in a specific memory location:
它不适用于类,因为您本质上是通过函数调用 (ctor) 初始化
const
。这类似于全局范围内的 const int foo = rand() :const
,但不是积分常量表达式。struct
代码不会调用任何构造函数,无论是对于struct
本身还是任何成员。It doesn't work with classes because you're essentially initializing the
const
via a function call (ctor). That's similar toconst int foo = rand()
at global scope:const
, but not an Integral Constant Expression.The
struct
code doesn't invoke any ctor, neither for thestruct
itself nor for any member.我想你会发现确实如此。
data
部分为空,这可能意味着您的常量存储在text
部分中。文本部分是只读的,并且可能驻留在就地执行 NOR ROM 中,具体取决于 ROM 映像的构建和运行方式。 (bss 部分不算在内,因为它本身不包含任何数据,而是告诉加载器 0 个初始化变量需要多少额外内存。)I think you will see that it does. The
data
section is empty which probably means that your constants were stored in thetext
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.)IO led1(LPC_GPIO0, 5);
行做了两件事。它告诉编译器分配一个长度为8字节的读/写结构,然后调用初始化函数viz。构造函数将其分别初始化为可写静态内存中的 LPC_GPIO0 和 5。此初始化是由在调用主函数之前运行的构造函数完成的。您的第二个示例不涉及初始化函数,即。一个构造函数,但是分别将不可更改的内存简单初始化为“LPC_GPIO0”和“5”,因此可以直接放入文本部分。
最终,这是一个优化问题,并且由于构造函数是内联的且微不足道的,因此可以完全消除它。然而,这可能需要你的编译器不具备的智能程度。
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 functionYour 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.