如何将变量分配给c中的绝对地址?

How to assign a variable to an absolute address in c?

我正在尝试访问 PMC_PCER0 并在 ARM Cortex M3 上为 PID14 启用它。我被要求创建一个 void 函数来读取一个按钮和 "returns"(我的教授坚持这样称呼它)它的值。无论如何,这是问题所在:

void readButton( unsigned int *button)
{
   do something yo;
}

我有一个 PMC_PCER0 的地址,为了问题的缘故我们假设它在 0xfff123da 并且这个 PMC_PER0 有 32 个 PIO,其中一个是 PID 并且发生从第14位开始,所以我需要激活这个。

为了激活它,我需要使用 `or 运算符屏蔽 PMC_PCER0 吗?

我知道我可以定义PMC_PCER0如下

#define PMC_PCER0 (0xfff123da)

然而,这只会给 PMC_PCER0 0xfff123da 的值,但我想要做的是 PMC_PCER0 实际拥有该地址。后来我想掩盖它。如果您能详细解释一下,我将不胜感激。

那么你如何在 C 中的某个地址加载或存储一些东西?你需要一个数组或指针吗?如何为指针分配地址?

unsigned int *p;
...
p = (unsigned int *)0x12345678;

然后*p = 10;会向该地址写入 10 吗? or p[0] = 10;, elementary C language programming, 与微控制器或操作系统无关。

你最终遇到的问题是优化器。如果以后不使用 *p 或 p[0] 则根本没有理由生成代码。即使它确实生成了代码,也不能保证它确实进行了存储或加载

void myfun ( unsigned int x )
{
    unsigned int *p;
    p = (unsigned int *)0x12345678;
    *p = x;
}

你如何告诉编译器或者你如何使用语言来要求编译器实际进行内存操作?

volatile unsigned int *p;
p = (unsigned int *)0x12345678;

所以试着让你的定义看起来像这样

#define PMC_PCER0   (*((volatile unsigned int *)0xfff123da))

并且了解这仍然不能保证 1) 编译器将执行总线操作 2) 总线操作将达到您想要的大小。如果你想保证这样的事情,那么

#define PMC_PCER0 (0xfff123da)

并制作一个小的 asm 文件 link 到项目中,或者将其放入您的 bootstrap.

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr
.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr

然后使用它

void myfun ( unsigned int x )
{
    PUT32(PMC_PCER0,x);
}

这会产生性能成本,但它也有显着的好处,首先是编译器,如果远程兼容必须按顺序执行所有函数调用。因此,您可以确保您收到您的货物或商店,并且您可以确保它的尺寸合适。其次,您对外围设备和其他特殊地址的所有访问都是通过抽象层控制的,当放置在芯片模拟器或操作系统之上时,或者当您针对手工测试台(模拟器)进行自己的测试时,您已经拥有C函数级别的抽象层,易于移植。如果你想调试正在发生的事情,你可以使用这个抽象层来插入断点或 printfs 或其他任何东西。

要么接受要么放弃,我花了很多年才让编译器无法使用 volatile 技巧生成正确的指令。如果您至少不学习一点汇编语言,并且不定期反汇编工具生成的代码,那么当出现错误时,您会比必要的更加努力,例如编译器生成错误的指令或将项目加载到错误的位置 linker(芯片不启动,程序挂起等)。然后是如何移动工具链解决问题。

是的,我知道你想要的功能是加载而不是存储,我想你可以从这里弄明白。

这都是基本的 C 语言编程内容,可能是为什么没有人愿意插手回答的原因。此外,为您正在使用的微控制器以及所有其他系列和品牌免费提供的库使用了这些技巧,尽管其中一些有点可怕,所以请对它们持保留态度(或将它们用作参考,但不一定直接,因为您可能最终拥有他们的问题和维护)。