【发布时间】:2021-07-06 07:04:36
【问题描述】:
我希望能够配置一个类,使其能够在其成员函数中访问硬件。假设我们有一个 avr 设备,我们可以简单地访问像 PORTA = 0x00; 这样的硬件,它将0x00 写入 io 内存空间。这个问题对于每种嵌入式内存 io 访问都是通用的,而不是特定于 avr。
但是如果我现在想使用一个可以参数化的类,C++ 似乎已经关闭了所有的大门,因为似乎根本不可能定义任何类型的指针类型并给它们一个 constexpr 值。
之前的一些编译器版本,我们能够运行这样的代码:constexpr reference to avr port address
但是现在所有尝试为 constexpr 值的指针分配值都失败了,因为在这种情况下不能再使用 reinterpret_cast。
作为一个肮脏的黑客,我尝试过但失败了:
struct ONE
{
static constexpr volatile uint8_t* helper=nullptr;
static constexpr volatile uint8_t* portc=&helper[100];
};
失败:
x.cpp:6:57: error: arithmetic involving a null pointer in '0'
6 | static constexpr volatile uint8_t* portc=&helper[100];
同样失败:
// for AVR PORTB is defined in io.h like:
#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))
constexpr volatile uint8_t* ptr=&PORTB;
失败:
x.cpp: In function 'int main()':
x.cpp:15:37: error: 'reinterpret_cast<volatile uint8_t* {aka volatile unsigned char*}>(56)' is not a constant expression
15 | constexpr volatile uint8_t* ptr=&PORTB;
直接让我找到reinterpret_cast<volatile uint8_t*>(37)' is not a constant expression。而且还没有任何解决办法!
我的目标非常非常简单: 编写一些可以配置为使用特定寄存器的类,例如:
template < volatile uint8_t* REG>
class X
{
public:
X() { REG = 0x02; }
};
如果我们不能再将指针值定义为 constexpr 值,我们就不能在模板中使用它们,也不能直接使用它们。这意味着,我们只有运行时变量,无法再优化,并且总是需要 ram 和 闪存中的空间。这对于非常小的嵌入式系统是不可接受的。
如果事实确实如此,那么唯一的工作方式就是使用 c-macros 吗?我不敢相信我的任何代码都不会再工作了......而且如果不使用 C 宏,将来也永远不会工作。
我目前使用avr-g++ (Fedora 10.2.0-1.fc33) 10.2.0,但从我的所有读数看来,如果在 C++17 模式下使用它是正确的行为。
【问题讨论】:
-
您使用什么确切的编译器和版本?是最近GCC吗?还有哪些编译器选项?
-
@BasileStarynkevitch avr-g++ (Fedora 10.2.0-1.fc33) 10.2.0 with c++17