当前位置: 首页 > news >正文

嵌入式科普(32)指向寄存器的指针变量2---可变指针

一、概述

  • 嵌入式科普(23)指向寄存器的指针变量1

    ,总结就是指向寄存器的指针要谨慎使用强制类型转换

  • 寄存器数据是易变的,通常用可变指针去访问

  • 可变指针有三种写法:

volatile int*  p;
int* volatile p;
volatile int* volatile p;

二、参考资料

https://en.cppreference.com/w/c/language/volatile
https://en.cppreference.com/w/cpp/language/cv
https://en.cppreference.com/w/c/language/const
https://learn.microsoft.com/zh-cn/cpp/cpp/const-and-volatile-pointers?view=msvc-170
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
https://zhuanlan.zhihu.com/p/423212827

三、通过int*偏移去访问寄存器

  • 通常的外设驱动库:一组外设寄存器通常是结构体,外设的实例使用结构体指针访问寄存器

  • stm32 hal库uart:USART_TypeDef *Instance;

#define     __IO    volatile             /*!< Defines 'read / write' permissions */

/**
  * @brief Universal Synchronous Asynchronous Receiver Transmitter
  */
typedef struct
{
  __IO uint32_t CR1;         /*!< USART Control register 1,                 Address offset: 0x00  */
  __IO uint32_t CR2;         /*!< USART Control register 2,                 Address offset: 0x04  */
  __IO uint32_t CR3;         /*!< USART Control register 3,                 Address offset: 0x08  */
  __IO uint32_t BRR;         /*!< USART Baud rate register,                 Address offset: 0x0C  */
  __IO uint32_t GTPR;        /*!< USART Guard time and prescaler register,  Address offset: 0x10  */
  __IO uint32_t RTOR;        /*!< USART Receiver Time Out register,         Address offset: 0x14  */
  __IO uint32_t RQR;         /*!< USART Request register,                   Address offset: 0x18  */
  __IO uint32_t ISR;         /*!< USART Interrupt and status register,      Address offset: 0x1C  */
  __IO uint32_t ICR;         /*!< USART Interrupt flag Clear register,      Address offset: 0x20  */
  __IO uint32_t RDR;         /*!< USART Receive Data register,              Address offset: 0x24  */
  __IO uint32_t TDR;         /*!< USART Transmit Data register,             Address offset: 0x28  */
  __IO uint32_t PRESC;       /*!< USART Prescaler register,                 Address offset: 0x2C  */
} USART_TypeDef;

/**
  * @brief  UART handle Structure definition
  */
typedef struct __UART_HandleTypeDef
{
  USART_TypeDef            *Instance;                /*!< UART registers base address        */

  UART_InitTypeDef         Init;                     /*!< UART communication parameters      */
  ....
} UART_HandleTypeDef;  
  • rzn2l通过int*偏移去访问定时器计数寄存器

volatile uint32_t * volatile gtp_ptr ;
volatile uint32_t * volatile ptr ;
 uint32_t smStatus1 = 0;
 uint32_t smStatus2 = 0;
 uint32_t smStatus3 = 0;
 uint32_t smStatus4 = 0;

/*******************************************************************************************************************//**
 * main() is generated by the FSP Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
#if defined(BSP_MCU_GROUP_RZN2H)
 #if (defined(BSP_CFG_CORE_CR52) && (0 == BSP_CFG_CORE_CR52))

    /* Set "1" to CA550_CTRL. */
    R_MPU_AC->CPU_CTRL |= 0x00000100;
 #endif
#endif

    /* TODO: add your own code here */
    R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
    R_GPT_Enable(&g_timer0_ctrl);
    R_GPT_Start(&g_timer0_ctrl);

    gtp_ptr = (uint32_t *)g_timer0_ctrl.p_reg;

    ptr = gtp_ptr + 0x48/4;
    while(1)
    {

        smStatus1 = ((uint32_t*)gtp_ptr)[0x48/4];

        smStatus2 = gtp_ptr[0x12];

        smStatus3 = *ptr;

        smStatus4 = *(uint32_t*)(0x90002048);
    }
}
#define     HW_EscReadByte(ByteValue, Address)          ((ByteValue) = (((UINT8 *) pEsc)[(Address)]))
  • 直接使用指针访问地址

uint32_t smStatus4 = 0;
smStatus4 = *(uint32_t*)(0x90002048);

四、优化等级和编译器版本

  • -none同volatile

  • -o1甚至更高优化等级需加volatile

  • gcc12版本以上比10.3以下版本,对volatile指针优化有不同

五、总结

  • 首先volatile修饰是为了告诉编译器

  • 访问寄存器指针需注意易变属性

  • 通过offset方式访问寄存器更要注意易变属性

  volatile int*  p;         p指向的数据是易变的
  int* volatile p;          变量p是易变的
  volatile int* volatile p; 都是易变的
  • 编译器版本优化有差异

  • volatile int* volatile p;货真价实

  • 下一节总结volatile和const

图片

相关文章:

  • 世优科技国内首家 MR 体验店开业,打造 MAS 任意门奇幻之旅
  • 基于PSO-LSTM长短期记忆神经网络的多分类预测【MATLAB】
  • IO进程 day05
  • MobileNet 改进:添加SpatialGroupEnhance 增加语义特征学习能力
  • STM32-智能小车项目
  • Python的PyTorch+CNN深度学习技术在人脸识别项目中的应用
  • #5【CVPR2024】PLACE:自适应布局语义融合
  • 强化学习笔记(一)
  • 数据同步的中间件
  • tailwindcss 前端 css 框架 无需写css 快速构建页面
  • 关于网关和ip地址怎么理解?
  • cpu、mem监控
  • 【C】初阶数据结构7 -- 树与顺序结构的二叉树(堆)
  • 【AI】模型量化--模型量化技术基础
  • 深入理解 window.postMessage:跨域通信的解决方案与实战
  • ERROR:This version of pnpm requires at least Node.js vXXX 的解决方案
  • TCPDF 任意文件读取漏洞:隐藏在 PDF 生成背后的危险
  • 方法区和堆的区别
  • echarts 环形图 指定区域从右侧中心点展开
  • 批量将手机照片修改为一寸白底证件照的方法
  • wordpress codebox/贵州二级站seo整站优化排名
  • 景安网站备案表格/百度竞价推广方法
  • 网站 百度地图/找个免费网站这么难吗
  • 常州网站建设/推广合作
  • 牡丹江建设局网站/百度的网站网址
  • wap网站 开发/房产网站建设