【问题标题】:Preprocessor Macro : Make pointer from integer content预处理器宏:从整数内容制作指针
【发布时间】:2020-07-27 04:10:15
【问题描述】:

我想制作一个预处理器宏,它将表示地址的整数转换为指针。这是用于 MCU 开发的。

例如,寄存器是这样定义的

#define SOME_REGISTER 0x05 // This the the address of SOME_REGISTER

所以我定义了以下宏:

#define REG_ADDR(reg) (*((volatile uint8_t*) reg))

当我不想使用它时

volatile uint8_t * reg_ptr = REG_ADDR(SOME_REGISTER)

当然,我收到了makes pointer from integer without a cast [-Wint-conversion] 警告

有没有干净的方法来做到这一点?

提前致谢

【问题讨论】:

  • 我认为应该删除REG_ADDR 定义中的第一个星号。这不是取消引用您刚刚通过转换reg 创建的指针吗?这不是你想要做的,是吗?
  • 您要访问什么寄存器,您使用的是什么 AVR?如果您在程序顶部包含 avr/io.h,您的 AVR 工具链是否已经为寄存器提供了定义?

标签: pointers macros embedded avr


【解决方案1】:

您可以重复使用已存在且经过适当许可发布的经过验证的代码。
例如,您可以使用来自 Arm 的 mmio.h 代码,您可以在 include/lib 目录中的 Arm 可信固件的 git 存储库中找到它。

在您的示例中,您将使用来自mmio.hmmio_read_8() 函数:

static inline uint8_t mmio_read_8(uintptr_t addr)
{
    return *(volatile uint8_t*)addr;
}

结果代码是:

volatile uint8_t * reg_ptr = mmio_read_8((uintptr_t) SOME_REGISTER);

【讨论】:

  • 非常感谢您的快速回答。我要测试一下。
  • 直接写入硬件寄存器不是火箭科学,而是日常的嵌入式编程。没有必要让第 3 方英国媒体报道软件做这些琐碎的事情。如果有的话,请使用工具供应商为特定部分提供的寄存器映射。
  • 此外,这个所谓的“可信库”充满了可疑的隐式类型提升。可能对 32 种苦味剂效果很好,然后在 8 种苦味剂上咳出细微的虫子。永远不要相信在同一行包含一些 4-5 静默隐式类型转换的“智能”单行代码。这是一个脆弱的代码,至少符合 MISRA-C 标准就可以消除所有这些潜在危险。
  • @Lundin:我想说,如果这对我们的朋友来说是微不足道的,他可能一开始就不会问他的问题,即使答案对你和我来说似乎微不足道。另一方面,Arm 的人可能知道他们在做什么,但他们仍然选择重用他们可以使用的现有头文件,这是一个值得尊敬的选择 UMHO。
  • @Lundin:我们朋友的应用程序中使用的任何代码最终都必须经过测试。我仍然认为重用 mmio.h 对于初学者来说比使用自己的代码更安全,但我同意这可能是主观的。
【解决方案2】:

通常,您只需将此类寄存器定义为#define SOME_REGISTER (*(volatile uint8_t*) 0x05),无需额外步骤。

编译器消息的出现是因为宏是用* 取消引用编写的,因此它可以用作常规变量。所以你可以直接读/写寄存器,中间没有局部指针变量。

如果这不是你想要的,那么要么不要这样使用寄存器,要么将代码更改为:

volatile uint8_t* reg_ptr = &REG_ADDR(SOME_REGISTER);

调用方的& 和宏内部的* 将相互抵消。

【讨论】:

  • 感谢您的明确答复,我误用了寄存器,现在更清楚了。
  • 这个“额外步骤”在汇编语言文件中可能会派上用场,因为可以在.S 源文件中使用简单的#define 寄存器号。
  • @ndim 这是非常特定于工具链的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
相关资源
最近更新 更多