前言
在產品板子(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窗口的信息感知到。