Arm 如何使用一次只能读取32位的方法准确读取64位寄存器值?

Arm 如何使用一次只能读取32位的方法准确读取64位寄存器值?,arm,embedded,microcontroller,low-level-io,Arm,Embedded,Microcontroller,Low Level Io,在过去的面试中遇到这个问题,但没有得到反馈 由于它是一个寄存器,我是否需要在访问寄存器之前禁用中断以防止数据损坏?考虑使用两个缓冲区,32位和64位,并将32位缓冲区发送到read32()中,并相应地将其转换为64位缓冲区。让我们假设这是little endian架构 我在repl.it上编写了一个快速示例代码(输出与寄存器值不匹配) #包括 #包括 #包括 无效读取32(uint64\u t*reg,uint32\u t*buffer){ memcpy(缓冲区,寄存器,4); } 内部主(空)

在过去的面试中遇到这个问题,但没有得到反馈

由于它是一个寄存器,我是否需要在访问寄存器之前禁用中断以防止数据损坏?考虑使用两个缓冲区,32位和64位,并将32位缓冲区发送到read32()中,并相应地将其转换为64位缓冲区。让我们假设这是little endian架构

我在repl.it上编写了一个快速示例代码(输出与寄存器值不匹配

#包括
#包括
#包括
无效读取32(uint64\u t*reg,uint32\u t*buffer){
memcpy(缓冲区,寄存器,4);
}
内部主(空){
//登记册
uint64_t reg=0xAAAAAAAAFFFFFF;
//缓冲区
uint32_t buf_32=0;
uint64_t buf_64=0;
//读LSW
read32(®,&buf_32);
buf_64 |=buf_32;//添加LSW
//阅读都市固体废物
read32(®+4,&buf_32);

buf_64 |=((uint64_t)buf_32禁用中断不会阻止可能独立于代码序列而改变的I/O寄存器改变

通常,当两个大于体系结构宽度的硬件寄存器之间需要数据一致性时,硬件数据表或参考手册将建议如何读取数据-通常通过指定寄存器必须读取的顺序,以使用使其“安全”的硬件机制

在其他情况下,该方法可能由寄存器的性质及其功能/行为决定。例如,如果您有两个32位计时器/计数器,其中一个的溢出触发另一个的增量,以形成一个64位计数器,那么显然,高阶计数器只会在低阶计数器溢出时改变。在这种情况下ase您可以简单地读取低位,然后读取高位,如果低位已包装,则重复此操作:

uint32_t low_word = 0, high_word = 0;

do
{
    low_word = *low_reg_addr ;
    high_word = *high_reg_addr ;

} while( *low_reg_addr > low_word ) ;  // If low has wrapped, re-read

uint64_t full_word = (uint64_t)high_word << 32 | low_word;
uint32低字=0,高字=0;
做
{
low_word=*low_reg_addr;
high_word=*high_reg_addr;
}while(*low_reg_addr>low_word);//如果low已包装,请重新读取

uint64\u t完整单词=(uint64\u t)high_word我认为你应该省略你的示例代码,因为你有一个问题,并且代码没有达到你期望的效果。为什么代码不起作用的问题是另一个问题。也不清楚代码如何回答这个问题。如果你不知道只问问题而不提出自己的问题,通常是最好的解决方案,以免它仅仅成为关于您的提案的讨论而不是问题的答案。您所说的术语“注册”是什么意思?可以看出面试问题会问这个问题,但您的代码不同。感谢您的明确解释。另外,do while条件,不应该是low_word!=*low_reg_addr吗?如果它是循环计数器(或更快)。(不能读取相同的值两次,永远)阅读
low1
high
low2
,并从
high
中减去1是安全的,如果
low2
low1
@RussSchultz:Good point,但它的含义不止于此。
high\u word
可能会在读取后但在重新读取low之前增加,在这种情况下,它不应该减少mented.正在研究它-感谢你发现了这个缺陷。我想问题是在你不能泛泛地问之后。然后再问关于寄存器的更多细节。在这里,你已经回答了计时器计数器寄存器的问题,这是实用编程的常用习惯用法。但是,它可能是位字段或随机数生成器(在这种情况下,您可能不关心误读)。如果是随机更改的地址,则示例代码至少需要一些东西使编译器重新读取。在随机更改指针/地址的情况下,高/低都可能更改;导致是否有适合使用的过时值?另一个示例是FIFO寄存器。每次读取实际上都会获得下一个值。如果“ter”的行为就像RAM,那么事情可能是安全的。因此,如果你不理解寄存器是如何工作的,你就不能编写代码。我想这就是面试的问题所在?
uint32_t low_word = 0, high_word = 0;

do
{
    low_word = *low_reg_addr ;
    high_word = *high_reg_addr ;

} while( *low_reg_addr > low_word ) ;  // If low has wrapped, re-read

uint64_t full_word = (uint64_t)high_word << 32 | low_word;