IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32在Keil调试时能成功运行但下载就运行不了的问题 -> 正文阅读

[嵌入式]STM32在Keil调试时能成功运行但下载就运行不了的问题

记得之前在STM32上做串口终端的时候图方便,想用C库里的 printf() ,于是重载了 putc()?,也在 keil 的项目配置中勾选了 Use MicroLIB 选项。但是程序下载到STM32上之后,串口却一点反应也没有,我先是检查了时钟、GPIO配置和串口使能,发现都没问题。而且调试的时候程序正常运行,串口也正常输出。后来发现程序在调试的时候总是会在停在 BKPT 0xAB 指令处,但它又不属于用户代码,因此意识到是标准库的问题(准确来说是我自己的问题)。最后发现要使用 printf() 重载的是 fputc() 而不是 putc() 。

近来我又遇到类似问题,同样是下载后没反应,同样是调试的时候可以顺利运行,但是这回我在程序中没有使用 printf() 函数,因此起初调试的时候没有想到是标准库的问题。而后我在数次调试中看到了熟悉的身影,依旧是指令?BKPT 0xAB 。

可这次我没有使用 printf() ,怎么还会有软件断点呢?而且这次的 BKPT 是在程序刚刚开始运行的时候就出现的,比 startup 运行得还要早,这就更不可能是 printf() 的问题了。不过幸运的是,我们可以在调试洁界面的调用栈中看到当前所处的函数:_sys_command_string()

?根据 keil 网站提供的帮助文档中我们可知,_sys_command_string() 是C库中用于向 main 函数提供命令行调用参数的函数。它在堆初始化前就被执行,肯定是早于 SystemInit() 和 main() 的。

问题到这里就解决了,我虽然没有使用 printf() ,但是包含了C库 stdio.h 并且没有勾选 Use MicroLIB ,导致标准C库被调用,程序卡死在半主机模式(也就是 BKPT 软件断点等待主机调试端响应)下。解决方法也很简单,在项目配置中勾选 Use MicroLIB 然后重新编译(Rebuild)即可。

---------------------------------------------------------分割线---------------------------------------------------------

关于为何要重新编译而不是直接点编译,则又是一部血泪史了。

曾经解决 BKPT 问题的时候,还让我发现了一个新问题。这问题也算是一个 keil 的小bug吧……在项目没有勾选 Use MicroLIB 的时候点击编译,毫无疑问,只要你代码本身没问题,编译器也不会报错。可是当你回过头来选择 Use MicroLIB 的时候再次点击编译(Build)的时候,却惊讶的发现了编译器的报错:

.\Objects\xxx.axf: Error: L6218E: Undefined symbol __use_two_region_memory (referred from startup_stm32f40_41xxx.o).

.\Objects\xxxaxf: Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o).

?(奇妙不奇妙?!)

这是因为 keil 在你点击编译的时候只会编译内容有变动的部分(指预处理后的部分)。当你选择使用 MicroLIB 的时候,编译器会自动添加宏定义 __MICROLIB ,相对应的,头文件中的内容就会有所改变,导致包含了头文件的 .c 文件内容改变。

可以看到,清一色都是 .c 文件。而 startup 中处存在的条件汇编语句却没有得到预处理和汇编:

?

被抛弃的部分是堆栈的初始化处理程序,可以看出定义了??__MICROLIB 宏和没有定义时堆栈的初始化是交由不同的函数处理的。但是编译的时候没改变这里的条件汇编,结果没有初始化的程序了,因此报错“符号未定义”。解决方式同样很简单,点击重新编译即可。(想当初为了解决把startup.s 给改了,真是醉了)

(文章为个人经验,仅作自身警醒之用,如有错漏请见谅)

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:05:27  更:2022-01-30 19:06:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:24:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码