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,我们就可以来操作 ...
随机推荐
- TDH - 使用DBeaver连接InceptorSQL
TDH版本:TDH 4.3.x DBeaver版本:dbeaver-ce-23.0.4-win32.win32.x86_64 1.下载客户端(即为DBeaver连接InceptorSQL所需的驱动包) ...
- CF1793E题解
\(\text{Problem - 1793E - Codeforces}\) \(\text{*2600}\) 备注 2024.10.19 考试 T2.考场未能想出正解,找到性质但没有根据性质往 d ...
- Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
一:背景 1. 讲故事 前面跟大家分享过一篇 C# 调用 C代码引发非托管内存泄露 的文章,这是一个故意引发的正向泄露,这一篇我们从逆向的角度去洞察引发泄露的祸根代码,这东西如果在 windows 上 ...
- AWVS安装使用
AWVS安装使用 1.双击exe文件,然后点击下一步. 2.选择我接受,然后下一步. 3.选择路径(我选择的默认路径)然后下一步. 4.还是下一步. 5.设置邮箱,用户名密码,用户名12345678@ ...
- nuxt.js 使用 Typescript 在 VSCode 报错: File 'xxx/components/Logo.vue' is not a module. Vetur(2306)
nuxt.js 生成的默认文件 components/Logo.vue 源码大概如下: 1 <template> 2 <svg 3 class="NuxtLogo" ...
- Alibaba Sentinel SSRF漏洞分析(CVE-2021-44139)
Alibaba Sentinel SSRF漏洞分析(CVE-2021-44139) 一.Alibaba Sentienl 简介 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel ...
- Django实战项目-学习任务系统-发送短信通知
接着上期代码内容,继续完善优化系统功能. 本次增加发送短信通知功能,学习任务系统发布的任务,为了更加及时通知到学生用户,再原有发送邮件通知基础上,再加上手机短信通知功能. 第一步:开通短信通知服务 目 ...
- OSPF协议报文
OSPF(Open Shortest Path First,开放最短路径优先)是一种内部网关协议(Interior Gateway Protocol,IGP),用于在同一个自治系统(Autonomou ...
- 基于.NetCore开发 StarBlog 番外篇 (1) StarBlog Publisher,跨平台一键发布,DeepSeek加持的文章创作神器
前言 我一直在优化发布文章的工作流 之前的 StarBlog 已经支持文章打包上传(将 Markdown 和图片文件一并打包为 ZIP 格式上传),但还是有不少步骤,重复的次数多了,还是感觉麻烦. 为 ...
- Spring Boot的常用注解
在Spring Boot中,注解(Annotation)是核心特性之一,广泛用于配置和简化开发.以下是Spring Boot中一些常用的注解及其示例: 1. @SpringBootApplicatio ...