愛伊米

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

M3,M4核心都支援硬體位帶操作,M7核心不支援。

硬體位帶操作優勢

優勢1:

比如我們在地址0x2000 0000定義了一個變數unit8_t  a, 如果我們要將此變數的bit0清零,而其它bit不變。

a & = ~0x01

這個過程就需要讀變數a,修改bit0,然後重新賦值給變數a,也就是讀 - 修改 - 寫經典三部曲,如果我們使用硬體位帶就可以一步就完成,也就是所謂的原子操作,優勢是不用擔心中斷或者RTOS任務打斷。

優勢2:

操作便捷,適合用於需要頻繁操作修改的場合,移植性強。不頻繁的直接標準庫,LL庫或者HAL庫配置即可。

背景知識

知道不知道都沒有關係,不影響我們使用硬體位帶,可以直接看後面案例的操作方法,完全不需要使用者去了解。

位帶操作就是對變數每個bit的操作,以M4核心的STM32F4為例:

1。 將1MB地址範圍 0x20000000-0x200FFFFF

對映到32MB空間範圍0x22000000 -  0x23FFFFFF ——> 這個對應STM32F4的通用RAM空間。

也就是說1MB空間每個bit都拓展為32bit來訪問控制:

0x20000000地址的位元組變數 bit0 對映到0x22000000來控制。

0x20000000地址的位元組變數 bit1對映到0x22000004來控制。

0x20000000地址的位元組變數 bit2對映到0x22000008來控制。

……。。。。依次類推

對映到32MB空間範圍0x42000000 -  0x43FFFFFF ——> 這個對應STM32F4的外設空間。

同樣也是1MB空間每個bit都拓展為32bit來訪問控制:

(3)舉例,比如訪問0x2000 0010地址裡面位元組變數的bit2

那麼實際要訪問的就是:

透過對地址空間0x22000208 進行賦值為0x01就表示bit2置位,賦值為0x00就表示bit2清零,對這個地址空間讀取操作就可以反應bit2的數值。

超簡單實現方案和四個經典方案

這種硬體未帶讓使用者去使用非常不方便,還需要倒騰地址計算。這裡以MDK為例,提供一種IDE支援的,直接加字尾__attribute__((bitband))即可,對於M3和M4可以直接轉換為硬體位帶實現。

案例1:超簡單控制RAM空間變數:

定義:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

我們定義了一個8bit的變數tTestVar,控制每個bit的方法如下:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

看彙編,已經修改為硬體位帶:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

案例2:超簡單控制GPIO輸入輸出暫存器:

GPIO裡面最常用的就是輸入輸出。GPIO輸入暫存器定義如下,每個bit控制一個IO引腳。

我們軟體定義如下:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

GPIO輸入暫存器定義如下:

我們軟體定義如下:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

實際操作效果動態,注意看除錯狀態暫存器變化,控制GPIOA的PIN0到PIN3:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

案例3:超方便的暫存器修改

比如定時器TIM1的CR暫存器:

我們的定義如下:

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

實際操作動態效果,注意看除錯狀態暫存器變化,設定TIM1 CR1暫存器的每個bit控制:

由於標準庫,HAL庫配置這些已經非常方便了,我們再使用這種方式意義不是很大,但對於需要頻繁操作的地方,這種方式就非常好使了,言簡意賅,移植性強,強力推薦,而且是原子操作方式,不用怕中斷打斷。

案例4:應用進階

最後我們來個進階,比如我們透過32位頻寬的FMC匯流排擴展出來32個GPIO,如果我們採用如下使用方式就非常不直觀

操作bit1 =0清零,就需要如下操作:

操作bit2和bit10置位,就需要如下操作:

這種操作會導致以後的程式碼修改非常不便,別人移植使用也非常不方便。如果我們改成如下方式,就方便太多了。

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置

比如控制AD7606的OS0引腳高電平就是

控制OS0引腳是低電平就是:

簡單易用,超方便。

M7核心為什麼不支援

M核心權威指南作者Joseph Yiu回覆:

1、Cache問題,如果SRAM所在區域開啟了讀寫Cache,使用位帶操作的話,會有資料一致性問題。

2、位帶需要匯流排鎖機制,在AHB匯流排協議中這相對容易實現,但在AXI匯流排協議中這有點混亂,並且在鎖定序列期間,它可能導致其他匯流排主控的延遲更長。

推薦一種超簡單的硬體位帶bitband操作方法,讓變數,暫存器控制,IO訪問更便捷,無需使用者計算位置