如何将变量赋值给c中的绝对地址?

时间:2015-11-21 15:38:13

标签: c pointers memory-address cortex-m

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

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

我有PMC_PCER0的地址,让我们假设问题是0xfff123da,而PMC_PER0有32个PIO,其中一个是PID并且恰好开始在第14位,所以我需要激活这个。

为了激活它,我是否需要使用`或运算符?

来屏蔽PMC_PCER0

我知道我可以按如下方式定义PMC_PCER0

#define PMC_PCER0 (0xfff123da)

但是,这只会给PMC_PCER0提供0xfff123da的值,但我想要做的是PMC_PCER0实际拥有该地址。后来我想掩盖它。如果您详细解释,我会很感激。

1 个答案:

答案 0 :(得分:2)

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

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

然后* p = 10;会写一个10到那个地址吗?或者p [0] = 10;,基本的C语言编程,与微控制器或操作系统无关。

你最终遇到的问题是优化者。如果以后没有使用* 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文件链接到项目中,或将其放入引导程序中。

.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技巧生成正确的指令。如果你不学习至少一点汇编语言,并且不经常反汇编工具生成的代码,那么当出现问题时,如编译器生成的错误指令或链接器加载到错误位置的项目,你将会遇到更多困难(芯片没有启动,程序挂起等)。然后,如何移动工具链超过问题。

是的我知道你想要的功能是一个负载而不是商店,我假设你可以从这里找到它。

这是所有基本的C语言编程的东西,可能是为什么没有人想要跳进去回答。对于你正在使用的微控制器以及所有其他家庭和品牌免费提供的库也会使用这些技巧,虽然它们中的一些有点可怕,所以请带上一些盐(或者用它们作为参考而不一定直接因为你可能最终拥有他们的问题和维护。)