首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >外围读与RAM读+ RAM写

外围读与RAM读+ RAM写
EN

Stack Overflow用户
提问于 2022-03-02 13:41:22
回答 1查看 64关注 0票数 1

我在用IOs调试关键代码时遇到了一个难题:

这两种功能之间最快的是什么?

我的CPU将在哪个功能中花费更少的时间?

答: CPU读取外设寄存器并写入外设寄存器。

代码语言:javascript
复制
void d_toggle_pin(void)
{ 
  NRF_P1->OUT ^= 1 << Debug_Pin; 
}

B: CPU读取RAM变量并写入外围寄存器+写入RAM变量

代码语言:javascript
复制
void d_toggle_pin(void)
{ 
  static byte pin_state = 0;
  if(pin_state) 
  { 
    NRF_P1->OUTCLR = 1U << Debug_Pin;  
    pin_state = 0;
  }
  else
  { 
    NRF_P1->OUTSET = 1U << Debug_Pin;  
    pin_state = 1;
  }
}

我正在使用nrf52840 (皮质M4 CPU),但是不管实现如何,答案可能是相同的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-02 14:36:31

TL;DR:第一个版本表现更好。

在性能方面的差异是微不足道的。皮层M3和更高版本有简单的分支预测和流水线,但是这不会对这里的简单代码产生很大的影响。当然,第二个版本在分支预测器上可能会稍微粗糙一点,因为它们是两个单独的内存映射寄存器,但两者之间的差别是可以忽略不计的。

如果您坚持将它们进行比较,那么下面是gcc ARM non-eabi -O3的一个小基准,在这里,我替换了寄存器名,并将“调试引脚”作为硬编码常量:https://godbolt.org/z/88vn1EqKj。对分支进行了优化,但第一个版本的性能仍略好一些。

然而,您在这里的首要任务应该是功能和可读性。这两种功能都可以,但如果我要解剖它们.

  • XOR版本的优点是,XOR是一种习惯的切换方式,所以它是可读的。您还可以保证代码始终与实际的寄存器值同步,以防发生问题。

  • XOR版本的缺点是,对硬件寄存器进行读-修改-写访问有时是有问题的,因为它带来了副作用,在某些情况下也可能导致重入问题。因此,与其使用寄存器值作为XOR的占位符,我认为另一个单独跟踪端口并只执行写访问的版本是可以的。

其他值得注意的事项:

1 << ...在C中总是错误的,您几乎可以肯定永远不要移动有符号的int,这是整数常量1的类型。例如,1 << 31调用未定义的行为。始终使用1u

为这样一个非常基本的事情编写包装函数,比如设置/清除/切换GPIO引脚已经做了上百次了.没有人能够编写比以下更容易阅读的函数包装器:

  • reg |= mask (set)
  • reg &= ~mask (clear)
  • reg ^= mask; (toggle)

这是惯用的、超快的、超可读的C代码,可以100%的C程序员理解。在查看了数百个失败的、臃肿的GPIO HALs之后,我会自信地说,抽象简单的GPIO可以而且只会导致膨胀。我自己也写了不少这样的书,这总是个错误。

(对于带有一系列路由寄存器、中断处理、奇怪的状态标志等更复杂的GPIO,那么无论如何都要编写一个HAL和一个驱动程序。但并不是为了做简单的端口I/O)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71323728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档