[原创]RTX使用printf输出后进入hardfault中断的处理方法 - 讨论
今天我用到RTX里面使用printf ,发现程序死掉了
我发现很多人遇到了这样的问题
找了网上很多的文章,说是这个是RTX的一个先天不足的问题
我发现了正点原子的 原子哥的解决方案,如下所示:
-------------------------------------------------------------------------------
产生原因:
使用库里的printf函数在输出结束后会调用__used void _mutex_acquire (OS_ID *mutex)这个方法,
但是传入的参数mutex并未进行初始化,所有内存访问地址出错。造成hardfault
解决方案:
1.修改RTX_Lib.c文件中的__used void _mutex_acquire (OS_ID *mutex)函数,在函数开始部分手动初始化互斥量。
__used void _mutex_acquire (OS_ID *mutex) {
/* Acquire a system mutex, lock stdlib resources. */
static int initialized = 0;
if (initialized == 0)
{ /* initialize the mutex */
_mutex_initialize(mutex);
initialized = 1;
}//printf使用进入硬件中断的解决方法
if (runtask_id ()) {
/* RTX running, acquire a mutex. */
mutex_wait (*mutex);
}
}
2.重定义ferror函数,因为此函数是被库中的ferro函数调用的。
int ferror(FILE *f)
{
return EOF;
}
两个方法都可以解决该问题。
----------------------------------------------------------------------------------------------------
以上的两种情况 我都使用了,但是发现 :
方法1还是有问题,在任务调度之后还是软件死掉了;
方法2 目前使用软件正常;
以下的代码可以放在 uUARTx_printf.c 中,然后把这个文件放在你的开发工程文件列表中加入编译
代码包含了 fputc重新定向
1 /* Includes ------------------------------------------------------------------*/ 2 #include "stm32f10x.h" 3 #include "stdio.h" 4 5 6 //加入以下代码,支持printf函数,而不需要选择use MicroLIB 7 #if 1 8 #pragma import(__use_no_semihosting) 9 //标准库需要的支持函数 10 struct __FILE 11 { 12 int handle; 13 14 }; 15 16 FILE __stdout; 17 18 //定义_sys_exit()以避免使用半主机模式 19 void _sys_exit(int x) 20 { 21 x = x; 22 } 23 //重定义fputc函数 24 int fputc(int ch, FILE *f) 25 { 26 27 /* 28 while((USART1->SR&0X40)==0); 29 USART1->DR = (u8) ch; 30 */ 31 //while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); //等待上次发送结束 32 //USART_SendData(USART1, (unsigned char)ch); //发送数据到串口 33 34 35 36 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} 37 USART_SendData(USART1, (unsigned char)ch); 38 while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET){} 39 40 41 return ch; 42 } 43 44 45 int ferror(FILE *f) 46 { 47 return EOF; 48 } 49 50 #endif
感谢原子哥的方法
也希望更多的人,有更好的办法解决这个问题
大家讨论解决方案