volatile的用法

变秃了也就变强了發表於2024-06-09

1.作用

  • 防止編譯器最佳化對該變數的訪問過程,確保每次訪問都能得到最新的值。
  • 編譯器通常會對程式碼進行最佳化,例如將變數的值儲存在暫存器中,以減少對記憶體的訪問

2.應用

場景:1.硬體暫存器 2.中斷服務程式中的變數 3.多執行緒程式中的共享變數

//stm32f407xx.h
typedef struct
{
  __IO uint32_t LISR;   /*!< DMA low interrupt status register,      Address offset: 0x00 */
  __IO uint32_t HISR;   /*!< DMA high interrupt status register,     Address offset: 0x04 */
  __IO uint32_t LIFCR;  /*!< DMA low interrupt flag clear register,  Address offset: 0x08 */
  __IO uint32_t HIFCR;  /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
} DMA_TypeDef;

//core_cm4.h
#ifdef __cplusplus  // C和C++編譯器區分一下 _I 的宏定義
  #define   __I     volatile             /*!< Defines 'read only' permissions */
#else
  #define   __I     volatile const       /*!< Defines 'read only' permissions */
#endif
#define     __O     volatile             /*!< Defines 'write only' permissions */
#define     __IO    volatile             /*!< Defines 'read / write' permissions */

/* 強呼叫於結構體成員M = member */
#define     __IM     volatile const      /*! Defines 'read only' structure member permissions */
#define     __OM     volatile            /*! Defines 'write only' structure member permissions */
#define     __IOM    volatile            /*! Defines 'read / write' structure member permissions */

3. 解釋說明

  • __O、_IO 都表示 volatile,變數訪問不可被最佳化,只是用不同識別符號來區別訪問許可權
  • __I表示輸入暫存器(只讀),不可被軟體修改,但可被硬體更新,__O表示輸出暫存器(只寫),__IO表示可讀寫暫存器
  • __I:volatile const __O:volatile    __IO:volatile
  • 輸入暫存器:例如一個溫度感測器連線到MCU,感測器的輸出連線到一個輸入暫存器,可以讀取該輸入暫存器的值獲得溫度值,當然還有狀態資訊或其他外部輸入訊號的應用場景
  • 輸出暫存器:用於向外部硬體傳送資料,典型的輸出暫存器用於控制外設、傳送資料或觸發特定的硬體操作
  • 輸入輸出暫存器:用於需要雙向資料傳輸的外設,例如GPIO、U(S)ART、I2C和SPI介面等
  • 根據作用分類可分為:狀態暫存器、控制暫存器、資料暫存器,跟MCU匯流排類似(地址匯流排、控制匯流排、資料匯流排)

相關文章