在C ++程序中,我需要将I / O寄存器的地址作为常量表达式获取,该表达式可以作为模板参数中的整数传递。在GCC 5中,这有效:
static constexpr uint16_t Address = _SFR_IO_ADDR(PORTA);
但是,GCC 6.3.0会产生以下错误:
error: reinterpret_cast from integer to pointer
以下是AVR libc中定义的摘要:
#define __SFR_OFFSET 0x20
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _SFR_MEM_ADDR(sfr) ((uint16_t) &(sfr))
#define _SFR_IO_ADDR(sfr) (_SFR_MEM_ADDR(sfr) - __SFR_OFFSET)
#define PORTA _SFR_IO8(0x02)
将寄存器地址提取为常量表达式整数是什么工作方法?
我怀疑通过“解析”定义可以通过宏来完成某些事情,但我只看到如何删除第一组括号而不是如何处理星号。
编辑:实际失败的情况是:
#include <avr/io.h>
struct PortDef {
static const uint32_t Address = _SFR_IO_ADDR(PORTA);
};
这是使用的命令和错误:
$ ~/avrgcc/bin/avr-g++ -v
Using built-in specs.
Reading specs from /nix/store/43k8vl3dzm102wj1jsdb1sil9k5b0k6r-avr-gcc-libc/lib/gcc/avr/6.3.0/device-specs/specs-avr2
COLLECT_GCC=/home/ambro/avrgcc/bin/avr-g++
COLLECT_LTO_WRAPPER=/nix/store/43k8vl3dzm102wj1jsdb1sil9k5b0k6r-avr-gcc-libc/libexec/gcc/avr/6.3.0/lto-wrapper
Target: avr
Configured with: ../configure --target=avr --prefix=/nix/store/43k8vl3dzm102wj1jsdb1sil9k5b0k6r-avr-gcc-libc --disable-nls --disable-libssp --with-dwarf2 --disable-install-libiberty --with-system-zlib --enable-languages=c,c++
Thread model: single
gcc version 6.3.0 (GCC)
$ ~/avrgcc/bin/avr-g++ -mmcu=atmega2560 test.cpp -c -o test.o
In file included from /nix/store/43k8vl3dzm102wj1jsdb1sil9k5b0k6r-avr-gcc-libc/avr/include/avr/io.h:99:0,
from test.cpp:1:
test.cpp:3:37: error: reinterpret_cast from integer to pointer
static const uint32_t Address = _SFR_IO_ADDR(PORTA);
在这些情况下它不会失败(所以这些是至少在GCC 6.3中的简单解决方法):
答案 0 :(得分:1)
我不明白<h2>@(Model.Movie==null?"New Movie": "Edit Movie")</h2>
和constexpr
之间的区别,但const
似乎适用于这种情况。以下代码为我编译:
const
我在this library成功使用了该宏。顺便说一句,我认为您可以使用#include <avr/io.h>
static const uint16_t address = _SFR_IO_ADDR(PORTB);
代替uint8_t
。
以下是来自Arch Linux系统的shell会话,显示上面的代码可以使用avr-g ++ 6.3.0进行编译:
uint16_t
答案 1 :(得分:0)
我通过生成定义特定寄存器的数字地址的头文件解决了这个问题。这是actual code。
它的工作原理如下:
PORTA
)。它不是有效的C ++,但在预处理之后会产生REG_PORTA:<definition>;
行,其中<definition>
是PORTA
扩展到的行。static uint16_t const Address_PORTA = <address>;
等定义,其中<address>
是通过剥离原始表达式中的所有强制转换而提取的数字地址。我使用与编译时相同的定义和编译器标志进行预处理,以确保使用正确的寄存器定义。这比解析原始设备特定的头文件更便携,因为您需要知道哪个头文件是正确的。
注意:结果是内存地址,相当于_SFR_MEM_ADDR
。要获取IO寄存器的IO地址(_SFR_IO_ADDR
),必须减去__SFR_OFFSET
。