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

STM32 HAL库原子操作编译问题解决指南

STM32 HAL库原子操作编译问题解决指南(ATOMIC Undefined)

现象描述:

​ 近日在新建开发工程时,发现所用的HAL的部分文件版本已经比较老了,于是将该部分文件用新版本替换后加入到工程中。却在编译时报出了如下图所示错误

在这里插入图片描述

HAL提供的UART驱动文件中报出了ATOMIC_CLEAR_BITATOMIC_SET_BIT 的函数隐式声明警告。

原因分析:

​ 在新版本的HAL库中,部分外设(例如上述的UART等)的驱动实现底层使用到了原子操作的API,而由于种种原因我们的工程中并没有包含这部分的实现,因而在链接时链接器无法正确定位到相关实现。

在这里插入图片描述

​ 在stm32f4xx.h头文件中,可以找到普通位操作的实现,但是缺失了原子操作的实现。这也照应了上述的错误警示。

解决方案:

  • 可以在stm32f4xx_hal_confstm32f4xx_hal_def文件中,找一个位置将ATOMIC相关的API宏映射到普通的位操作API上。

在这里插入图片描述

修改后清扫工程,重新编译即可。

为什么可以这么修改?

原子操作的目的在于防止出现数据竞争现象,这常见于多核CPU。而我们常用的都是单核Cortex-M处理器,在单核的环境下,大多数寄存器操作本身具有足够的原子性,对于新版本的 HAL 库,只是使用 ATOMIC_* 前缀来更明确地表示这些操作应该是原子的。

  • 如果确实需要原子操作,可将下列代码复制到stm32f4xx_hal_confstm32f4xx_hal_def中。
#define ATOMIC_SET_BIT(REG, BIT)                             \do {                                                       \uint32_t val;                                            \do {                                                     \val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT);       \} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \} while(0)#define ATOMIC_CLEAR_BIT(REG, BIT)                           \do {                                                       \uint32_t val;                                            \do {                                                     \val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT);      \} while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \} while(0)

这段代码使用了Cortex-M处理器的硬件原子指令,拥有硬件级的原子操作性能。

LDREX

  • 从内存加载值,并标记该内存区域为独占访问。
  • 建立了一个独占监视器。

STREX

  • 尝试将值存储到内存,如果内存仍然处于独占状态(没有被其他操作修改),则存储成功并返回0。
  • 如果内存已被修改,则存储失败并返回1。如果返回非0值会重新执行整个操作,最终确保成功完成原子修改。

  • 查阅资料后发现,该问题主要集中在Keil的老ARMCC5编译器,ARMCC5基于C99标准,对原子操作的支持并不好,而ARMCC6则基于更新的C11标准,内部完整支持了原子操作。因此还有一种解决办法是将工程重新转换到ARMCC6环境下进行编译。当然,半道转换编译环境是有一定风险的,该方法我也没有试过,因此此处仅作为一个参考。

总结:

​ 新版本HAL库使用了ATOMIC_SET_BITATOMIC_CLEAR_BIT宏。若由于编译器问题或某些原因导致缺失相关原子操作的实现,对于常见的单核环境下,可直接将其进行宏映射到普通位操作上。若有需要,也可加入自身的原子操作。将编译环境(Keil IDE)由ARMCC5改换到较新的ARMCC6或可解决问题,但是需要面临代码兼容性的风险,不建议中途更换编译环境。

http://www.dtcms.com/a/606940.html

相关文章:

  • 珠海门户网站建设多少钱网站做前端
  • 建设银行征信中心网站石景山广州网站建设
  • 08.引用
  • 网站综合查询工具wordpress群聊
  • 服务器里面如何做网站怎么提交网址让百度收录
  • 福州做网站的公成都it培训机构
  • 蓝桥java蜗牛
  • 05.判断和循环
  • wordpress 制作手机站万网域名注册后如何做网站教学
  • DiT block学习
  • 武安市住房和城乡规划建设局网站wordpress下拉框插件
  • 广东东信润建设有限公司网站搜索关键词排名查询
  • fastapi 中的db.add db.comit db.flush db.refresh都是什么意思 有顺序吗
  • 网站301设置上海百度推广排名
  • 免费做店招哪个网站好新站网站推广该如何做
  • 宝安三网合一网站建设佛山外贸网站建设机构
  • 打工人日报#20251113
  • 高压直流270V电源:无人机地面起动概述
  • 华建建设集团网站网站运营方法
  • java 全景图切片处理,前端用pannellum框架加载
  • 嵌入式开发核心题全解析
  • 营销型企业网站系统模板下载重庆宣传片制作
  • IDEA多java版本切换
  • phpcms校园网站厦门网站制作软件
  • 网站推广有什么方法wordpress电影广告插件
  • 广州的一起做网站自己做的网站打不开怎么搞
  • 2025 多场景运营:用 PageAdmin+QuickSSO 搭建站群,1 套认证管 N 个站点
  • AI解锁物流:文档抽取重塑供应链效率
  • 第12篇 EntryPointNotFoundException: 无法在 DLL“onnxruntime”中找到名为“OrtGetApiBase”的入口点
  • FT8783ND1低成本5V2A电源芯片方案替代LP3783A(轻松过EMC,过认证)