Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c语言中将变量分配给绝对地址?_C_Pointers_Memory Address_Cortex M - Fatal编程技术网

如何在c语言中将变量分配给绝对地址?

如何在c语言中将变量分配给绝对地址?,c,pointers,memory-address,cortex-m,C,Pointers,Memory Address,Cortex M,我正在尝试访问PMC_PCER0并在ARM Cortex M3上为PID14启用它。我被要求做一个空函数,读取一个按钮并“返回”(我的教授坚持称之为)它的值。无论如何,问题是: void readButton( unsigned int *button) { do something yo; } 我有一个地址用于PMC_PCER0,为了回答这个问题,我们假设它位于0xfff123da,这个PMC_PER0有32个PIO,其中一个是PID,恰好从第14位开始,所以我需要激活这个 要激活它,

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

void readButton( unsigned int *button)
{
   do something yo;
}
我有一个地址用于
PMC_PCER0
,为了回答这个问题,我们假设它位于
0xfff123da
,这个
PMC_PER0
有32个PIO,其中一个是PID,恰好从第14位开始,所以我需要激活这个

要激活它,我是否需要使用`or运算符屏蔽
PMC\u PCER0

我知道我可以定义如下

#define PMC_PCER0 (0xfff123da)

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

那么如何在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功能级别有了一个易于移植的抽象层。如果您想调试正在发生的事情,您可以使用这个抽象层来插入断点或printf或任何东西

不管你接受还是不接受,我花了好几年的时间才让编译器陷入使用volatile技巧无法生成正确指令的困境。如果你至少不学习一点汇编语言,也不定期地反汇编工具生成的代码,那么当编译器生成错误的指令或链接器将项目加载到错误的位置(芯片无法启动、程序挂起等)时,你会遇到更大的困难。然后,如何将工具链移过问题

是的,我知道你想要的功能是加载而不是存储,我想你可以从这里找到答案


这都是基本的C语言编程的东西,可能是为什么没有人想插嘴回答。此外,为您正在使用的微控制器以及所有其他家庭和品牌免费提供的库也使用了这些技巧,尽管其中一些技巧有点吓人,所以请对它们持保留态度(或者将它们用作参考,而不必直接使用,因为您可能最终会拥有它们的问题和维护).

为什么不在MCU中的外围模块上使用供应商(CMSIS)的标头?每个MCU制造商都提供这样的头文件。@Olaf这不是一个PC程序,而是一个嵌入式处理器,即ARM Cortex M3。硬件工程师提供了要使用的地址。编译器/链接器生成的地址不起作用。@QuentinUK:我很确定CMSIS头不是针对PC的。PC没有MCU,只有CPU(尽管差异正在缩小)。无论如何都应该有一个头文件。该名称来自Atmel MCU(AT91SAM3*)中外围模块的寄存器,我非常确信Atmel确实提供了标头。那么,你的观点是什么呢?那么,向公众提问的目的是让你对自己感到不好,因为这里的人实际上什么都不擅长,只会贬低你的问题。然而,没有人给出令人满意的答案!我当然不是指你们这些评论的人^^