I am currently using a library which heavily uses LOG()
functions, which
requires to output text on printf()
or one of its derivative. As I am also
evaluating ST’s HAL, I tried to use it instead of the low level putc()
function.
First, we need to be able to use printf()
in combination with
HAL_UART_Transmit()
.
For that, a small trick called
variadic functions is
required, it allows passing multiple arguments to our function. The other trick
is vprintf()
which is a printf()
with variadic args input and char*
output.
Two functions are implemented to be able to match the library Log prototype:
void logE(const char* fmt, ...)
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#define PRINT_BUFFER_SIZE 100
/** Custom printf function in order to use HAL_UART_Transmit()
* @param *fmt String to print
* @param argp Parameters list
*/
void HAL_printf_valist(const char *fmt, va_list argp) {
char string[PRINT_BUFFER_SIZE];
if (vsprintf(string, fmt, argp) > 0) {
HAL_UART_Transmit(&HAL_PRINT_UART, (uint8_t*)string, strlen(string), HAL_MAX_DELAY); // send message via UART
} else {
HAL_UART_Transmit(&HAL_PRINT_UART, (uint8_t*)"E - Print\n", 14, HAL_MAX_DELAY);
}
}
/** Custom printf function, only translate to va_list arg HAL_UART.
* @param *fmt String to print
* @param ... Data
*/
void HAL_printf(const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
HAL_printf_valist(fmt, argp);
va_end(argp);
}
Now serial printf()
can be used with a simple HAL_printf("Test: %d", value);
call.
And now the implementation of logI()
and logE()
is obvious:
/** Generic LOG procedure
* @param Log level
* @param *fmt String to print
* @param argp Parameters list
*/
static void log(uint8_t level, const char *fmt, va_list argp) {
HAL_printf("%c - ", level);
HAL_printf_valist(fmt, argp);
}
/** LOG procedure - Info
* @param *fmt String to print
* @param ... Parameters list
*/
void logI(const char* fmt, ...) {
va_list argp;
va_start(argp, fmt);
log('I', fmt, argp);
va_end(argp);
}
/** LOG procedure - Error
* @param *fmt String to print
* @param .. Parameters list
*/
void logE(const char* fmt, ...) {
va_list argp;
va_start(argp, fmt);
log('E', fmt, argp);
va_end(argp);
}
Notes:
- If you want to display floats with
%f
and you use GNU ARM provided by OpenSTM32, the flag-u _printf_float
must be added to linker options otherwise the data will be only whitespaces. - The main drawback of this method is the size of the char* buffer defined by
PRINT_BUFFER_SIZE
, you have to be sure that it is big enough for all your strings.
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email