STM32在使用Clion平台开发时调试失败 SystemClock_Config 返回 HAL_ERROR
问题记录
在尝试使用Clion在STM32平台上开发调试时,需要通过OpenOCD结合ST-Link等调试器进行烧录和调试。但通过STM32CubeMX生成代码后,发现出现以下现象:
- 程序能够正常编译并下载到开发板上,且运行符合预期。
- 调试时GDB Server能够正常连接,可以正常查看函数调用栈。但却在
SystemClock_Config函数配置参数时,调用的HAL_RCC_OscConfig等函数均返回为HAL_ERROR,而导致死循环在Error_Handler。


- OpenOCD的重置reset选项配置的为初始化init。

既然问题在正常下载时没有复现(排除硬件问题),且这段CubeMX生成代码比较成熟,出问题的可能不大。所以主要查看为什么调试会导致时钟配置有误。
根因分析

首先,STM32使用手册提到,PLL使能后,主PLL的配置参数不可更改。也就是说,重复配置PLL是不允许的。
OpenOCD 的启动流程(/usr/share/openocd/scripts/target/stm32f4x.cfg)入手分析。首先,ARM Cortex 内核限制 SWD 时钟频率不能超过内核频率的 1/6,而单片机上电后如果不做任何配置,时钟来源为 HSI 的 16MHz,这样 SWD 频率就最高是 2.666MHz。因此,如果不做时钟上的更改,OpenOCD 默认只能使用 2000kHz 的 adapter speed。
adapter speed 2000
adapter srst delay 100
if {[using_jtag]} {
jtag_ntrst_delay 100
}
reset_config srst_nogate
由于选择的重置选项是reset-init,所以,下面这行配置脚本会执行。
而如果让 OpenOCD 启动调试,为了加快 SWD 时钟,OpenOCD 会把 MCU 里面的 PLL 打开并设置到 64MHz,然后将系统时钟来源切换为 PLL.
在复位时提高系统时钟(16MHz → 64MHz),以提升调试速度。
$_TARGETNAME configure -event reset-init {
mww 0x40023804 0x08012008 ;# 配置 PLL
mww 0x40023C00 0x00000102 ;# 设置 Flash 等待状态
mmw 0x40023800 0x01000000 0 ;# 启用 PLL
sleep 10
mmw 0x40023808 0x00001000 0 ;# 配置总线分频
mmw 0x40023808 0x00000002 0 ;# 切换到 PLL 时钟
adapter speed 8000
}
那么,为什么会出现时钟不正常呢?我们分析 HAL 库设置系统时钟的流程。按照正常流程,HAL 库会启动 HSE,然后配置 PLL 参数,并将 PLL 时钟源设为 HSE,最后将系统时钟来源设置为 PLL。如果单片机上电后不做任何额外的时钟配置,这部分程序是可以正常工作的,单片机能够在正确的时钟上运行。
然而,巧合的是,启用调试器后,在运行用户代码前,系统时钟就处于已经配置 PLL 的状态。HAL 库如果检测到这种状态,则不会对 PLL 配置进行更改,只会检测现有的 PLL 配置与欲应用的配置是否相符,如果不相符,则返回 HAL_ERROR。
__weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) {
... // 初始化 HSI,HSE 等,在此省略
if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE) {
// 如果 PLL 当前不是系统时钟
if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) {
// 正常上电时,__HAL_RCC_GET_SYSCLK_SOURCE 应该返回 RCC_CFGR_SWS_HSI,从而进入这个分支
... // 对 PLL 进行配置
} else {
// 如果启动调试器,__HAL_RCC_GET_SYSCLK_SOURCE 应该返回 RCC_CFGR_SWS_PLL,就会进入这个分支
// 对 PLL 配置进行检查,如果与给定的配置不符,就返回 ERROR
pll_config = RCC->PLLCFGR;
if((READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != RCC_OscInitStruct->PLL.PLLM) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != RCC_OscInitStruct->PLL.PLLN) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != RCC_OscInitStruct->PLL.PLLP) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != RCC_OscInitStruct->PLL.PLLQ))
{
return HAL_ERROR;
}
}
}
}
后面的情况也正如开头所讲,返回错误值,卡死在错误处理函数内。
解决方法
- 调整OpenOCD的重置选项至Run,关于重置选项的用途,请参考:https://openocd.org/doc/html/Reset-Configuration.html
runLet the target runhaltImmediately halt the targetinitImmediately halt the target, and execute the reset-init script
- 在
main函数的 USER CODE 1 段内加入以下代码
int main(void)
{
/* USER CODE BEGIN 1 */
__HAL_RCC_HSI_ENABLE(); // 启用 HSI
__HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_HSI); // 切换系统时钟为 HSI
/* USER CODE END 1 */
HAL_Init();
SystemClock_Config();
// 进行其他初始化
}
参考文章
https://blog.vinkvin.com/post/96/
https://blog.t123yh.xyz:3/index.php/archives/922
STM32在使用Clion平台开发时调试失败 SystemClock_Config 返回 HAL_ERROR的更多相关文章
- 公众号第三方平台开发-aes解密失败
公众号第三方平台开发-aes解密失败 问题:本地启动项目,配置域名,测试微信公众号,系统正常运行:将项目部署到测试环境执行同样的操作,系统报错,错误异常:aes解密失败..... 调试--寻找问题-- ...
- 用C++做微信公众平台开发的后台开发时,用sha1加密验证的方法
微信公众平台开发时,须要验证消息是否来自微信server,这要用到sha1加密算法.官网上给的是php的sha函数,C++中要用到以下这个函数: 一.引入头文件: #include<openss ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(二十二):如何安装 Nuget(dll) 后使用项目源代码调试
最近碰到开发者问:我使用 nuget 安装了 Senparc.Weixin SDK,但是有一些已经封装好的过程想要调试,我又不想直接附加源代码项目,这样就没有办法同步更新了,我应该怎么办? 这其实是一 ...
- 【夯实PHP基础】php开发时遇到白页的调试方法
本文地址 分享提纲: 1. 设置报错报错级别,显示报错 2. 白页的可能原因 1.[设置报错报错级别,显示报错] php开发时,访问地址也对,但就是不出来页面,显示的是 白的页面,所以就可 ...
- NodeJs使用Express框架开发时的快速调试方法
习惯了php开发,可以直接使用echo或者var_dump()将想要查看的变量结果输出到网页查看,非常的方便.但是使用express开发时,每次修改文件后,都需要使用npm start命令重启服务,然 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十八):Web代理功能
在Senparc.Weixin.dll v4.5.7版本开始,我们提供了Web代理功能,以方便在受限制的局域网内的应用可以顺利调用接口. 有关的修改都在Senparc.Weixin/Utilities ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十七):个性化菜单接口说明
前不久微信上线了个性化菜单接口,Senparc.Weixin SDK也已经同步更新. 本次更新升级Senparc.Weixin.MP版本到v13.5.2,依赖Senparc.Weixin版本4.5.4 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(三):微信公众平台开发验证
要对接微信公众平台的"开发模式",即对接到自己的网站程序,必须在注册成功之后(见Senparc.Weixin.MP SDK 微信公众平台开发教程(一):微信公众平台注册),等待官方 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(七):解决用户上下文(Session)问题
从这篇文章中我们已经了解了微信公众平台消息传递的方式,这种方式有一个先天的缺陷:不同用户的请求都来自同一个微信服务器,这使得常规的Session无法使用(始终面对同一个请求对象,况且还有对方服务器Co ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明
上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>介绍了如何通过通用接口获取AccessToken,有了AccessToken,我们就可以来操作 ...
随机推荐
- 大数据之路Week08_day06 (Zookeeper搭建)
Zookeeper集群搭建 在本文中Zookeeper节点个数(奇数)为3个.Zookeeper默认对外提供服务的端口号2181 .Zookeeper集群内部3个节点之间通信默认使用2888:3888 ...
- go strings包
//是否包含指定的字符串中任意一个字符 有一个出现过 就返回true fmt.Println(strings.ContainsAny(s1,"glass")) //返回指定字符出现 ...
- Flink 实战之流式数据去重
系列文章 Flink 实战之 Real-Time DateHistogram Flink 实战之从 Kafka 到 ES Flink 实战之维表关联 Flink 实战之流式数据去重 流式数据是一种源源 ...
- Unity开发Hololens2—环境配置
博客地址:https://www.cnblogs.com/zylyehuo/ 配置如下: win11 专业版 Unity2018.4.26f1 / 2019.4.11f1 Hololens2 VS20 ...
- Linux系统挂载未分配硬盘空间
先查看未挂载之前的磁盘使用情况 发现磁盘使用率已经达到了96%,迫切需要扩容 查看分区情况fdisk –l 首先确保有可分配的磁盘空间 发现/dev/vda下有400多个G 的空间 所以将/dev/v ...
- linux查看分区命令和根分区扩容方法
df 查看文件系统磁盘空间的使用情况df [选项].[FILE]...当我们指定文件参数FILE时,将会显示该文件所在系统的信息-a 显示出所有的文件系统,包括大小只有0 blocks的文件系统:-h ...
- 使用 PHP cURL 实现 HTTP 请求类
类结构 创建一个 HttpRequest 类,其中包括初始化 cURL 的方法.不同类型的 HTTP 请求方法,以及一些用于处理响应头和解析响应内容的辅助方法. 初始化 cURL 首先,创建一个私有方 ...
- D常用快捷键大全(转)
Ctrl+PageUp将光标移至本屏的第一行,屏幕不滚动.Ctrl+PageDown将光标移至本屏的最后一行,屏幕不滚动.Ctrl+↓向下滚动屏幕,光标跟随滚动不出本屏.Ctrl+↑向上滚动屏幕,光标 ...
- 最火的 Python 异步 Web 框架的综合对比分析
以下是当前最火的 Python 异步 Web 框架的综合对比分析,涵盖性能.技术特性和适用场景,并补充其他值得关注的框架: 一.主流异步框架横向对比 1. FastAPI • 核心优势:基于 Star ...
- Chrome 135 版本新特性
Chrome 135 版本新特性 一.Chrome 135 版本浏览器更新 ** 1. 第三方托管账户注册迁移到 OIDC 授权码流程** Chrome 135 将账户注册的登录页面从营销网站迁移到动 ...