【发布时间】:2020-07-15 00:34:14
【问题描述】:
我想为支持 ARM Cortex-M3 的设备创建自己的库。当前写入寄存器如下所示:
(*((unsigned int volatile * const)(0x400E0410))) = (1 << 11) | (1 << 12);
其中0x400E0410 是 32 位外设寄存器的地址(在本例中是电源管理控制器的“外设时钟启用寄存器”的地址)。
所以我希望将外围设备抽象为struct,这样它对用户更加友好、可读,并允许在 IDE 中自动完成。前面的示例将如下所示:
PMC.PCER = PORTB.ID | PORTC.ID;
我不能在struct 或其成员上使用volatile,否则(据我所知)即使该结构实际上并未用于代码中的任何内容,它也会始终在最终代码中包含该结构。我还注意到,即使结构是 name-less 并且它的所有成员都已初始化为 const 值,编译器也会为它创建一个构造函数并将其存储在 RAM 中,而不是真正次优的 FLASH 中。
最好我还希望struct 方法生成这样的汇编代码(第一个示例的反汇编):
而不是像这样从 RAM 中读取结构变量的代码(我的方法在结构中使用 volatile 成员):
如何在不影响程序大小或性能的情况下实现这一点?
编辑:我的方法的 C++ 代码,u32v 是无符号 volatile 32 位整数,u32c 是无符号 const 32 位整数
【问题讨论】:
-
我强烈建议不要在编译域中使用结构。但是有无数的例子可以说明你正在尝试做的事情。所有这些 volatile 方法都会带来使用 volatile 的副作用。
-
@old_timer 你有这些例子的链接吗?
-
st.com, github.com
-
如果您想要基于 volatile 的方法,您的第一种方法看起来最干净。您可以将左侧的所有内容包装到一个定义中 #define SOME_REGISTER (*((unsigned int volatile * const)(0x400E0410))) .... SOME_REGISTER = (1
-
尽管 old_timer 不喜欢使用结构来访问寄存器,但大多数用户都愿意通过使用芯片寄存器的 CMSIS 定义来沿着这个边缘跳舞。你不是有什么原因吗?