BlueSCSI_log.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include "BlueSCSI_log.h"
  2. #include "BlueSCSI_config.h"
  3. #include "BlueSCSI_platform.h"
  4. const char *g_log_firmwareversion = BLUESCSI_FW_VERSION " " __DATE__ " " __TIME__;
  5. bool g_log_debug = true;
  6. // This memory buffer can be read by debugger and is also saved to log.txt
  7. #define LOGBUFMASK (LOGBUFSIZE - 1)
  8. // The log buffer is in special uninitialized RAM section so that it is not reset
  9. // when soft rebooting or jumping from bootloader.
  10. uint32_t g_log_magic;
  11. char g_logbuffer[LOGBUFSIZE + 1];
  12. uint32_t g_logpos;
  13. void log_raw(const char *str)
  14. {
  15. // Keep log from reboot / bootloader if magic matches expected value
  16. if (g_log_magic != 0xAA55AA55)
  17. {
  18. g_log_magic = 0xAA55AA55;
  19. g_logpos = 0;
  20. }
  21. const char *p = str;
  22. while (*p)
  23. {
  24. g_logbuffer[g_logpos & LOGBUFMASK] = *p++;
  25. g_logpos++;
  26. }
  27. // Keep buffer null-terminated
  28. g_logbuffer[g_logpos & LOGBUFMASK] = '\0';
  29. platform_log(str);
  30. }
  31. // Log byte as hex
  32. void log_raw(uint8_t value)
  33. {
  34. const char *nibble = "0123456789ABCDEF";
  35. char hexbuf[5] = {
  36. '0', 'x',
  37. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  38. 0
  39. };
  40. log_raw(hexbuf);
  41. }
  42. // Log integer as hex
  43. void log_raw(uint32_t value)
  44. {
  45. const char *nibble = "0123456789ABCDEF";
  46. char hexbuf[11] = {
  47. '0', 'x',
  48. nibble[(value >> 28) & 0xF], nibble[(value >> 24) & 0xF],
  49. nibble[(value >> 20) & 0xF], nibble[(value >> 16) & 0xF],
  50. nibble[(value >> 12) & 0xF], nibble[(value >> 8) & 0xF],
  51. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  52. 0
  53. };
  54. log_raw(hexbuf);
  55. }
  56. // Log integer as hex
  57. void log_raw(uint64_t value)
  58. {
  59. const char *nibble = "0123456789ABCDEF";
  60. char hexbuf[19] = {
  61. '0', 'x',
  62. nibble[(value >> 60) & 0xF], nibble[(value >> 56) & 0xF],
  63. nibble[(value >> 52) & 0xF], nibble[(value >> 48) & 0xF],
  64. nibble[(value >> 44) & 0xF], nibble[(value >> 40) & 0xF],
  65. nibble[(value >> 36) & 0xF], nibble[(value >> 32) & 0xF],
  66. nibble[(value >> 28) & 0xF], nibble[(value >> 24) & 0xF],
  67. nibble[(value >> 20) & 0xF], nibble[(value >> 16) & 0xF],
  68. nibble[(value >> 12) & 0xF], nibble[(value >> 8) & 0xF],
  69. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  70. 0
  71. };
  72. log_raw(hexbuf);
  73. }
  74. // Log integer as decimal
  75. void log_raw(int value)
  76. {
  77. char decbuf[16] = {0};
  78. char *p = &decbuf[14];
  79. int remainder = (value < 0) ? -value : value;
  80. do
  81. {
  82. *--p = '0' + (remainder % 10);
  83. remainder /= 10;
  84. } while (remainder > 0);
  85. if (value < 0)
  86. {
  87. *--p = '-';
  88. }
  89. log_raw(p);
  90. }
  91. void log_raw(bytearray array)
  92. {
  93. for (size_t i = 0; i < array.len; i++)
  94. {
  95. log_raw(array.data[i]);
  96. log_raw(" ");
  97. if (i > 32)
  98. {
  99. log_raw("... (total ", (int)array.len, ")");
  100. break;
  101. }
  102. }
  103. }
  104. uint32_t log_get_buffer_len()
  105. {
  106. return g_logpos;
  107. }
  108. const char *log_get_buffer(uint32_t *startpos)
  109. {
  110. uint32_t default_pos = 0;
  111. if (startpos == NULL)
  112. {
  113. startpos = &default_pos;
  114. }
  115. // Check oldest data available in buffer
  116. uint32_t margin = 16;
  117. if (g_logpos + margin > LOGBUFSIZE)
  118. {
  119. uint32_t oldest = g_logpos + margin - LOGBUFSIZE;
  120. if (*startpos < oldest)
  121. {
  122. *startpos = oldest;
  123. }
  124. }
  125. const char *result = &g_logbuffer[*startpos & LOGBUFMASK];
  126. if ((g_logpos & LOGBUFMASK) >= (*startpos & LOGBUFMASK))
  127. {
  128. // Ok, everything has been read now
  129. *startpos = g_logpos;
  130. }
  131. else
  132. {
  133. // Buffer wraps, read to end of buffer now and start from beginning on next call.
  134. *startpos = g_logpos & (~LOGBUFMASK);
  135. }
  136. return result;
  137. }