Basic debug library

Dependencies:   CBuffer

Dependents:   modem_ref_helper

Committer:
Jeej
Date:
Thu Aug 01 08:32:35 2019 +0000
Revision:
9:87d9cc850af1
Parent:
8:87a867b8a129
Updated for mbed-os 5.13

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 9:87d9cc850af1 13 static Thread g_dbg_thread(osPriorityLow, 512);
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 int assert_size;
Jeej 0:1d3ed1850649 123
Jeej 8:87a867b8a129 124 assert_size = sprintf(g_dbg_msg, "ASSERT ");
Jeej 0:1d3ed1850649 125
Jeej 0:1d3ed1850649 126 // expand assert string
Jeej 0:1d3ed1850649 127 va_list args;
Jeej 0:1d3ed1850649 128 va_start(args, format);
Jeej 4:31e1101e6999 129 vsprintf(g_dbg_msg+assert_size, format, args);
Jeej 0:1d3ed1850649 130 va_end(args);
Jeej 0:1d3ed1850649 131
Jeej 0:1d3ed1850649 132 dbg_flush();
Jeej 0:1d3ed1850649 133
Jeej 0:1d3ed1850649 134 g_dbg_serial->printf(g_dbg_msg);
Jeej 0:1d3ed1850649 135
Jeej 0:1d3ed1850649 136 #ifdef __REBOOT_ON_ASSERT__
Jeej 8:87a867b8a129 137 ThisThread::sleep_for(1000);
Jeej 0:1d3ed1850649 138 NVIC_SystemReset();
Jeej 0:1d3ed1850649 139 #else
Jeej 0:1d3ed1850649 140 DigitalOut* dbg_led = NULL;
Jeej 0:1d3ed1850649 141 if (g_dbg_led != NC)
Jeej 0:1d3ed1850649 142 {
Jeej 0:1d3ed1850649 143 dbg_led = new DigitalOut(g_dbg_led);
Jeej 0:1d3ed1850649 144 }
Jeej 0:1d3ed1850649 145
Jeej 0:1d3ed1850649 146 // Die...
Jeej 0:1d3ed1850649 147 while(1)
Jeej 0:1d3ed1850649 148 {
Jeej 0:1d3ed1850649 149 if (dbg_led != NULL)
Jeej 0:1d3ed1850649 150 {
Jeej 0:1d3ed1850649 151 *(dbg_led) = !(*(dbg_led));
Jeej 0:1d3ed1850649 152 }
Jeej 8:87a867b8a129 153 ThisThread::sleep_for(30);
Jeej 0:1d3ed1850649 154 //wait_ms(30);
Jeej 0:1d3ed1850649 155 }
Jeej 0:1d3ed1850649 156 #endif
Jeej 0:1d3ed1850649 157 }
Jeej 0:1d3ed1850649 158
Jeej 0:1d3ed1850649 159 // Prints a message to the debug port.
Jeej 0:1d3ed1850649 160 void dbg_print(const char* format, ...)
Jeej 0:1d3ed1850649 161 {
Jeej 0:1d3ed1850649 162 int size;
Jeej 0:1d3ed1850649 163
Jeej 0:1d3ed1850649 164 va_list args;
Jeej 0:1d3ed1850649 165 va_start(args, format);
Jeej 0:1d3ed1850649 166 size = vsprintf(g_dbg_msg, format, args);
Jeej 0:1d3ed1850649 167 va_end(args);
Jeej 0:1d3ed1850649 168
Jeej 0:1d3ed1850649 169 dbg_add_to_buf(g_dbg_msg, size);
Jeej 0:1d3ed1850649 170 }
Jeej 0:1d3ed1850649 171
Jeej 0:1d3ed1850649 172 // Flush the pending debug messages.
Jeej 0:1d3ed1850649 173 void dbg_flush( void )
Jeej 0:1d3ed1850649 174 {
Jeej 0:1d3ed1850649 175 g_dbg_ressource.lock();
Jeej 0:1d3ed1850649 176 while(!g_dbg_buf.empty())
Jeej 0:1d3ed1850649 177 {
Jeej 0:1d3ed1850649 178 g_dbg_serial->putc(g_dbg_buf.pop());
Jeej 0:1d3ed1850649 179 }
Jeej 0:1d3ed1850649 180 g_dbg_ressource.unlock();
Jeej 0:1d3ed1850649 181 }
Jeej 0:1d3ed1850649 182
Jeej 0:1d3ed1850649 183 // Prints malloc parameters.
Jeej 0:1d3ed1850649 184 void* dbg_malloc(size_t size, const char* f, uint32_t l)
Jeej 0:1d3ed1850649 185 {
Jeej 0:1d3ed1850649 186 void* a;
Jeej 0:1d3ed1850649 187 a = malloc(size);
Jeej 0:1d3ed1850649 188 g_dbg_nb_mallocs++;
Jeej 0:1d3ed1850649 189 dbg_print("M @%08x %dB %s:%d (%d)\r\n", (uint32_t)a, size, f, l, g_dbg_nb_mallocs);
Jeej 0:1d3ed1850649 190 return a;
Jeej 0:1d3ed1850649 191 }
Jeej 0:1d3ed1850649 192
Jeej 0:1d3ed1850649 193 // Prints realloc parameters.
Jeej 0:1d3ed1850649 194 void* dbg_realloc(void* p, size_t size, const char* f, uint32_t l)
Jeej 0:1d3ed1850649 195 {
Jeej 0:1d3ed1850649 196 void* a;
Jeej 0:1d3ed1850649 197 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 198 a = realloc(p, size);
Jeej 0:1d3ed1850649 199 dbg_print("R @%08x->@%08x %dB %s:%d\r\n", (uint32_t)p, (uint32_t)a, size, f, l);
Jeej 0:1d3ed1850649 200 return a;
Jeej 0:1d3ed1850649 201 }
Jeej 0:1d3ed1850649 202
Jeej 0:1d3ed1850649 203 // Prints free parameters.
Jeej 0:1d3ed1850649 204 void dbg_free(void* p, const char* f, uint32_t l)
Jeej 0:1d3ed1850649 205 {
Jeej 0:1d3ed1850649 206 g_dbg_nb_mallocs--;
Jeej 0:1d3ed1850649 207 dbg_print("F @%08x %s:%d (%d)\r\n", (uint32_t)p, f, l, g_dbg_nb_mallocs);
Jeej 0:1d3ed1850649 208 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 209 free(p);
Jeej 0:1d3ed1850649 210 }
Jeej 0:1d3ed1850649 211
Jeej 0:1d3ed1850649 212 void dbg_print_data(const char* before, const char* format, uint8_t* data, uint8_t length, const char* after)
Jeej 0:1d3ed1850649 213 {
Jeej 0:1d3ed1850649 214 uint32_t total_len = 0;
Jeej 0:1d3ed1850649 215
Jeej 0:1d3ed1850649 216 total_len += sprintf(g_dbg_msg, before);
Jeej 0:1d3ed1850649 217
Jeej 0:1d3ed1850649 218 for (uint8_t i=0 ; i<length ; i++)
Jeej 0:1d3ed1850649 219 {
Jeej 0:1d3ed1850649 220 total_len += sprintf(&g_dbg_msg[total_len], format, data[i]);
Jeej 0:1d3ed1850649 221 dbg_assert(total_len < DBG_MAX_STRING_SIZE, "Print data too long.\r\n");
Jeej 0:1d3ed1850649 222 }
Jeej 0:1d3ed1850649 223
Jeej 0:1d3ed1850649 224 total_len += sprintf(&g_dbg_msg[total_len], after);
Jeej 0:1d3ed1850649 225
Jeej 0:1d3ed1850649 226 dbg_add_to_buf(g_dbg_msg, total_len);
Jeej 0:1d3ed1850649 227 }
Jeej 0:1d3ed1850649 228
Jeej 0:1d3ed1850649 229
Jeej 0:1d3ed1850649 230 // Thread for printing debug messages.
Jeej 0:1d3ed1850649 231 void dbg_print_thread()
Jeej 0:1d3ed1850649 232 {
Jeej 0:1d3ed1850649 233 FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:1d3ed1850649 234
Jeej 0:1d3ed1850649 235 while (true)
Jeej 0:1d3ed1850649 236 {
Jeej 9:87d9cc850af1 237 g_dbg_print.acquire();
Jeej 0:1d3ed1850649 238
Jeej 0:1d3ed1850649 239 if (g_dbg_missing)
Jeej 0:1d3ed1850649 240 {
Jeej 0:1d3ed1850649 241 g_dbg_serial->printf("Missing %d traces!!!\r\n", g_dbg_missing);
Jeej 0:1d3ed1850649 242 g_dbg_missing = 0;
Jeej 0:1d3ed1850649 243 }
Jeej 0:1d3ed1850649 244
Jeej 0:1d3ed1850649 245 while(!g_dbg_buf.empty())
Jeej 0:1d3ed1850649 246 {
Jeej 0:1d3ed1850649 247 g_dbg_ressource.lock();
Jeej 0:1d3ed1850649 248
Jeej 0:1d3ed1850649 249 #ifdef __FORCE_LINE_INTEGRITY__
Jeej 0:1d3ed1850649 250 // Flush until EOL
Jeej 0:1d3ed1850649 251 uint8_t byte;
Jeej 0:1d3ed1850649 252 do {
Jeej 0:1d3ed1850649 253 byte = g_dbg_buf.pop();
Jeej 0:1d3ed1850649 254 g_dbg_serial->putc(byte);
Jeej 9:87d9cc850af1 255 } while (byte != '\n' && !g_dbg_buf.empty());
Jeej 0:1d3ed1850649 256 #else
Jeej 0:1d3ed1850649 257 // Flush characters one by one
Jeej 0:1d3ed1850649 258 g_dbg_serial->putc(g_dbg_buf.pop());
Jeej 0:1d3ed1850649 259 #endif
Jeej 0:1d3ed1850649 260
Jeej 0:1d3ed1850649 261 g_dbg_ressource.unlock();
Jeej 8:87a867b8a129 262 ThisThread::yield();
Jeej 0:1d3ed1850649 263 }
Jeej 0:1d3ed1850649 264 }
Jeej 0:1d3ed1850649 265 }
Jeej 0:1d3ed1850649 266
Jeej 7:8e75991f65e5 267 void dbg_set_rx_callback(void (*rx_isr)(char c))
Jeej 7:8e75991f65e5 268 {
Jeej 7:8e75991f65e5 269 g_dbg_rx_callback = rx_isr;
Jeej 7:8e75991f65e5 270 }