簡體   English   中英

外設讀取 vs RAM 讀取 + RAM 寫入

[英]Peripheral read vs RAM read + RAM write

我正在使用 IOs 調試關鍵代碼,我遇到了一個難題:

這兩個功能之間最快的是什么?
我的 CPU 在哪個 function 花費的時間會更少?

A:CPU讀取一個外設寄存器,寫入外設寄存器

void d_toggle_pin(void)
{ 
  NRF_P1->OUT ^= 1 << Debug_Pin; 
}

B:CPU讀一個RAM變量並寫外設寄存器+寫一個RAM變量

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),但無論實現如何,答案都是一樣的

TL;DR:第一個版本表現更好。


性能方面的差異是微不足道的。 Cortex M3 及更高版本具有簡單的分支預測和流水線,但這不會對這里的這個簡單的小代碼產生太大影響。 當然,第二個版本在分支預測器上可能會稍微粗糙一些,因為它們是兩個獨立的內存映射寄存器,但差異可以忽略不計。

如果您堅持要比較它們,那么這里有一個 gcc ARM non-eabi -O3的小基准,我在其中替換了寄存器名稱並將“調試引腳”設為硬編碼常量: https://godbolt.org/z/88vn1EqKj 該分支已被優化掉,但第一個版本的性能仍然稍好一些。


然而,您在這里的首要任務應該是功能性和可讀性。 這兩個函數都可以,但如果我要剖析它們......

  • XOR 版本的優點是 XOR 是一種切換位的慣用方式,因此它是可讀的。 您還可以保證代碼始終與實際寄存器值同步,以防萬一。

  • XOR 版本的缺點是,對硬件寄存器進行讀-修改-寫訪問有時會出現問題,因為它會引入副作用,並且在某些情況下還會導致重入問題。 因此,與其將寄存器值用作 XOR 的占位符,我認為您的其他版本單獨跟蹤端口並僅執行寫訪問就可以了。


其他注意事項:

1 <<...在 C 中總是錯誤的。您幾乎可以肯定永遠不要移動 signed int ,它是 integer 常量1的類型。 例如1 << 31調用未定義的行為。 始終使用1u

為諸如設置/清除/切換 GPIO 引腳之類的非常基本的事情編寫包裝函數已經完成了數百次……並且沒有人設法編寫比這更容易閱讀的 function 包裝函數:

  • reg |= mask (設置)
  • reg &= ~mask (清除)
  • reg ^= mask; (切換)

這是慣用的、超快的、超可讀的 C 代碼,所有 C 程序員 100% 都可以輕松理解。 在查看了數百個失敗的、臃腫的 GPIO HAL 之后,我可以自信地說簡單 GPIO 的抽象可以而且只會導致臃腫。 我自己寫了很多這樣的東西,但總是出錯。

(對於帶有一堆路由寄存器、中斷處理、奇怪的狀態標志等的更復雜的 GPIO,那么一定要編寫一個 HAL 和一個驅動程序。但不是為了只做簡單的端口 I/O。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM