驅動器設計的一個基本問題是決定如何映射到外設寄存器。多年來,已經使用了許多不同的方法,例如建立結構來定義位圖,或者簡單地將所需的值寫入寄存器;然而在嵌入式開發中,還有一種方法是創建一個映射到外設寄存器的指針數組,這種方法提供了一種將外設寄存器分組到邏輯通道的優雅方式,并提供了一種簡單的方法來初始化外設以及訪問其數據。
指針數組方法很容易移植,可以用來創建標準的API和應用程序代碼,它們可以在不同的硬件平臺上工作,允許共享應用程序代碼。如果編寫得當,它還可以創建更容易閱讀和理解的代碼,從而使軟件維護更容易。
指針數組的概念是一種相對直接的映射到外設的方法。其思想是創建一個數組,其中數組的每個索引都是指向特定類型的外圍寄存器的指針。例如,對于具有多個GPIO端口的微控制器,將設置一個指針數組來訪問每個可用端口的方向寄存器(圖1)。將設置另一個指針數組來訪問輸入和輸出寄存器。每個寄存器類型都將與其自己的指針數組相關聯。
(圖1)
注意指針數組的聲明方式是很重要的。指針數組portsddr是一個指向可變uint16的常量指針。請注意,聲明是從右向左定義的。指向寄存器的指針是一個常量指針,但將其聲明為易失性uint16會通知編譯器,所指向的值可能會在沒有軟件交互的情況下自行改變。
嵌入式開發人員使用這種方法進行內存映射有很多好處。首先,它允許將功能相同的寄存器邏輯地組合在一起。這使得軟件工程師可以將每個外設視為MCU的一個獨立通道。例如,定時器1和定時器2可以看作是兩個不同的定時器通道。
設置每個定時器的周期寄存器只需要簡單地寫入周期指針陣列的適當通道索引。指針數組的索引變成了通道訪問索引。例如,指針數組索引0將與定時器1相關聯;指針數組索引1將與定時器2相關聯。
接下來,當外設開始看起來像通道時,創建一個抽象的方法就變得容易了,不僅可以初始化,還可以訪問每個外設數據。這允許使用一個簡單的循環來初始化每個外設(圖2)。只需使用正確的通道索引,就可以訪問外設的數據。這使得驅動程序框架不僅易于理解和重用,而且是一個抽象設備寄存器的框架。
圖2
最后,它允許開發人員為每個外設創建配置表。嵌入式開發人員可以創建一個可重用的驅動程序,將配置表作為參數,而不是總是編寫定制的初始化代碼。然后,初始化函數一次遍歷表中的一個通道,并通過指針數組初始化外設寄存器。這使得驅動程序成為一個庫模塊,一次又一次地被測試,從而產生可以加速下一個項目的經過驗證的代碼。