refactor: add options to swo_log.h, minor logging formatting fixes

This commit is contained in:
Kilian Bracher 2025-03-04 17:22:13 +01:00
parent 219a5c3a87
commit 6329859d31
4 changed files with 94 additions and 44 deletions

View File

@ -14,33 +14,57 @@
#include <stdio.h>
#define MAX_MESSAGE_LENGTH 256
#define USE_MULTIPLE_CHANNELS false // if true, each log level has its own channel (FATAL : 0, ERROR : 1, etc.)
#define USE_ANSI_ESCAPE_CODES true // if true, log messages will be colored according to their log level, and the console can be cleared
#if !USE_MULTIPLE_CHANNELS
#define DEBUG_CHANNEL 0 // channel to output messages on
#define USE_CHANNEL_MASK_VARIABLE true
#endif
#if USE_CHANNEL_MASK_VARIABLE
#define MASK_VARIABLE logging_mask // variable to store the channel mask, must be globally defined somewhere
extern volatile uint32_t MASK_VARIABLE;
#endif
enum log_level_t {
LOG_LEVEL_NOISY,
LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_FATAL,
LOG_LEVEL_ERROR,
LOG_LEVEL_FATAL
LOG_LEVEL_WARNING,
LOG_LEVEL_INFO,
LOG_LEVEL_DEBUG,
LOG_LEVEL_NOISY
};
[[maybe_unused]] static const char * const log_level_names[] = {
"\033[37m[NOISY]\033[0m ",
"\033[37m[DEBUG]\033[0m ",
"\033[97m[INFO] \033[0m ",
"\033[93m[WARN] \033[0m ",
"\033[31m[ERROR]\033[0m ",
"\033[31m[FATAL]\033[0m "
};
#if USE_ANSI_ESCAPE_CODES
[[maybe_unused]] static const char *const log_level_names[] = {
"\033[31m[FATAL]\033[0m ", "\033[31m[ERROR]\033[0m ",
"\033[93m[WARN] \033[0m ", "\033[97m[INFO] \033[0m ",
"\033[37m[DEBUG]\033[0m ", "\033[37m[NOISY]\033[0m "};
#else
[[maybe_unused]] static const char *const log_level_names[] = {
"[FATAL] ", "[ERROR] ", "[WARN] ", "[INFO] ", "[DEBUG] ", "[NOISY] "};
#endif
static inline bool __ITM_channel_enabled(uint32_t channel) {
return (ITM->TER & (1UL << channel)) != 0UL;
#if !USE_MULTIPLE_CHANNELS
#if USE_CHANNEL_MASK_VARIABLE
return ((ITM->TER & (1UL << DEBUG_CHANNEL)) != 0UL) &&
((MASK_VARIABLE & (1UL << channel)) != 0UL);
#else
channel = DEBUG_CHANNEL;
#endif
#endif
return ((ITM->TER & (1UL << channel)) != 0UL);
}
// adapted from ITM_SendChar() in the CMSIS-Core
//
// channel should be between 0 and 31
static inline uint32_t __swo_putc(uint32_t c, unsigned int channel) {
#if !USE_MULTIPLE_CHANNELS
channel = DEBUG_CHANNEL;
#endif
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
((ITM->TER & (1UL << channel)) != 0UL)) /* ITM Port enabled */
{
@ -68,15 +92,27 @@ static inline void __swo_print(unsigned int channel, const char *str) {
}
}
[[maybe_unused]]
static void debug_clear_console() {
for (int i = 0; i < LOG_LEVEL_NOISY; i++) {
#if USE_ANSI_ESCAPE_CODES
__swo_print(i, "\033[2J\033[;H"); // clear screen
#else
__swo_print(i, "\n\n\n\n\n-------------------\n\n\n\n\n"); // clear screen
#endif
}
}
#define debug_log(level, msg, ...) \
do { \
if (DEBUG_CHANNEL_ENABLED(level)) { \
char buffer[MAX_MESSAGE_LENGTH]; \
size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \
char __swo_buffer[MAX_MESSAGE_LENGTH]; \
size_t len = \
snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__); \
__swo_putc('\n', level); \
__swo_print(level, log_level_names[level]); \
__swo_print(level, buffer); \
if (len >= sizeof(buffer)) { \
__swo_print(level, __swo_buffer); \
if (len >= sizeof(__swo_buffer)) { \
__swo_print(level, " [message length exceeded] "); \
} \
} \
@ -85,13 +121,13 @@ static inline void __swo_print(unsigned int channel, const char *str) {
#define debug_log_cont(level, msg, ...) \
do { \
if (DEBUG_CHANNEL_ENABLED(level)) { \
char buffer[MAX_MESSAGE_LENGTH]; \
size_t len = snprintf(buffer, sizeof(buffer), msg, ##__VA_ARGS__); \
__swo_print(level, buffer); \
if (len >= sizeof(buffer)) { \
char __swo_buffer[MAX_MESSAGE_LENGTH]; \
size_t len = \
snprintf(__swo_buffer, sizeof(__swo_buffer), msg, ##__VA_ARGS__); \
__swo_print(level, __swo_buffer); \
if (len >= sizeof(__swo_buffer)) { \
__swo_print(level, " [message length exceeded] "); \
} \
__swo_putc('\n', level); \
} \
} while (0)

View File

@ -20,7 +20,7 @@ static const char* const HAL_Statuses[] = {"HAL_OK", "HAL_ERROR", "HAL_BUSY", "H
do { \
HAL_StatusTypeDef status = x; \
if (status != 0) { \
debug_log(LOG_LEVEL_ERROR, "@%s:%s:%d: %s failed with status %d (%s)", __FILE_NAME__, __func__, __LINE__, \
debug_log(LOG_LEVEL_ERROR, "in %s:%d@%s: %s failed with status %d (%s)", __FILE_NAME__, __LINE__, __func__,\
#x, status, \
(status < (sizeof(HAL_Statuses) / sizeof(HAL_Statuses[0]))) ? HAL_Statuses[status] : "Unknown"); \
return status; \
@ -57,9 +57,8 @@ HAL_StatusTypeDef amsReset() {
for (size_t j = 0; j < SID_GROUP_SIZE; j++) {
id |= sidbuffer[BUFFER_BMS_OFFSET(i, SID_GROUP_SIZE) + j] << (j * 8);
}
debug_log_cont(LOG_LEVEL_INFO, "0x%llx ", id);
debug_log_cont(LOG_LEVEL_INFO, "0x%lx%lx ", (uint32_t)(id >> 32), (uint32_t)(id & 0xFFFFFFFF)); //newlib does not support %llu
}
debug_log_cont(LOG_LEVEL_INFO, "\n");
}
mcuDelay(10);

View File

@ -173,17 +173,17 @@ HAL_StatusTypeDef ___writeCMD(uint16_t command, uint8_t * args, size_t arglen) {
args[1] = (command) & 0xFF;
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) {
debug_log(LOG_LEVEL_NOISY, "%lu W | %x %x ", HAL_GetTick(), args[0], args[1]);
debug_log(LOG_LEVEL_NOISY, "%lu W | %02X %02X ", HAL_GetTick(), args[0], args[1]);
//print out data bytes
for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%x ", args[4 + (i * (arglen + 2)) + j]);
if (arglen > 0) {
for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%02X ", args[BUFFER_BMS_OFFSET(i, arglen) + j]);
}
}
}
debug_log_cont(LOG_LEVEL_NOISY, "\n");
}
calculateCommandPEC(args, 4);
@ -232,17 +232,17 @@ HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen)
//TODO: check command counter?
if (DEBUG_CHANNEL_ENABLED(LOG_LEVEL_NOISY)) {
debug_log(LOG_LEVEL_NOISY, "%lu R | %x %x ", HAL_GetTick(), command >> 8, command & 0xFF);
debug_log(LOG_LEVEL_NOISY, "%lu R | %02X %02X ", HAL_GetTick(), command >> 8, command & 0xFF);
//print out data bytes
for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%x ", buffer[4 + (i * (arglen + 2)) + j]);
if (arglen > 0) {
for (size_t i = 0; i < N_BMS; i++) {
debug_log_cont(LOG_LEVEL_NOISY, "%d: ", i);
for (size_t j = 0; j < arglen; j++) {
debug_log_cont(LOG_LEVEL_NOISY, "%02X ", buffer[BUFFER_BMS_OFFSET(i, arglen) + j]);
}
}
}
debug_log_cont(LOG_LEVEL_NOISY, "\n");
}
//check data PEC

View File

@ -22,6 +22,7 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ADBMS_Driver.h"
#include "swo_log.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@ -58,7 +59,7 @@ static void MX_SPI1_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t volatile logging_mask = 0b11111; // no LOG_LEVEL_NOISY
/* USER CODE END 0 */
/**
@ -95,15 +96,29 @@ int main(void)
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
AMS_Init(&hspi1);
debug_clear_console();
debug_log(LOG_LEVEL_INFO, "Starting BMS...");
int status = -1;
while (status != ADBMS_NO_ERROR) {
status = AMS_Init(&hspi1).status;
if (status != ADBMS_NO_ERROR) {
debug_log(LOG_LEVEL_ERROR, "Failed to initialize BMS, AMS_Init returned %d", status);
HAL_Delay(2000);
}
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
AMS_Idle_Loop();
HAL_Delay(20);
status = AMS_Idle_Loop().status;
if (status != ADBMS_NO_ERROR) {
debug_log(LOG_LEVEL_ERROR, "AMS_Idle_Loop returned %d", status);
HAL_Delay(2000);
AMS_Init(&hspi1);
}
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */