我想访问由硬件寄存器中的地址指向的32位数据(64位,仅设置40 LSb)。所以我这样做:
paddr_t address = read_hw(); // paddr_t is unsigned long long
unsigned int value = *(unsigned int*) address; // error: cast to pointer from integer of different size
unsigned int value2 = (unsigned int) *((paddr_t*) address); // error: cast to pointer from integer of different size
在没有编译器错误的情况下,正确的方法是什么(我使用-Werror)?
答案 0 :(得分:1)
名义上使用C99,第一个选项最接近正确,
uint32_t value = *(uint32_t*)address;
但是,您也可以选择使用其他指针/整数助手
uintptr_t address = read_hw();
uint32_t value = *(uint32_t*)address;
答案 1 :(得分:0)
检查指针和paddr_t类型的实际大小:
printf("paddr_t size: %d, pointer size: %d\n",
sizeof(paddr_t), sizeof(unsigned int *));
你得到了什么?
<强>更新强>
ARM是32位架构,因此您尝试将64位整数转换为32位指针,而编译器不喜欢它!
如果您确定paddr_t中的值适合32位指针,您可以先将其转换为int
:
unsigned int *p = (unsigned int *)(int)addrs;
答案 2 :(得分:0)
我不确定我理解这个问题。
“我想访问硬件寄存器中地址所指向的32位数据(64位,只设置40 LSb)。”
所以你有一个64位宽的硬件寄存器,其中最不重要的40个应该被解释为内存中包含32位数据的地址?
你能试试吗
uint32_t* pointer = (*(uint64_t *) register_address) & (~0 >> 24)
uint32_t value = *pointer
虽然根据endian-ness以及编译器是否将>>
解释为逻辑或算术右移,这可能会变得更复杂。
虽然,我想问一下,
答案 3 :(得分:0)
根据你所写的,你有一个64指针,其中只有40位是指针,而指针指向一些32位大小的数据。
您的代码似乎试图将40位指针转换为32位指针。
你应该做的是在64位指针内放置相关的40位,使其保持64位指针,然后使用它来访问数据,然后你可以同样地&amp;获取数据。否则你(如错误所示)截断指针。
类似的东西(我没有64位所以我无法测试这个,但你明白了):
address = address & 0x????????????????; // use the ?s to mask off the bits you
// want to ignore
value64 = *address; // value64 is 64 bits
value32 = (int)(value64 & 0x00000000ffffffff); // if the data is in the lower
// half of value64
or
value32 = (int)((value64 & 0xffffffff00000000) > 32); // if the data is in the
// higher half of value64
在哪里?根据需要屏蔽这些位(取决于您正在使用的持久性)。
您可能还需要更改(int)强制转换以适合(您希望将其转换为数据所代表的任何32位数据类型 - 即value32的类型)。