【问题标题】:Best practices for designing registers into a peripheral that will be accessed by C and C++?将寄存器设计为将由 C 和 C++ 访问的外设的最佳实践?
【发布时间】:2018-10-31 23:40:10
【问题描述】:

我正在 FPGA 中设计一个串行端口外设,它的内存映射寄存器对我的处理器可见。

C/C++(我同时使用)是否保证写入内存位置不会同时导致从同一位置读取?

我问是因为读取会读回与刚刚写入不同的数据,并且因为读取有副作用(它从队列中拉下一个字节)。

我正在尝试为 TX 和 RX 数据共享一个内存位置,以最小化我的解码逻辑的大小。

相关问题:C/C++ 是否保证单个内存位置读取始终是单次读取,而不是以某种方式最终成为多次读取。长期的经验说是的,但我想知道规范是怎么说的。

注意:我总是将指向外围寄存器的指针声明为易失的,如下所示: 易失性 uint32_t * p_reg;

【问题讨论】:

  • 不,我不相信 C++ 标准可以保证任何这样的事情。您可能想阅读volatile 限定符,但我并不认为这是相关的。
  • 我认为volatile 可能保证这一点。但除此之外,我很确定它不会,因为它对抽象机器没有影响。
  • 天哪,这被否决了。这是一个很好的问题。也许这个问题可以更好地表述为“读取和写入映射到物理外围设备的位置的最佳实践”
  • @pm100,更改标题会很好,但我对将寄存器设计成外设的最佳实践更感兴趣。感谢您的建议
  • 有标准扩展iohw.h,但是我还没有看到实现它的实现......因为它是一个标准,如果你正在设计自己的接口,最好遵循任何一种的规范。在我使用 stm32 的实践中,我使用 keil's cmsis,他们使用宏并通过位操作访问位 & |`,例如 here。

标签: c++ c fpga specifications


【解决方案1】:

在 C 或 C++ 中确实没有写入内存位置这样的事情。只有代码和内存,编译器决定是读取还是写入内存,以使代码执行它认为必要的代码需要执行的操作。您的平台可能让volatile 做您想做的事,也可能不做,但这是一个特定于平台的问题。

如果您编写 j=1; 并且您有一个平台,其中除零以外的常量很昂贵,但增量很便宜,如果需要,实现可以随意将其视为 j=0; ++j;。

在现实世界中甚至出现过看起来像纯读取的操作实际上写入内存的情况。 C 和 C++ 标准中都没有禁止这一点。

您可以在volatile 附近查看编译器的文档,看看它是否满足您的需求。如果没有,请查看内联汇编代码。如果在您的平台上这样做是明智的,那么体面的编译器应该提供一个很好的方法来做到这一点。

【讨论】:

  • 没有任何保证,我想知道嵌入式系统曾经是如何工作的。
  • @NXT 有几种方法。最常见的是使用平台提供的函数或宏,通常通过内联汇编代码,保证提供您想要的行为。一些平台对volatile 或“超级易失”的特殊类型具有特定于平台的保证,并保证您需要特定的东西。显然,人们想要制作可用的平台,因此他们试图为您提供简单的方法来获得您可能需要的有保证的语义。 (如果这在您的平台上是合理的,您的编译器应该为您提供简单的方法来获取它。)
  • 有道理,当给定一个随机指针时,我应该编写一个宏来处理读写情况。实际上我开始认为我应该放弃将读/写语义组合到单个寄存器位置的想法。
猜你喜欢
  • 1970-01-01
  • 2012-04-22
  • 2011-08-05
  • 1970-01-01
  • 2011-10-31
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多