项目场景:
在项目中调用APP_PRINTF(…)、APP_LOG(TS,VL,…)进行浮点输出时,格式符直接输出,无法正确输出浮点数。
问题描述
如下所示:
APP_PRINTF("\r\nAPP_LOG输出浮点测试:\r\n");
float test = (float)1/3;
APP_LOG(TS_OFF, VLEVEL_M,"APP_LOG test = 1/3 = %f\n\r",test);
APP_PRINTF("APP_PRINTF test = 1/3 = %f\n\r",test);
APP_PRINTF("\r\n");
实际输出如下所示:
原因分析:
跟踪APP_PRINTF和APP_LOG宏在sys_app.h中均是调用了UTIL_ADV_TRACE_COND_FSend函数
#define APP_PPRINTF(...) do{ } while( UTIL_ADV_TRACE_OK \
!= UTIL_ADV_TRACE_COND_FSend(VLEVEL_ALWAYS, T_REG_OFF, TS_OFF, __VA_ARGS__) ) /* Polling Mode */
#define APP_TPRINTF(...) do{ {UTIL_ADV_TRACE_COND_FSend(VLEVEL_ALWAYS, T_REG_OFF, TS_ON, __VA_ARGS__);} }while(0); /* with timestamp */
#define APP_PRINTF(...) do{ {UTIL_ADV_TRACE_COND_FSend(VLEVEL_ALWAYS, T_REG_OFF, TS_OFF, __VA_ARGS__);} }while(0);
#if defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 1)
#define APP_LOG(TS,VL,...) do{ {UTIL_ADV_TRACE_COND_FSend(VL, T_REG_OFF, TS, __VA_ARGS__);} }while(0);
#elif defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 0) /* APP_LOG disabled */
#define APP_LOG(TS,VL,...)
#else
#error "APP_LOG_ENABLED not defined or out of range <0,1>"
#endif /* APP_LOG_ENABLED */
在UTIL_ADV_TRACE_COND_FSend()里将格式化数据从可变参数列表写入大小缓冲区时调用了UTIL_ADV_TRACE_VSNPRINTF()宏。UTIL_ADV_TRACE_VSNPRINTF的定义位于utilities_conf.h
#define UTIL_ADV_TRACE_VSNPRINTF(...) tiny_vsnprintf_like(__VA_ARGS__) /*!< vsnprintf utilities interface to trace feature */
在stm32_tiny_vsnprintf.h中tiny_vsnprintf_like(VA_ARGS) 的描述如下:
/**
* @brief Tiny implementation of vsnprintf() like function
*
* It has been adapted so that:
* - Tiny implementation, when defining TINY_PRINTF, is available. In such as case,
* not all the format are available. Instead, only %02X, %x, %d, %u, %s and %c are available.
* %f,, %+, %#, %- and others are excluded
* - Provide a snprintf like implementation. The size of the buffer is provided,
* and the length of the filled buffer is returned (not including the final '\0' char).
* The string may be truncated
* @param Pointer to a buffer where the resulting C-string is stored. The buffer should have a size of
* at least n characters.
* @param Maximum number of bytes to be used in the buffer. The generated string has a length of at
* most n-1, leaving space for the additional terminating null character.
* @param C string that contains a format string that follows the same specifications as format
* in printf (see printf for details).
* @param A value identifying a variable arguments list initialized with va_start.
* @retval The number of written char (note that this is different from vsnprintf()
*/
int tiny_vsnprintf_like(char *buf, const int size, const char *fmt, va_list args);
tiny_vsnprintf_like(VA_ARGS) 只实现了%02X, %x, %d, %u, %s and %c 等基本格式输出,不支持%f, %+, %#, %- 等其他格式。
解决方案:
经上分析不支持浮点输出是因为UTIL_ADV_TRACE_VSNPRINTF(…)对应tiny_vsnprintf_like格式化数据从可变参数列表写入大小缓冲区时不支持%f输出。我们将UTIL_ADV_TRACE_VSNPRINTF(…)定义为vsnprintf既可以支持。
//#define UTIL_ADV_TRACE_VSNPRINTF(...) tiny_vsnprintf_like(__VA_ARGS__) /*!< vsnprintf utilities interface to trace feature */
#define UTIL_ADV_TRACE_VSNPRINTF(...) vsnprintf(__VA_ARGS__) /*!< vsnprintf utilities interface to trace feature */
执行结果如下:
但是生成的bin文件中code原来增加了5852Byte,勾选Use MicroLIB的情况下修改前后code增加了2724Byte。