打印log方法和使用断言 素颜马尾好姑娘i 2022-02-24 02:06 257阅读 0赞 特此说明,这篇博客就是为了水而水,很久没写了,一方面是工作忙,一方面是最近心烦,懒得写, 感觉这种生活态度是不对滴,还是应该坚持把自己学到的点点滴滴记录下来,有点跑题了,这篇博客 即作为开水第一篇。 我们在调试程序过程中经常需要打印一些log信息,作为我们必要的调试手段,开始我是这么做的 #pragma import(__use_no_semihosting) //禁止半主机模式 //冲定义函数 int fputc(int ch, FILE *f) { while((LOG_UART->SR&0X40)==0);//循环发送 LOG_UART->DR = (u8) ch; return ch; } 然后在printf。。。。。。 如果需要删除printf,我就一个一个动手删除,不要笑话我,开始我就是这么做滴。。。。。 后来用来一个宏,如果使能就定义为printf,否则为空,这样关闭log,就不需要一个个手动删除。 但是还是不够灵活,后来看到一段代码: // Trace compilation depends on TRACE_LEVEL value #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) #define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); } #define TRACE_DEBUG_WP(...) { printf(__VA_ARGS__); } #else #define TRACE_DEBUG(...) { } #define TRACE_DEBUG_WP(...) { } #endif #if (TRACE_LEVEL >= TRACE_LEVEL_INFO) #define TRACE_INFO(...) { printf("-I- " __VA_ARGS__); } #define TRACE_INFO_WP(...) { printf(__VA_ARGS__); } #else #define TRACE_INFO(...) { } #define TRACE_INFO_WP(...) { } #endif #if (TRACE_LEVEL >= TRACE_LEVEL_WARNING) #define TRACE_WARNING(...) { printf("-W- " __VA_ARGS__); } #define TRACE_WARNING_WP(...) { printf(__VA_ARGS__); } #else #define TRACE_WARNING(...) { } #define TRACE_WARNING_WP(...) { } #endif #if (TRACE_LEVEL >= TRACE_LEVEL_ERROR) #define TRACE_ERROR(...) { printf("-E- " __VA_ARGS__); } #define TRACE_ERROR_WP(...) { printf(__VA_ARGS__); } #else #define TRACE_ERROR(...) { } #define TRACE_ERROR_WP(...) { } #endif #if (TRACE_LEVEL >= TRACE_LEVEL_FATAL) #define TRACE_FATAL(...) { printf("-F- " __VA_ARGS__); while(1); } #define TRACE_FATAL_WP(...) { printf(__VA_ARGS__); while(1); } #else #define TRACE_FATAL(...) { while(1); } #define TRACE_FATAL_WP(...) { while(1); } #endif 不同的优先级开启不同的宏,感觉很灵活,现在基本用这个。但是这个还是有不够灵活的地方,如果我的log出厂需要关闭, 现场出了问题,我需要打开,这个时候就不能简单用printf搞定了,需要用一个log服务模块。 我举个简单例子,log日志我单独占用了一个UART的TX,并且是查询发送,不是死查询,是每次发一个: static void log_tx(void) { uint8_t chTemp = 0; if(IS_BYTE_QUEUE_EMPTY(&s_tLogBuffer)){ return; } if(SET != USART_GetFlagStatus(USART3, USART_FLAG_TC)){ return; } if(DEQUEUE_BYTE(&s_tLogBuffer,&chTemp)){ if(0 != chTemp){ USART_SendData(USART3, chTemp); } } } 入队也很简单: static void log(uint8_t chTemp) { ENQUEUE_BYTE(&s_tLogBuffer,chTemp); } 使用也很简单: uartx_mode_set_txhook(&s_tUart2Parameter,log); 根据配置参数,这可以选择是否打印。 2019.04.22 最近群里有位仁兄请教uart的接受丢数问题,现象是发送5个字节的数据,会丢掉中间的几个数据。 他就感觉很奇怪,发送是没有问题的,接收是用中断模式。光看现象,我也不知道原因,于是让 这位仁兄把接收代码贴出来,看看他在中断里面都干啥了。通过分析代码,我初步找到了原因: 在接收代码里面有很多printf,于是我让他把这些都屏蔽掉,再调试,问题解决。这就是一个log 干扰正常流程的例子,具体原因是他把串口的速率设置的都一样,那么printf的时间肯定大于一个 字节接收的时间,这种情况不丢数就怪了。 2019.08.09 最近开始使用断言,感觉很方便,能够清楚的指出运行时错误行和文件名,总结如下: 1、断言是当所检查条件不满足即为false时候进入; 2、断言可以通过宏关闭和打开; 3、断言主要用于检查运行时错误; 使用: 1、包含头文件: \#include "stm32\_assert.h" #ifdef __cplusplus extern "C" { #endif /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT /** * @brief The assert_param macro is used for function's parameters check. * @param expr: If expr is false, it calls assert_failed function * which reports the name of the source file and the source * line number of the call that failed. * If expr is true, it returns no value. * @retval None */ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) /* Exported functions ------------------------------------------------------- */ void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */ #ifdef __cplusplus } #endif 2、打开宏 USE\_FULL\_ASSERT 3、实现 void assert\_failed(uint8\_t\* file, uint32\_t line); #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ printf("Wrong parameters value: file %s on line %d\r\n", file, line); while (1) { } /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 使用: assert\_param((&(ptRoutingTableItem->ptNext))); 当ptRoutingTableItem->ptNext的指针为NULL时候,进入断言。
还没有评论,来说两句吧...