COSA
An Object-Oriented Platform for Arduino Programming
Debug.cpp
Go to the documentation of this file.
1 
21 #include "Debug.hh"
22 
23 Debug debug __attribute__((weak));
24 
25 extern int __heap_start, *__brkval;
26 
27 bool
29  const char* file,
30  int line,
31  const char* func)
32 {
33  if (m_dev != NULL) return (false);
34 
35  DATAEND =(int) &__heap_start;
36  DATASIZE = DATAEND - RAMSTART;
37 
38  device(dev);
39  print(PSTR("Cosa/Debug 1.0 Copyright (C) 2015\nDebug::begin:"));
40  run(file, line, func);
41  return (true);
42 }
43 
44 void
45 Debug::assert(const char* file,
46  int line,
47  const char* func,
48  str_P cond)
49 {
50  print(PSTR("Debug::assert"));
51  run(file, line, func, cond);
53  flush();
54  exit(0);
55 }
56 
57 void
58 Debug::break_at(const char* file,
59  int line,
60  const char* func,
61  str_P cond)
62 {
63  print(PSTR("Debug::break_at"));
64  run(file, line, func, cond);
65 }
66 
67 bool
69 {
70  uint16_t marker = 0xA5A5;
71  int HEAPEND = (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
72  int STACKSTART = (int) ▮
73  return (STACKSTART > HEAPEND + room);
74 }
75 
76 bool
78 {
79  if (m_dev == NULL) return (false);
80  device(NULL);
81  return (true);
82 }
83 
84 void
85 Debug::run(const char* file, int line, const char* func, str_P expr)
86 {
87  if (func != NULL) printf(PSTR(":%s:%d"), func, line);
88  if (expr != NULL) printf(PSTR(":%S"), expr);
89  if (func != NULL) println();
90 
91  uint16_t marker = 0xA5A5;
92  str_P prompt = PSTR("Debug> ");
93 
94  while (1) {
95  const size_t BUF_MAX = 32;
96  char buf[BUF_MAX];
97  memset(buf, 0, sizeof(buf));
98 
99  print(prompt);
100  while (readline(buf, sizeof(buf)) == NULL) yield();
101  size_t len = strlen(buf) - 1;
102  if (buf[len] != '\n') continue;
103  if (len == 0) continue;
104  buf[len] = 0;
105 
106  if (!strncmp_P(buf, PSTR("go"), len)) return;
107 
108 #if !defined(COSA_DEBUG_NO_BACKTRACE)
109  if (!strncmp_P(buf, PSTR("backtrace"), len)) {
110  printf(PSTR("%p:%s\n"), &marker, func);
111  do_backtrace(func);
112  continue;
113  }
114 #endif
115 
116 #if !defined(COSA_DEBUG_NO_PRINT_DATA)
117  if (!strncmp_P(buf, PSTR("data"), len)) {
118  do_print_data();
119  continue;
120  }
121 #endif
122 
123 #if !defined(COSA_DEBUG_NO_PRINT_HEAP)
124  if (!strncmp_P(buf, PSTR("heap"), len)) {
125  do_print_heap();
126  continue;
127  }
128 #endif
129 
130 #if !defined(COSA_DEBUG_NO_HELP)
131  if (!strncmp_P(buf, PSTR("help"), len)) {
132  do_help();
133  continue;
134  }
135 #endif
136 
137 #if !defined(COSA_DEBUG_NO_MEMORY_USAGE)
138  if (!strncmp_P(buf, PSTR("memory"), len)) {
139  do_memory_usage((int) &marker);
140  continue;
141  }
142 #endif
143 
144 #if !defined(COSA_DEBUG_NO_PRINT_STACK)
145  if (!strncmp_P(buf, PSTR("stack"), len)) {
146  do_print_stack((int) &marker);
147  continue;
148  }
149 #endif
150 
151 #if !defined(COSA_DEBUG_NO_PRINT_VARIABLES)
152  if (!strncmp_P(buf, PSTR("variables"), len)) {
154  continue;
155  }
156 #endif
157 
158 #if !defined(COSA_DEBUG_NO_QUIT)
159  if (!strncmp_P(buf, PSTR("quit"), len)) {
161  flush();
162  exit(0);
163  }
164 #endif
165 
166 #if !defined(COSA_DEBUG_NO_WHERE)
167  if (!strncmp_P(buf, PSTR("where"), len)) {
168  printf(PSTR("%s:%d:%s\n"), file, line, func);
169  continue;
170  }
171 #endif
172 
173 #if !defined(COSA_DEBUG_NO_LOOKUP_VARIABLES)
174  if (*buf == '?') {
175  const char* name = buf + 1;
176  if (!do_lookup_variables(name))
177  printf(PSTR("%s: unknown variable\n"), name);
178  continue;
179  }
180 #endif
181  printf(PSTR("%s: unknown command\n"), buf);
182  }
183 }
184 
185 #if !defined(COSA_DEBUG_NO_BACKTRACE)
186 void
187 Debug::do_backtrace(const char* func)
188 {
189  for (Variable* vp = m_var; vp != NULL; vp = vp->m_next) {
190  if (func != vp->m_func) {
191  func = vp->m_func;
192  printf(PSTR("%p:%s\n"), vp, vp->m_func);
193  }
194  }
195 }
196 #endif
197 
198 #if !defined(COSA_DEBUG_NO_HELP)
199 void
201 {
202  static const char help[] PROGMEM =
203 #if !defined(COSA_DEBUG_NO_LOOKUP_VARIABLES)
204  "?VARIABLE -- print variable(s)\n"
205 #endif
206 #if !defined(COSA_DEBUG_NO_BACKTRACE)
207  "backtrace -- print call stack\n"
208 #endif
209 #if !defined(COSA_DEBUG_NO_PRINT_DATA)
210  "data -- print data\n"
211 #endif
212  "go -- return to sketch\n"
213 #if !defined(COSA_DEBUG_NO_PRINT_HEAP)
214  "heap -- print heap\n"
215 #endif
216 #if !defined(COSA_DEBUG_NO_MEMORY_USAGE)
217  "memory -- print memory usage\n"
218 #endif
219 #if !defined(COSA_DEBUG_NO_QUIT)
220  "quit -- exit sketch\n"
221 #endif
222 #if !defined(COSA_DEBUG_NO_PRINT_STACK)
223  "stack -- print stack\n"
224 #endif
225 #if !defined(COSA_DEBUG_NO_PRINT_REGISTER)
226  "variables -- print variables\n"
227 #endif
228 #if !defined(COSA_DEBUG_NO_WHERE)
229  "where -- location in source code\n"
230 #endif
231  ;
232  print((str_P) help);
233 }
234 #endif
235 
236 #if !defined(COSA_DEBUG_NO_LOOKUP_VARIABLES)
237 bool
238 Debug::do_lookup_variables(const char* name)
239 {
240  bool found = false;
241  for (Variable* vp = m_var; vp != NULL; vp = vp->m_next) {
242  if (strcmp_P(name, vp->m_name) == 0) {
243  vp->print();
244  found = true;
245  }
246  }
247  return (found);
248 }
249 #endif
250 
251 #if !defined(COSA_DEBUG_NO_MEMORY_USAGE)
252 void
254 {
255  int HEAPEND = (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
256  printf(PSTR("data=%d,heap=%d,stack=%d,free=%d\n"),
257  DATASIZE,
258  HEAPEND - (int) &__heap_start,
259  RAMEND - marker + 1,
260  marker - HEAPEND);
261 }
262 #endif
263 
264 #if !defined(COSA_DEBUG_NO_PRINT_DATA)
265 void
267 {
268  print(RAMSTART, (void*) RAMSTART, DATASIZE, IOStream::hex);
269 }
270 #endif
271 
272 #if !defined(COSA_DEBUG_NO_PRINT_HEAP)
273 void
275 {
276  int HEAPSTART = (int) &__heap_start;
277  int HEAPEND = (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
278  int size = HEAPEND - HEAPSTART;
279  if (size == 0) return;
280  print(HEAPSTART, (void*) HEAPSTART, size, IOStream::hex);
281 }
282 #endif
283 
284 #if !defined(COSA_DEBUG_NO_PRINT_STACK)
285 void
287 {
288  int size = RAMEND - marker + 1;
289  if (size == 0) return;
290  print(marker, (void*) marker, size, IOStream::hex);
291 }
292 #endif
293 
294 #if !defined(COSA_DEBUG_NO_PRINT_VARIABLES)
295 void
297 {
298  for (Variable* vp = m_var; vp != NULL; vp = vp->m_next) vp->print();
299 }
300 #endif
301 
302 void
304 {
305  debug.printf(PSTR("%p:%s:%S@%p"), this, m_func, m_name, m_ref);
306  if (m_size == 1) {
307  debug.printf(PSTR("=%d\n"), *((uint8_t*) m_ref));
308  }
309  else if (m_size == 2) {
310  debug.printf(PSTR("=%d\n"), *((int*) m_ref));
311  }
312  else {
313  debug.printf(PSTR("[%d]:"), m_size);
314  if (m_size > 16) debug.println();
315  debug.print((uint32_t) m_ref, m_ref, m_size, IOStream::hex);
316  }
317 }
int strncmp_P(const char *s1, str_P s2, size_t n)
Definition: Types.h:230
void println()
Definition: IOStream.hh:467
void print(int value, Base base=dec)
Definition: IOStream.cpp:46
void do_print_heap()
Definition: Debug.cpp:274
#define NULL
Definition: Types.h:101
void run(const char *file=NULL, int line=0, const char *func=NULL, str_P expr=NULL)
Definition: Debug.cpp:85
void do_print_stack(int marker)
Definition: Debug.cpp:286
void print()
Definition: Debug.cpp:303
#define PSTR(s)
Definition: Types.h:202
bool check_stack(int room=128)
Definition: Debug.cpp:68
void do_print_variables()
Definition: Debug.cpp:296
char EXITCHARACTER
Character to emit on exit.
Definition: Debug.hh:268
Debug debug
Definition: Debug.cpp:23
void do_backtrace(const char *func)
Definition: Debug.cpp:187
void assert(const char *file, int line, const char *func, str_P cond)
Definition: Debug.cpp:45
bool end()
Definition: Debug.cpp:77
void printf(str_P format,...)
Definition: IOStream.hh:487
void flush()
Definition: IOStream.hh:504
bool begin(IOStream::Device *dev, const char *file, int line, const char *func)
Definition: Debug.cpp:28
Variable * m_var
Last registered variable.
Definition: Debug.hh:267
char * readline(char *buf, size_t size, bool echo=true)
Definition: IOStream.cpp:262
void do_print_data()
Definition: Debug.cpp:266
const class prog_str * str_P
Definition: Types.h:187
void do_help()
Definition: Debug.cpp:200
void do_memory_usage(int marker)
Definition: Debug.cpp:253
int DATAEND
End of data segment.
Definition: Debug.hh:269
int * __brkval
void(* yield)()
void break_at(const char *file, int line, const char *func, str_P cond)
Definition: Debug.cpp:58
int DATASIZE
Size of data segment.
Definition: Debug.hh:270
Device * device() const
Definition: IOStream.hh:265
bool do_lookup_variables(const char *name)
Definition: Debug.cpp:238
Definition: Debug.hh:48
Device * m_dev
Delegated device.
Definition: IOStream.hh:723
int __heap_start
static const size_t BUF_MAX
Definition: IOStream.hh:730
int strcmp_P(const char *s1, str_P s2)
Definition: Types.h:224