今天在新移植的ucos工程上,突然发现debug进不了main函数,debug直接进入SystemInit函数,单步发现循环走汇编指令(如图一),开始时推测是中断引起的,把关联的中断处理屏蔽后,发现还是有问题,费了九牛二虎之力才将问题解决,通过调查,发现能引起此问题的原因不少,简单总结如下,希望大家遇到此类问题能快速解决。
图一
整体来说导致debug无法进入main函数或卡死的原因有以下几类:
A. 硬件问题
B. KEIL软件配置问题
C.代码本身的问题(我遇到的就是这个原因)
下面我们分类说明下。
I、硬件问题
STM32芯片有自举程序,此程序段存储在系统存储器(System Memory),而引脚BOOT0、BOOT1的状态能控制是否从System Memory进入ISP程序段(即:Bootloader,这个区域的内容在芯片出厂后就无法修改或擦除,即它是一个ROM区)。所以可以排查下硬件管脚是否正常。
BOOT0和 BOOT1这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表:
BOOT1=x BOOT0=0从用户闪存启动,这是正常的工作模式。
BOOT1=0 BOOT0=1从系统存储器启动,这种模式启动的程序功能由厂家设置。BOOT1=1 BOOTO=1 从内置 SRAM启动,这种模式可以用于调试。
II、KEIL 软件配置问题
1、KEIL是否还在使用期限内,如果注册码超过期限,重新搞一个期限就可以了。
File->License Management 打开License Management,选择 Single-User License页面,查看使用期限,如下图所示即为超过期限了,需要重新处理下了。
图二
2、确认Options配置是否有问题
菜单Flash->Configure Flash Tools 或直接在工具栏点击“Options for Target”工具打开Options for Target"XXXX"窗口。
Target页面,如下图所示的配置,要与硬件相符,如果不确定可以查询芯片的手册确认。
图三
Output页面,如下图所示的配置, 要选中Debug Information。
图四
Debug页面,如下图所示的选项要选中,并且根据硬件配置。
图五
在Debug页面,点击“Settings”按钮,打开"Contex-M Target Driver Setup"窗口页面,如下图所示的选项要勾选。
图六
在"Contex-M Target Driver Setup"窗口->FlashDownload --> Download Function选择Erase Sectors, 复选Program、Verify、Reset and Run 全勾上。
图七
在"Contex-M Target Driver Setup"窗口->Trace–> CoreClock要设对了,认为对应SysClk、Trace Enable使能上。
3、KEIL工程的路径问题
1)KEIL工程的路径,不能太长也不能太深。有的人说路径的长度有限制,所以能短就短不要太深,也不要有中文,否则debug可能会闪退。
2)KEIL的工程要经常Clear、Rebuild,尤其是文件结构发生变化时。
3)Debug断点不能太多,最好不要超过5个。
检查完了,可以重启下单片机、重启PC再试试。
III、代码问题
代码问题一般与中断、printf的重定向有关。如果上述软硬件配置都尝试过了,都没有问题,那么可以尝试单步看看是否与系统的中断有关来排查。例如SystemTick之类在的在系统启动时记得关中断。
如果与中断无关,那么检查下代码中是否用到了printf,而printf是否做了重定向。这里,我遇到的就是因为没有对printf做重定向导致的。
关于printf的重定向,一般有两种方法:
A. 微库MicroLIB ( 要勾选Target标签下的Use MicroLIB)
+ 头文件包含#include "stdio.h"
B. 头文件包含#include "stdio.h"
+ printf重定向,添加fputc()函数
注意:使用printf要避免使用 semihosting半主机模式!!!!
由于MicroLIB对是缺省 C 库的备选库,它是为了配合实现要装入到极少量内存中的深层嵌入式应用程序而存在的,而这种使用场合下,多数是没有操作系统的,故它删除了与操作系统有关的函数,并且不符合 ISO C 库标准, 不支持某些 ISO 特性;不符合 IEEE 754 二进制浮点算法标准;对 C99 的支持有限……等等,所以,一般情况下,我们不采用MicroLIB,这里我用的是B方法进行重定向。
采用B方法,需要加入以下代码,以支持printf。
// 加入以下代码,以支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
// 重定义fputc函数 如果暂时不需要,也可以直接return 0
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
重新编译即可。
参考资料:
KeilMDK配置项中Use MicroLIB是干什么的_xiayufeng520的专栏-CSDN博客
STM32程序进不了main函数奇葩现象---你不知道的原因_Psyduck_ing的博客-CSDN博客_stm32进不了main
单片机 keil调试的时候进入不了main函数_叮叮.一叮点的博客-CSDN博客_keil5调试进入不了主函数
感谢网友的慷慨分享~
如果网友有更好的解决办法或其他原因导致的debug异常以及解决方案,欢迎告诉我哈,谢谢~
转载要要说明出处哦~