gpt4 book ai didi

c++ - 如何在嵌入式系统上创建指向寄存器的 constexpr 指针

转载 作者:行者123 更新时间:2023-12-04 17:19:35 25 4
gpt4 key购买 nike

我希望能够将一个类配置为能够访问其成员函数中的硬件。假设我们有一个 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 和 flash 中的空间。这对于非常小的嵌入式系统是 Not Acceptable 。
如果事实确实如此,那么唯一的工作方法就是真正使用c-宏?我不敢相信我的代码都不会再工作了……而且如果不使用 C 宏,将来也永远不会工作。
我目前使用 avr-g++ (Fedora 10.2.0-1.fc33) 10.2.0但似乎,从我所有的阅读来看,如果在 C++17 模式下使用它是正确的行为。

最佳答案

我认为这在 C++17 中根本不可能。但是,如果您愿意切换到 C++20,则有一种可能的解决方法。而不是锻造一个constexpr直接指针,创建一个自定义类型来表示它,当constexpr时,它会第一时间转换为指针。上下文剩下:

#include <cstdint>

template <typename T>
struct fixed_ptr {
std::uintptr_t m_value;

inline constexpr fixed_ptr(std::uintptr_t p): m_value(p) {}

inline operator T * () const {
return reinterpret_cast<T *>(m_value);
}
};
然后不是直接为模板参数指定类型,而是通过一个概念对其进行约束:
#include <utility>
#include <cstdint>

template <typename T, typename U>
concept pointerish = std::is_same_v<U &, decltype(*std::declval<T>())>;

template <pointerish<volatile std::uint8_t> auto REG>
class X {
public:
X() { *REG = 0x02; }
};

volatile std::uint8_t x;

auto p = X<fixed_ptr<volatile std::uint8_t>(5)>();
auto q = X<&x>();
-O1在直接指针上使用类包装器应该没有开销:内联会处理它。

关于c++ - 如何在嵌入式系统上创建指向寄存器的 constexpr 指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67037386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com