前言
在产品板子(STM32F407 + ucOS-II)上, 加入printf后,用MDK单步时,必然进入HardFault.
开始怀疑是硬件问题,于是用开发板先验证程序是否写错?
后来发现是编译前勾选了微库, 不勾选微库, 就不会进入HardFault.
// 不能勾选微库(Target => Code Generation => Use MIcroLIB), 否则启动ucOS任务后,会进入HardFault
// 浮点运算选上(407支持浮点运算)
然后看printf是否能打印到MDK串行调试窗口。
先改fputc实现。
#include <stdio.h>
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
if (DEMCR & TRCENA)
{
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
/*
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
*/
}
#endif
程序跑起来后,设置正确的前提下,printf信息无法打印到MDK串行调试窗口。
然后试了开发板对应的ucOS-III工程,printf可以正常打印到MDK串行调试窗口。
结论
ucOS-II不兼容printf, 更准确的说,是不支持F407的ITM.
因为以前维护过一个F103的ucOS-II的工程,是可以正常将printf信息打到MDK调试窗口的。
本来维护工程的原则,都是要保持最小化的修改,防止带入更多的bug。
这下,不得已要将工程将ucOS-II迁移到ucOS-III去。
这样可以用MDK带着板子长时间跑, 不加断点全速跑,如果有潜在错误,可以通过printf打到MDK窗口的信息感知到。