Skip to content

Instantly share code, notes, and snippets.

@jdek
Last active February 7, 2020 11:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdek/dc487f9a368afbe6445364449fd5ad8c to your computer and use it in GitHub Desktop.
Save jdek/dc487f9a368afbe6445364449fd5ad8c to your computer and use it in GitHub Desktop.
Serial logging helper for Arduino programs
/**
* SPDX-License-Identifier: MIT
*
* Arduino logging utility (with logging levels)
* =============================================
*
* Settings
* --------
*
* E_LEVEL: set the desired maximum logging level to be displayed, the default
* is E_TRACE.
*
* F_CRASH: function to instantly crash a program, it is used by any FATAL
* level message. This can be disabled by setting to `NOOP', the
* default is exit(1).
*
* Usage
* -----
*
* Add this into a file called `serial_logger.h' and then include the file in
* your application with:
*
* #include "serial_logger.h"
*
* Settings should be defined using `#define SETTING_NAME' *before* including
* the logging file.
*/
#ifndef _SERIAL_LOGGER
#define _SERIAL_LOGGER
/* Define log levels */
#define E_FATAL 0
#define E_ERROR 1
#define E_WARN 2
#define E_INFO 3
#define E_DEBUG 4
#define E_TRACE 5
/* Max level to show */
#ifndef E_LEVEL
#define E_LEVEL E_TRACE
#endif
#ifndef F_CRASH
#if F_CRASH == NOOP
#define F_CRASH (void)0
#else
#define F_CRASH exit(1)
#endif
#endif
#if E_LEVEL >= 0
static inline int debug_printf(int level, const char *file, int line, const char *format, ...)
__attribute__((format(printf, 3, 4))) {
int bytes = 0;
char buffer[1024];
va_list list;
switch(level) {
case E_TRACE:
Serial.print("TRACE");
break;
case E_DEBUG:
Serial.print("DEBUG");
break;
case E_INFO:
Serial.print("INFO ");
break;
case E_WARN:
Serial.print("WARN ");
break;
case E_ERROR:
Serial.print("ERROR");
break;
case E_TRACE:
default:
Serial.print("FATAL");
break;
}
bytes += 5;
Serial.print(" @ ");
Serial.print(file);
Serial.print(":");
snprintf(buffer, sizeof(buffer), "%d", line);
Serial.print(buffer);
Serial.print(": ");
bytes += 6 + strlen(file) + strlen(buffer);
va_start(list, format);
bytes += vsnprintf(buffer, sizeof(buffer), format, list);
Serial.print(buffer);
va_end(list);
if (level <= E_FATAL)
F_CRASH;
Serial.print("\n");
return bytes + 1;
}
#endif
#if E_LEVEL >= E_TRACE
#define TRACE(fmt, ...) debug_printf(E_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define TRACE_RAW(msg) Serial.print(msg)
#else
#define TRACE(fmt, ...)
#define TRACE_RAW(msg)
#endif
#if E_LEVEL >= E_DEBUG
#define DEBUG(fmt, ...) debug_printf(E_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define DEBUG_RAW(msg) Serial.print(msg)
#else
#define DEBUG(fmt, ...)
#define DEBUG_RAW(msg)
#endif
#if E_LEVEL >= E_INFO
#define INFO(fmt, ...) debug_printf(E_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define INFO_RAW(msg) Serial.print(msg)
#else
#define INFO(fmt, ...)
#define INFO_RAW(msg)
#endif
#if E_LEVEL >= E_WARN
#define WARN(fmt, ...) debug_printf(E_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define WARN_RAW(msg) Serial.print(msg)
#else
#define WARN(fmt, ...)
#define WARN_RAW(msg)
#endif
#if E_LEVEL >= E_ERROR
#define ERROR(fmt, ...) debug_printf(E_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define ERROR_RAW(msg) Serial.print(msg)
#else
#define ERROR(fmt, ...)
#define ERROR_RAW(msg)
#endif
#if E_LEVEL >= E_FATAL
#define FATAL(fmt, ...) debug_printf(E_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define FATAL_RAW(msg) Serial.print(msg)
#else
#define FATAL(fmt, ...)
#define FATAL_RAW(msg)
#endif
#endif /* _SERIAL_LOGGER */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment