#pragma once #include #include #ifndef LOGLEVEL #define LOGLEVEL 3 #endif #define LOGGER_BUFLEN 0x100 static inline char *_do_nothing(char *dest, const char *) { return dest; } static inline char *_logger_string(char *dest, const char *src) { while (*src != '\0') *dest++ = *src++; *dest = '\0'; return dest; } static inline char *_logger_hex(char *dest, uint64_t x) { *dest++ = '0'; *dest++ = 'x'; for (int n, c = 60; c >= 0; c -= 4) { n = (x >> c) & 0xf; n += (n > 9) ? 0x37 : 0x30; *dest++ = (char)n; } *dest = '\0'; return dest; } static inline char *_logger_int(char *dest, int x) { char arr[12], *c = &arr[11]; arr[11] = '\0'; if (x < 0) *dest++ = '-', x = -x; if (x == 0) *dest++ = '0'; while (x > 0) *--c = x % 10 + '0', x /= 10; for (int i = 0; c[i] != '\0'; ++i) *dest++ = c[i]; *dest = '\0'; return dest; } static inline char *_logger_uint(char *dest, size_t x) { char arr[12], *c = &arr[11]; arr[11] = '\0'; if (x == 0) *dest++ = '0'; while (x > 0) *--c = x % 10 + '0', x /= 10; for (int i = 0; c[i] != '\0'; ++i) *dest++ = c[i]; *dest = '\0'; return dest; } static inline char *_logger_pointer(char *dest, void *x) { *dest++ = '*'; return _logger_hex(dest, (uint64_t)x); } static inline void _uart_puts_sync(const char *s) { while (*s != '\0') uart_putb_sync((const uint8_t *)s++, 1); } #define _I_HATE_C_LANG(msg) \ logger_cur = _Generic((msg), \ char * : _do_nothing, \ const char *: _do_nothing, \ default : _logger_string \ )(logger_cur, #msg " = "); \ logger_cur = _Generic((msg), \ char * : _logger_string, \ const char *: _logger_string, \ uint64_t : _logger_hex, \ int32_t : _logger_int, \ size_t : _logger_uint, \ default : _logger_pointer \ )(logger_cur, msg) #define LOG(val) { \ if (logger_cur != logger_buf) \ logger_cur = _logger_string(logger_cur, ", "); \ _I_HATE_C_LANG(val); \ } static inline uint64_t _r_sp() { uint64_t ret; asm volatile("mov %[a], sp" : [a] "=r" (ret)); return ret; } #define FLUSH(prefix) { \ _logger_hex(sp_cur, _r_sp()); \ _uart_puts_sync(sp_buf); \ _uart_puts_sync(" | "); \ _uart_puts_sync(prefix); \ _uart_puts_sync(logger_buf); \ _uart_puts_sync(ENDL); \ logger_cur = logger_buf; \ } #define CLEAN { \ logger_cur = logger_buf; \ } #if LOGLEVEL >= 0 #define ERROR(val) { \ LOG(val); \ FLUSH("[ERROR]: "); \ } #else #define ERROR(val) CLEAN #endif #if LOGLEVEL >= 1 #define INFOR(val) { \ LOG(val); \ FLUSH("[INFOR]: "); \ } #else #define INFOR(val) CLEAN #endif #if LOGLEVEL >= 2 #define DEBUG(val) { \ LOG(val); \ FLUSH("[DEBUG]: "); \ } #else // #if LOGLEVEL >= 2 #define DEBUG(val) CLEAN #endif // #if LOGLEVEL >= 2 // #define DEBUG_DTB(val) DEBUG(val) #define DEBUG_DTB(val) CLEAN // #define DEBUG_EXCEP(val) DEBUG(val) #define DEBUG_EXCEP(val) CLEAN // #define DEBUG_MEM(val) DEBUG(val) #define DEBUG_MEM(val) CLEAN // #define DEBUG_INITRD(val) DEBUG(val) #define DEBUG_INITRD(val) CLEAN // #define DEBUG_THREAD(val) DEBUG(val) #define DEBUG_THREAD(val) CLEAN #define DEBUG_SIGNAL(val) DEBUG(val) // #define DEBUG_SIGNAL(val) CLEAN extern char logger_buf[LOGGER_BUFLEN]; extern char *logger_cur; extern char sp_buf[LOGGER_BUFLEN]; extern char *sp_cur;