在 C/C 中直接写入内存地址的最短代码是什么?
我正在为没有内存保护的嵌入式系统(在 ARM Cortex-M1 上,使用 gcc 4.3 编译)编写系统级代码,并且需要直接读/写内存映射寄存器。到目前为止,我的代码如下所示:
#define UART0 0x4000C000
#define UART0CTL (UART0 + 0x30)
volatile unsigned int *p;
p = UART0CTL;
*p &= ~1;
有没有不使用指针的更短的方法(我的意思是代码更短)?我正在寻找一种方法来编写如此短的实际赋值代码(如果我必须使用更多#defines,那就没问题了):
*(UART0CTL) &= ~1;
到目前为止我尝试过的任何事情都以 gcc 抱怨它无法将某些内容分配给左值而告终。 ..
I'm writing system-level code for an embedded system without memory protection (on an ARM Cortex-M1, compiling with gcc 4.3) and need to read/write directly to a memory-mapped register. So far, my code looks like this:
#define UART0 0x4000C000
#define UART0CTL (UART0 + 0x30)
volatile unsigned int *p;
p = UART0CTL;
*p &= ~1;
Is there any shorter way (shorter in code, I mean) that does not use a pointer? I looking for a way to write the actual assignment code as short as this (it would be okay if I had to use more #defines):
*(UART0CTL) &= ~1;
Anything I tried so far ended up with gcc complaining that it could not assign something to the lvalue...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
:-P
编辑添加:哦,为了回应有关如何标记问题 C++ 以及 C 的所有评论,这里有一个 C++ 解决方案。 :-P
这可以直接放在头文件中,就像 C 风格的宏一样,但您必须使用函数调用语法来调用它。
:-P
Edited to add: Oh, in response to all the comments about how the question is tagged C++ as well as C, here's a C++ solution. :-P
This can be stuck straight in a header file, just like the C-style macro, but you have to use function call syntax to invoke it.
我想吹毛求疵:我们是在谈论 C 还是 C++?
如果是 C,我愿意听从 Chris 的回答(并且我希望删除 C++ 标签)。
如果是 C++,我建议不要完全使用那些令人讨厌的 C-Cast 和
#define
。惯用的 C++ 方法是使用全局变量:
我声明一个类型化全局变量,它将遵守范围规则(与宏不同)。
它可以轻松使用(无需使用
*()
),因此更短!如果你希望它是指针,那么它会是:
但是使用不能为 null 的 const 指针有什么意义呢?从语义上讲,这就是创建引用的原因。
I'd like to be a nitpick: are we talking C or C++ ?
If C, I defer to Chris' answer willingly (and I'd like the C++ tag to be removed).
If C++, I advise against the use of those nasty C-Casts and
#define
altogether.The idiomatic C++ way is to use a global variable:
I declare a typed global variable, which will obey scope rules (unlike macros).
It can be used easily (no need to use
*()
) and is thus even shorter!If you want it to be pointer, then it would be:
But what is the point of using a
const
pointer that cannot be null ? This is semantically why references were created for.如果您想让硬件寄存器看起来像普通的旧变量,您可以比克里斯的答案更进一步:
这是一个可能更可取的品味问题。我曾经遇到过团队希望寄存器看起来像变量的情况,并且我曾经编写过添加的取消引用被认为“隐藏太多”的代码,因此寄存器的宏将被保留为必须明确取消引用(如克里斯的回答)。
You can go one further than Chris's answer if you want to make the hardware registers look like plain old variables:
It's a matter of taste which might be preferable. I've worked in situations where the team wanted the registers to look like variables, and I've worked on code where the added dereference was considered 'hiding too much' so the macro for a register would be left as a pointer that had to be dereferenced explicitly (as in Chris' answer).
我喜欢指定结构中的实际控制位,然后将其分配给控制地址。像这样的东西:(
如果语法不太正确,我很抱歉,我实际上已经有一段时间没有用 C 编写代码了......)
I like to specify the actual control bits in a struct, then assign that to the control address. Something like:
(Apologies if the syntax isn't quite right, I haven't actually coded in C for quite awhile...)
对于嵌入式应用程序,我喜欢的另一个选项是使用链接器来定义硬件设备的部分,并将变量映射到这些部分。这样做的优点是,如果您的目标是多个器件,即使来自同一供应商(例如 TI),您通常也必须逐个器件地更改链接器文件。即同一系列中的不同设备具有不同数量的内部直接映射内存,并且板与板之间也可能具有不同数量的 RAM 以及位于不同位置的硬件。以下是 GCC 文档中的示例:
Another option which I kinda like for embedded applications is to use the linker to define sections for your hardward devices and map your variable to those sections. This has the advantage that if you are targeting multiple devices, even from the same vendor such as TI, you will typically have to alter the linker files on a device by device basis. i.e. Different devices in the same family have different amounts of internal direct mapped memory, and board to board you might have different amounts of ram as well and hardware at different locations. Here's an example from the GCC documentation: