嵌入式STM32-C语言中__IO的含义

  • /** 
      * @brief Universal Synchronous Asynchronous Receiver Transmitter
      */
     
    typedef struct
    {
      __IO uint32_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
      __IO uint32_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
      __IO uint32_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
      __IO uint32_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
      __IO uint32_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
      __IO uint32_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
      __IO uint32_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
    } USART_TypeDef;
  • 上面这段程序是来自STM32F103库函数中的结构体定义,涉及到了符号__IO。
  • 这里__IO 表示 volatile,这是标准 C 语言中的一个修饰字core_m3.h 文件定义了这个宏:
  • /* IO definitions (access restrictions to peripheral registers) */
    /**
        \defgroup CMSIS_glob_defs CMSIS Global Defines
    
        <strong>IO Type Qualifiers</strong> are used
        \li to specify the access to peripheral variables.
        \li for automatic generation of peripheral register debug information.
    */
    #ifdef __cplusplus
      #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 */
    
    /* following defines should be used for structure members */
    #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 */
  • __IO的定义本质

    • 在 STM32 库函数中,__IO是一个宏定义,用于修饰变量,表示这个变量是一个 “输入 / 输出”(Input/Output)变量。
    • 它主要用于对硬件寄存器的访问,确保对这些变量的操作能够正确地反映到硬件上,并且能够及时获取硬件状态的变化。
    • __IO的定义与编译器和硬件的内存映射(Memory - Mapping)机制有关。在 ARM Cortex - M 系列(STM32 基于此架构)处理器中,硬件寄存器是通过内存映射的方式来访问的。这意味着硬件寄存器被映射到了特定的内存地址空间,对这些内存地址的读写操作就相当于对硬件寄存器的操作。
  • __IO的实现方式和作用原理

    • 编译器层面的作用
      • 当编译器看到__IO修饰的变量时,它会根据这个宏定义来生成特殊的指令序列,以确保对变量的读写操作能够正确地与硬件寄存器交互。
      • volatile关键字告诉编译器这个变量的值可能会在程序的控制流之外被改变(例如,被硬件中断或者其他外部设备改变),所以编译器在优化代码时不会对这个变量进行过度的优化。
      • volatile关键字可以确保每次对变量的读取都是从硬件寄存器中获取最新的值,而每次对变量的写入都能够及时地更新到硬件寄存器中。
    • 硬件交互层面的作用
      • 以 STM32 的 GPIO(通用输入输出)寄存器为例,当设置一个 GPIO 引脚为输出模式并控制其输出电平高低时,需要对相应的 GPIO 控制寄存器和数据寄存器进行操作。这些寄存器都是被定义为__IO类型的变量。
      • /** 
          * @brief General Purpose I/O
          */
        
        typedef struct
        {
          __IO uint32_t CRL;
          __IO uint32_t CRH;
          __IO uint32_t IDR;
          __IO uint32_t ODR;
          __IO uint32_t BSRR;
          __IO uint32_t BRR;
          __IO uint32_t LCKR;
        } GPIO_TypeDef;
      • GPIOC->ODR是一个__IO类型的变量,它代表了 GPIOC 端口的数据输出寄存器。
      • 当执行GPIOC->ODR = 0x0001;这样的代码时,由于__IO的存在,编译器会确保这个赋值操作能够直接将值0x0001写入到对应的硬件寄存器中,从而使得 GPIOC 端口的相应引脚输出高电平。
      • 当读取GPIOC - > IDR这个__IO变量时,编译器会从硬件寄存器中获取当前引脚的输入状态值。
  • 与普通变量的对比示例

    • 普通变量
      • 对于普通的变量,编译器在优化代码时会根据自己的规则进行一些优化。例如,如果一个变量在一个循环中没有被其他外部因素改变,编译器可能会将这个变量的值缓存起来,而不是每次都从内存中读取。这样可以提高程序的执行效率,但在与硬件寄存器交互的场景下就会出现问题。
      • 比如,定义一个普通变量int normal_variable;,在一个循环中对其进行操作:
      • for(int i = 0; i < 10; i++)
        {
            normal_variable = i;
            // 假设这里没有其他代码改变normal_variable的值
        }
      • 编译器可能会认为normal_variable的值在每次循环中除了赋值操作外没有其他改变,所以可能会将normal_variable的值存储在 CPU 的寄存器中,而不是每次都从内存中读取和写入。
    • __IO变量
      • 对于__IO变量,由于其代表的是硬件寄存器,其值随时可能被硬件改变(如外部设备的输入改变了 GPIO 引脚的状态),或者需要及时更新到硬件(如更新 GPIO 引脚的输出电平)。
      • __IO uint32_t gpio_register;这个变量代表一个 GPIO 寄存器。
      • 当读取gpio_register时,每次读取都必须从硬件寄存器获取最新的值,因为硬件状态可能随时改变。
      • 当写入gpio_register时,写入操作必须立即更新到硬件寄存器,以确保硬件能够按照程序的要求进行操作。所以编译器不会对__IO变量进行像普通变量那样的过度优化,以保证与硬件的正确交互。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魂兮-龙游

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值