Basic debug library

Dependents:   modem_ref_helper_for_v5_3_217 modem_ref_helper

Committer:
Jeej
Date:
Tue Apr 02 08:54:07 2019 +0000
Revision:
7:8e75991f65e5
Parent:
6:70e985e34364
Child:
8:87a867b8a129
Added RX callback

Who changed what in which revision?

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