Basic debug library
Dependents: modem_ref_helper_for_v5_3_217 modem_ref_helper
WizziDebug.cpp@0:1d3ed1850649, 2017-04-26 (annotated)
- Committer:
- Jeej
- Date:
- Wed Apr 26 12:31:00 2017 +0000
- Revision:
- 0:1d3ed1850649
- Child:
- 2:9e2ab0547cd0
Initial version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jeej | 0:1d3ed1850649 | 1 | #include "mbed.h" |
Jeej | 0:1d3ed1850649 | 2 | #include "rtos.h" |
Jeej | 0:1d3ed1850649 | 3 | #include "WizziDebug.h" |
Jeej | 0:1d3ed1850649 | 4 | #include "CBuffer.h" |
Jeej | 0:1d3ed1850649 | 5 | #include <stdio.h> |
Jeej | 0:1d3ed1850649 | 6 | #include <string.h> |
Jeej | 0:1d3ed1850649 | 7 | #include <stdarg.h> |
Jeej | 0:1d3ed1850649 | 8 | |
Jeej | 0:1d3ed1850649 | 9 | #define DBG_MAX_STRING_SIZE (150) |
Jeej | 0:1d3ed1850649 | 10 | |
Jeej | 0:1d3ed1850649 | 11 | static CBuffer<uint8_t, 2048> g_dbg_buf; |
Jeej | 0:1d3ed1850649 | 12 | static char g_dbg_msg[DBG_MAX_STRING_SIZE]; |
Jeej | 0:1d3ed1850649 | 13 | static Thread g_dbg_thread(osPriorityIdle, 512, NULL); |
Jeej | 0:1d3ed1850649 | 14 | static RawSerial* g_dbg_serial; |
Jeej | 0:1d3ed1850649 | 15 | static Mutex g_dbg_ressource; |
Jeej | 0:1d3ed1850649 | 16 | static Semaphore g_dbg_print(0); |
Jeej | 0:1d3ed1850649 | 17 | static uint32_t g_dbg_nb_mallocs; |
Jeej | 0:1d3ed1850649 | 18 | static PinName g_dbg_led; |
Jeej | 0:1d3ed1850649 | 19 | static uint32_t g_dbg_missing; |
Jeej | 0:1d3ed1850649 | 20 | |
Jeej | 0:1d3ed1850649 | 21 | void dbg_print_thread(); |
Jeej | 0:1d3ed1850649 | 22 | |
Jeej | 0:1d3ed1850649 | 23 | // Redefine mbed error function |
Jeej | 0:1d3ed1850649 | 24 | void error(const char* format, ...) |
Jeej | 0:1d3ed1850649 | 25 | { |
Jeej | 0:1d3ed1850649 | 26 | char buf[DBG_MAX_STRING_SIZE]; |
Jeej | 0:1d3ed1850649 | 27 | |
Jeej | 0:1d3ed1850649 | 28 | va_list args; |
Jeej | 0:1d3ed1850649 | 29 | va_start(args, format); |
Jeej | 0:1d3ed1850649 | 30 | vsprintf(buf, format, args); |
Jeej | 0:1d3ed1850649 | 31 | va_end(args); |
Jeej | 0:1d3ed1850649 | 32 | |
Jeej | 0:1d3ed1850649 | 33 | ASSERT(false, buf); |
Jeej | 0:1d3ed1850649 | 34 | } |
Jeej | 0:1d3ed1850649 | 35 | |
Jeej | 0:1d3ed1850649 | 36 | void dbg_open(PinName led, PinName tx, PinName rx) |
Jeej | 0:1d3ed1850649 | 37 | { |
Jeej | 0:1d3ed1850649 | 38 | //FPRINT("\r\n"); |
Jeej | 0:1d3ed1850649 | 39 | |
Jeej | 0:1d3ed1850649 | 40 | g_dbg_nb_mallocs = 0; |
Jeej | 0:1d3ed1850649 | 41 | g_dbg_led = led; |
Jeej | 0:1d3ed1850649 | 42 | g_dbg_missing = 0; |
Jeej | 0:1d3ed1850649 | 43 | |
Jeej | 0:1d3ed1850649 | 44 | g_dbg_serial = new RawSerial(tx, rx, 115200); |
Jeej | 0:1d3ed1850649 | 45 | g_dbg_serial->format(8, SerialBase::None, 1); |
Jeej | 0:1d3ed1850649 | 46 | |
Jeej | 0:1d3ed1850649 | 47 | g_dbg_thread.start(dbg_print_thread); |
Jeej | 0:1d3ed1850649 | 48 | } |
Jeej | 0:1d3ed1850649 | 49 | |
Jeej | 0:1d3ed1850649 | 50 | // Destructor |
Jeej | 0:1d3ed1850649 | 51 | void dbg_close( void ) |
Jeej | 0:1d3ed1850649 | 52 | { |
Jeej | 0:1d3ed1850649 | 53 | FPRINT("\r\n"); |
Jeej | 0:1d3ed1850649 | 54 | g_dbg_thread.terminate(); |
Jeej | 0:1d3ed1850649 | 55 | delete g_dbg_serial; |
Jeej | 0:1d3ed1850649 | 56 | } |
Jeej | 0:1d3ed1850649 | 57 | |
Jeej | 0:1d3ed1850649 | 58 | void dbg_set_led(PinName led, PinName dummy1, PinName dummy2) |
Jeej | 0:1d3ed1850649 | 59 | { |
Jeej | 0:1d3ed1850649 | 60 | FPRINT("\r\n"); |
Jeej | 0:1d3ed1850649 | 61 | g_dbg_led = led; |
Jeej | 0:1d3ed1850649 | 62 | } |
Jeej | 0:1d3ed1850649 | 63 | |
Jeej | 0:1d3ed1850649 | 64 | static void dbg_add_to_buf(char* msg, int size) |
Jeej | 0:1d3ed1850649 | 65 | { |
Jeej | 0:1d3ed1850649 | 66 | if(size > 0) |
Jeej | 0:1d3ed1850649 | 67 | { |
Jeej | 0:1d3ed1850649 | 68 | if (g_dbg_buf.remaining_space() < size) |
Jeej | 0:1d3ed1850649 | 69 | { |
Jeej | 0:1d3ed1850649 | 70 | #ifdef __FLUSH_IF_FULL__ |
Jeej | 0:1d3ed1850649 | 71 | // Flush just what is needed |
Jeej | 0:1d3ed1850649 | 72 | do { |
Jeej | 0:1d3ed1850649 | 73 | g_dbg_serial->putc(g_dbg_buf.pop()); |
Jeej | 0:1d3ed1850649 | 74 | } while (g_dbg_buf.remaining_space() < size); |
Jeej | 0:1d3ed1850649 | 75 | |
Jeej | 0:1d3ed1850649 | 76 | g_dbg_buf.add((uint8_t*)msg, size); |
Jeej | 0:1d3ed1850649 | 77 | #else |
Jeej | 0:1d3ed1850649 | 78 | // Discard |
Jeej | 0:1d3ed1850649 | 79 | g_dbg_missing++; |
Jeej | 0:1d3ed1850649 | 80 | #endif |
Jeej | 0:1d3ed1850649 | 81 | } |
Jeej | 0:1d3ed1850649 | 82 | else |
Jeej | 0:1d3ed1850649 | 83 | { |
Jeej | 0:1d3ed1850649 | 84 | // add |
Jeej | 0:1d3ed1850649 | 85 | g_dbg_buf.add((uint8_t*)msg, size); |
Jeej | 0:1d3ed1850649 | 86 | } |
Jeej | 0:1d3ed1850649 | 87 | |
Jeej | 0:1d3ed1850649 | 88 | // Allow printing |
Jeej | 0:1d3ed1850649 | 89 | g_dbg_print.release(); |
Jeej | 0:1d3ed1850649 | 90 | } |
Jeej | 0:1d3ed1850649 | 91 | } |
Jeej | 0:1d3ed1850649 | 92 | |
Jeej | 0:1d3ed1850649 | 93 | // Asserts and trap processor. |
Jeej | 0:1d3ed1850649 | 94 | void dbg_assert(bool test, const char* format, ...) |
Jeej | 0:1d3ed1850649 | 95 | { |
Jeej | 0:1d3ed1850649 | 96 | if (test) return; |
Jeej | 0:1d3ed1850649 | 97 | |
Jeej | 0:1d3ed1850649 | 98 | char* assert_msg = "ASSERT "; |
Jeej | 0:1d3ed1850649 | 99 | int assert_size; |
Jeej | 0:1d3ed1850649 | 100 | int size; |
Jeej | 0:1d3ed1850649 | 101 | |
Jeej | 0:1d3ed1850649 | 102 | assert_size = sprintf(g_dbg_msg, assert_msg); |
Jeej | 0:1d3ed1850649 | 103 | |
Jeej | 0:1d3ed1850649 | 104 | // expand assert string |
Jeej | 0:1d3ed1850649 | 105 | va_list args; |
Jeej | 0:1d3ed1850649 | 106 | va_start(args, format); |
Jeej | 0:1d3ed1850649 | 107 | size = vsprintf(g_dbg_msg+assert_size, format, args); |
Jeej | 0:1d3ed1850649 | 108 | va_end(args); |
Jeej | 0:1d3ed1850649 | 109 | |
Jeej | 0:1d3ed1850649 | 110 | dbg_flush(); |
Jeej | 0:1d3ed1850649 | 111 | |
Jeej | 0:1d3ed1850649 | 112 | g_dbg_serial->printf(g_dbg_msg); |
Jeej | 0:1d3ed1850649 | 113 | |
Jeej | 0:1d3ed1850649 | 114 | #ifdef __REBOOT_ON_ASSERT__ |
Jeej | 0:1d3ed1850649 | 115 | Thread::wait(1000); |
Jeej | 0:1d3ed1850649 | 116 | NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 117 | #else |
Jeej | 0:1d3ed1850649 | 118 | DigitalOut* dbg_led = NULL; |
Jeej | 0:1d3ed1850649 | 119 | if (g_dbg_led != NC) |
Jeej | 0:1d3ed1850649 | 120 | { |
Jeej | 0:1d3ed1850649 | 121 | dbg_led = new DigitalOut(g_dbg_led); |
Jeej | 0:1d3ed1850649 | 122 | } |
Jeej | 0:1d3ed1850649 | 123 | |
Jeej | 0:1d3ed1850649 | 124 | // Die... |
Jeej | 0:1d3ed1850649 | 125 | while(1) |
Jeej | 0:1d3ed1850649 | 126 | { |
Jeej | 0:1d3ed1850649 | 127 | if (dbg_led != NULL) |
Jeej | 0:1d3ed1850649 | 128 | { |
Jeej | 0:1d3ed1850649 | 129 | *(dbg_led) = !(*(dbg_led)); |
Jeej | 0:1d3ed1850649 | 130 | } |
Jeej | 0:1d3ed1850649 | 131 | Thread::wait(30); |
Jeej | 0:1d3ed1850649 | 132 | //wait_ms(30); |
Jeej | 0:1d3ed1850649 | 133 | } |
Jeej | 0:1d3ed1850649 | 134 | #endif |
Jeej | 0:1d3ed1850649 | 135 | } |
Jeej | 0:1d3ed1850649 | 136 | |
Jeej | 0:1d3ed1850649 | 137 | // Prints a message to the debug port. |
Jeej | 0:1d3ed1850649 | 138 | void dbg_print(const char* format, ...) |
Jeej | 0:1d3ed1850649 | 139 | { |
Jeej | 0:1d3ed1850649 | 140 | // Critical section |
Jeej | 0:1d3ed1850649 | 141 | g_dbg_ressource.lock(); |
Jeej | 0:1d3ed1850649 | 142 | |
Jeej | 0:1d3ed1850649 | 143 | int size; |
Jeej | 0:1d3ed1850649 | 144 | |
Jeej | 0:1d3ed1850649 | 145 | va_list args; |
Jeej | 0:1d3ed1850649 | 146 | va_start(args, format); |
Jeej | 0:1d3ed1850649 | 147 | size = vsprintf(g_dbg_msg, format, args); |
Jeej | 0:1d3ed1850649 | 148 | va_end(args); |
Jeej | 0:1d3ed1850649 | 149 | |
Jeej | 0:1d3ed1850649 | 150 | dbg_add_to_buf(g_dbg_msg, size); |
Jeej | 0:1d3ed1850649 | 151 | |
Jeej | 0:1d3ed1850649 | 152 | // End of critical section |
Jeej | 0:1d3ed1850649 | 153 | g_dbg_ressource.unlock(); |
Jeej | 0:1d3ed1850649 | 154 | } |
Jeej | 0:1d3ed1850649 | 155 | |
Jeej | 0:1d3ed1850649 | 156 | // Flush the pending debug messages. |
Jeej | 0:1d3ed1850649 | 157 | void dbg_flush( void ) |
Jeej | 0:1d3ed1850649 | 158 | { |
Jeej | 0:1d3ed1850649 | 159 | g_dbg_ressource.lock(); |
Jeej | 0:1d3ed1850649 | 160 | while(!g_dbg_buf.empty()) |
Jeej | 0:1d3ed1850649 | 161 | { |
Jeej | 0:1d3ed1850649 | 162 | g_dbg_serial->putc(g_dbg_buf.pop()); |
Jeej | 0:1d3ed1850649 | 163 | } |
Jeej | 0:1d3ed1850649 | 164 | g_dbg_ressource.unlock(); |
Jeej | 0:1d3ed1850649 | 165 | } |
Jeej | 0:1d3ed1850649 | 166 | |
Jeej | 0:1d3ed1850649 | 167 | // Prints malloc parameters. |
Jeej | 0:1d3ed1850649 | 168 | void* dbg_malloc(size_t size, const char* f, uint32_t l) |
Jeej | 0:1d3ed1850649 | 169 | { |
Jeej | 0:1d3ed1850649 | 170 | void* a; |
Jeej | 0:1d3ed1850649 | 171 | a = malloc(size); |
Jeej | 0:1d3ed1850649 | 172 | g_dbg_nb_mallocs++; |
Jeej | 0:1d3ed1850649 | 173 | dbg_print("M @%08x %dB %s:%d (%d)\r\n", (uint32_t)a, size, f, l, g_dbg_nb_mallocs); |
Jeej | 0:1d3ed1850649 | 174 | return a; |
Jeej | 0:1d3ed1850649 | 175 | } |
Jeej | 0:1d3ed1850649 | 176 | |
Jeej | 0:1d3ed1850649 | 177 | // Prints realloc parameters. |
Jeej | 0:1d3ed1850649 | 178 | void* dbg_realloc(void* p, size_t size, const char* f, uint32_t l) |
Jeej | 0:1d3ed1850649 | 179 | { |
Jeej | 0:1d3ed1850649 | 180 | void* a; |
Jeej | 0:1d3ed1850649 | 181 | dbg_assert(((uint32_t)p >= RAM_START_ADDRESS) && ((uint32_t)p < RAM_END_ADDRESS), "Trying to realloc illegal address @08x\r\n", (uint32_t)p); |
Jeej | 0:1d3ed1850649 | 182 | a = realloc(p, size); |
Jeej | 0:1d3ed1850649 | 183 | dbg_print("R @%08x->@%08x %dB %s:%d\r\n", (uint32_t)p, (uint32_t)a, size, f, l); |
Jeej | 0:1d3ed1850649 | 184 | return a; |
Jeej | 0:1d3ed1850649 | 185 | } |
Jeej | 0:1d3ed1850649 | 186 | |
Jeej | 0:1d3ed1850649 | 187 | // Prints free parameters. |
Jeej | 0:1d3ed1850649 | 188 | void dbg_free(void* p, const char* f, uint32_t l) |
Jeej | 0:1d3ed1850649 | 189 | { |
Jeej | 0:1d3ed1850649 | 190 | g_dbg_nb_mallocs--; |
Jeej | 0:1d3ed1850649 | 191 | dbg_print("F @%08x %s:%d (%d)\r\n", (uint32_t)p, f, l, g_dbg_nb_mallocs); |
Jeej | 0:1d3ed1850649 | 192 | dbg_assert(((uint32_t)p >= RAM_START_ADDRESS) && ((uint32_t)p < RAM_END_ADDRESS), "Trying to free illegal address @08x\r\n", (uint32_t)p); |
Jeej | 0:1d3ed1850649 | 193 | free(p); |
Jeej | 0:1d3ed1850649 | 194 | } |
Jeej | 0:1d3ed1850649 | 195 | |
Jeej | 0:1d3ed1850649 | 196 | void dbg_print_data(const char* before, const char* format, uint8_t* data, uint8_t length, const char* after) |
Jeej | 0:1d3ed1850649 | 197 | { |
Jeej | 0:1d3ed1850649 | 198 | // Critical section |
Jeej | 0:1d3ed1850649 | 199 | g_dbg_ressource.lock(); |
Jeej | 0:1d3ed1850649 | 200 | |
Jeej | 0:1d3ed1850649 | 201 | uint32_t total_len = 0; |
Jeej | 0:1d3ed1850649 | 202 | |
Jeej | 0:1d3ed1850649 | 203 | total_len += sprintf(g_dbg_msg, before); |
Jeej | 0:1d3ed1850649 | 204 | |
Jeej | 0:1d3ed1850649 | 205 | for (uint8_t i=0 ; i<length ; i++) |
Jeej | 0:1d3ed1850649 | 206 | { |
Jeej | 0:1d3ed1850649 | 207 | total_len += sprintf(&g_dbg_msg[total_len], format, data[i]); |
Jeej | 0:1d3ed1850649 | 208 | dbg_assert(total_len < DBG_MAX_STRING_SIZE, "Print data too long.\r\n"); |
Jeej | 0:1d3ed1850649 | 209 | } |
Jeej | 0:1d3ed1850649 | 210 | |
Jeej | 0:1d3ed1850649 | 211 | total_len += sprintf(&g_dbg_msg[total_len], after); |
Jeej | 0:1d3ed1850649 | 212 | |
Jeej | 0:1d3ed1850649 | 213 | dbg_add_to_buf(g_dbg_msg, total_len); |
Jeej | 0:1d3ed1850649 | 214 | |
Jeej | 0:1d3ed1850649 | 215 | // End of critical section |
Jeej | 0:1d3ed1850649 | 216 | g_dbg_ressource.unlock(); |
Jeej | 0:1d3ed1850649 | 217 | } |
Jeej | 0:1d3ed1850649 | 218 | |
Jeej | 0:1d3ed1850649 | 219 | |
Jeej | 0:1d3ed1850649 | 220 | // Thread for printing debug messages. |
Jeej | 0:1d3ed1850649 | 221 | void dbg_print_thread() |
Jeej | 0:1d3ed1850649 | 222 | { |
Jeej | 0:1d3ed1850649 | 223 | FPRINT("(id:0x%08x)\r\n", osThreadGetId()); |
Jeej | 0:1d3ed1850649 | 224 | |
Jeej | 0:1d3ed1850649 | 225 | while (true) |
Jeej | 0:1d3ed1850649 | 226 | { |
Jeej | 0:1d3ed1850649 | 227 | g_dbg_print.wait(); |
Jeej | 0:1d3ed1850649 | 228 | |
Jeej | 0:1d3ed1850649 | 229 | if (g_dbg_missing) |
Jeej | 0:1d3ed1850649 | 230 | { |
Jeej | 0:1d3ed1850649 | 231 | g_dbg_serial->printf("Missing %d traces!!!\r\n", g_dbg_missing); |
Jeej | 0:1d3ed1850649 | 232 | g_dbg_missing = 0; |
Jeej | 0:1d3ed1850649 | 233 | } |
Jeej | 0:1d3ed1850649 | 234 | |
Jeej | 0:1d3ed1850649 | 235 | while(!g_dbg_buf.empty()) |
Jeej | 0:1d3ed1850649 | 236 | { |
Jeej | 0:1d3ed1850649 | 237 | g_dbg_ressource.lock(); |
Jeej | 0:1d3ed1850649 | 238 | |
Jeej | 0:1d3ed1850649 | 239 | #ifdef __FORCE_LINE_INTEGRITY__ |
Jeej | 0:1d3ed1850649 | 240 | // Flush until EOL |
Jeej | 0:1d3ed1850649 | 241 | uint8_t byte; |
Jeej | 0:1d3ed1850649 | 242 | do { |
Jeej | 0:1d3ed1850649 | 243 | byte = g_dbg_buf.pop(); |
Jeej | 0:1d3ed1850649 | 244 | g_dbg_serial->putc(byte); |
Jeej | 0:1d3ed1850649 | 245 | } while (byte != '\n'); |
Jeej | 0:1d3ed1850649 | 246 | #else |
Jeej | 0:1d3ed1850649 | 247 | // Flush characters one by one |
Jeej | 0:1d3ed1850649 | 248 | g_dbg_serial->putc(g_dbg_buf.pop()); |
Jeej | 0:1d3ed1850649 | 249 | #endif |
Jeej | 0:1d3ed1850649 | 250 | |
Jeej | 0:1d3ed1850649 | 251 | g_dbg_ressource.unlock(); |
Jeej | 0:1d3ed1850649 | 252 | Thread::yield(); |
Jeej | 0:1d3ed1850649 | 253 | } |
Jeej | 0:1d3ed1850649 | 254 | |
Jeej | 0:1d3ed1850649 | 255 | } |
Jeej | 0:1d3ed1850649 | 256 | } |
Jeej | 0:1d3ed1850649 | 257 | |
Jeej | 0:1d3ed1850649 | 258 | // Reset_Handler |
Jeej | 0:1d3ed1850649 | 259 | // NMI_Handler |
Jeej | 0:1d3ed1850649 | 260 | // HardFault_Handler |
Jeej | 0:1d3ed1850649 | 261 | // MemManage_Handler |
Jeej | 0:1d3ed1850649 | 262 | // BusFault_Handler |
Jeej | 0:1d3ed1850649 | 263 | // UsageFault_Handler |
Jeej | 0:1d3ed1850649 | 264 | extern "C" void HardFault_Handler() { |
Jeej | 0:1d3ed1850649 | 265 | ASSERT(false, "Hard Fault!\r\n"); |
Jeej | 0:1d3ed1850649 | 266 | //NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 267 | } |
Jeej | 0:1d3ed1850649 | 268 | extern "C" void NMI_Handler() { |
Jeej | 0:1d3ed1850649 | 269 | ASSERT(false, "NMI Fault!\r\n"); |
Jeej | 0:1d3ed1850649 | 270 | //NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 271 | } |
Jeej | 0:1d3ed1850649 | 272 | extern "C" void MemManage_Handler() { |
Jeej | 0:1d3ed1850649 | 273 | ASSERT(false, "MemManage Fault!\r\n"); |
Jeej | 0:1d3ed1850649 | 274 | //NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 275 | } |
Jeej | 0:1d3ed1850649 | 276 | extern "C" void BusFault_Handler() { |
Jeej | 0:1d3ed1850649 | 277 | ASSERT(false, "BusFault Fault!\r\n"); |
Jeej | 0:1d3ed1850649 | 278 | //NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 279 | } |
Jeej | 0:1d3ed1850649 | 280 | extern "C" void UsageFault_Handler() { |
Jeej | 0:1d3ed1850649 | 281 | ASSERT(false, "UsageFault Fault!\r\n"); |
Jeej | 0:1d3ed1850649 | 282 | //NVIC_SystemReset(); |
Jeej | 0:1d3ed1850649 | 283 | } |