osdebug.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Log$
  35. * Revision 1.10 2009/03/05 22:16:57 freckle
  36. * use __NUT_EMULATION instead of __APPLE__, __linux__, or __CYGWIN__
  37. *
  38. * Revision 1.9 2009/01/17 11:26:52 haraldkipp
  39. * Getting rid of two remaining BSD types in favor of stdint.
  40. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
  41. *
  42. * Revision 1.8 2008/08/11 07:00:34 haraldkipp
  43. * BSD types replaced by stdint types (feature request #1282721).
  44. *
  45. * Revision 1.7 2005/07/26 15:50:00 haraldkipp
  46. * Cygwin support added.
  47. *
  48. * Revision 1.6 2005/07/12 14:07:14 freckle
  49. * removed unnecessary critical sections
  50. *
  51. * Revision 1.5 2005/06/12 16:55:24 haraldkipp
  52. * Timer pool has been removed from the kernel.
  53. *
  54. * Revision 1.4 2004/04/07 12:13:58 haraldkipp
  55. * Matthias Ringwald's *nix emulation added
  56. *
  57. * Revision 1.3 2004/03/19 09:05:12 jdubiec
  58. * Fixed format strings declarations for AVR.
  59. *
  60. * Revision 1.2 2004/03/16 16:48:45 haraldkipp
  61. * Added Jan Dubiec's H8/300 port.
  62. *
  63. * Revision 1.1.1.1 2003/05/09 14:41:52 haraldkipp
  64. * Initial using 3.2.1
  65. *
  66. * Revision 1.8 2003/04/21 17:09:01 harald
  67. * *** empty log message ***
  68. *
  69. * Revision 1.7 2003/02/04 18:15:57 harald
  70. * Version 3 released
  71. *
  72. * Revision 1.6 2002/06/26 17:29:44 harald
  73. * First pre-release with 2.4 stack
  74. *
  75. */
  76. #include <compiler.h>
  77. #include <cfg/os.h>
  78. #include <sys/thread.h>
  79. #include <sys/timer.h>
  80. #include <sys/event.h>
  81. #include <sys/heap.h>
  82. #include <sys/osdebug.h>
  83. #if defined(__arm__) || defined(__AVR32__) || defined(__m68k__) || defined(__H8300H__) || defined(__H8300S__) || defined(__NUT_EMULATION__)
  84. #define ARCH_32BIT
  85. #endif
  86. FILE *__os_trs;
  87. uint_fast8_t __os_trf;
  88. FILE *__heap_trs;
  89. uint_fast8_t __heap_trf;
  90. static char *states[] = { "TRM", "RUN", "RDY", "SLP" };
  91. #ifdef ARCH_32BIT
  92. /* 12345678 12345678 1234 123 12345678 12345678 12345678 1234556789 123456789*/
  93. static const char qheader[] PROGMEM = "\nHandle Name Prio Sta Queue Timer StackPtr FreeMem MinStack\n";
  94. #else
  95. /* 1234 12345678 1234 123 1234 1234 1234 1234567 12345678*/
  96. static const char qheader[] PROGMEM = "\nHndl Name Prio Sta QUE Timr StkP FreeMem MinStack\n";
  97. #endif
  98. /*!
  99. * \brief Dump system queue contents.
  100. *
  101. * \param stream Pointer to a previously opened stream associated to
  102. * a debug device.
  103. * \param tdp Pointer to the queue.
  104. *
  105. * \warning Interrupts are disabled inside this funtion.
  106. */
  107. void NutDumpThreadQueue(FILE * stream, NUTTHREADINFO * tdp)
  108. {
  109. #ifdef ARCH_32BIT
  110. static const char fmt[] PROGMEM = "%08lX %-8s %4u %s %08lX %08lX %08lX %9lu %s\n";
  111. #else
  112. static const char fmt[] PROGMEM = "%04lX %-8s %4u %s %04lX %04lX %04lX %5lu %s\n";
  113. #endif
  114. if (tdp == SIGNALED)
  115. fputs("SIGNALED\n", stream);
  116. else {
  117. while (tdp) {
  118. #ifdef __NUT_EMULATION__
  119. fprintf_P(stream, fmt, (uintptr_t) tdp, tdp->td_name, tdp->td_priority,
  120. states[tdp->td_state], (uintptr_t) tdp->td_queue, (uintptr_t) tdp->td_timer, tdp->td_cs_level, 0, "--");
  121. #else
  122. fprintf_P(stream, fmt, (long) (intptr_t) tdp, tdp->td_name, tdp->td_priority,
  123. states[tdp->td_state], (long) (intptr_t) tdp->td_queue,
  124. (long) (intptr_t) tdp->td_timer, (long) tdp->td_sp,
  125. (long) tdp->td_sp - (long) (intptr_t) tdp->td_memory,
  126. *((uint32_t *) tdp->td_memory) != DEADBEEF
  127. && *((uint32_t *) (tdp->td_memory + 4)) != DEADBEEF
  128. && *((uint32_t *) (tdp->td_memory + 8)) != DEADBEEF
  129. && *((uint32_t *) (tdp->td_memory + 12)) != DEADBEEF ? "FAIL" : "OK");
  130. #endif
  131. tdp = tdp->td_qnxt;
  132. }
  133. }
  134. }
  135. /*!
  136. * \brief Dump system thread list.
  137. *
  138. * \param stream Pointer to a previously opened stream associated to
  139. * a debug device.
  140. *
  141. * \warning Interrupts are disabled inside this funtion.
  142. */
  143. void NutDumpThreadList(FILE * stream)
  144. {
  145. #ifdef ARCH_32BIT
  146. static const char fmt1[] PROGMEM = "%08X %-8s %4u %s %08X %08X %08X %9u %9u %s";
  147. static const char fmt2[] PROGMEM = " %08X";
  148. #else
  149. static const char fmt1[] PROGMEM = "%04X %-8s %4u %s %04X %04X %04X %7u %8u %s";
  150. static const char fmt2[] PROGMEM = " %04X";
  151. #endif
  152. NUTTHREADINFO *tqp;
  153. NUTTHREADINFO *tdp;
  154. fputs_P(qheader, stream);
  155. tdp = nutThreadList;
  156. while (tdp) {
  157. #ifdef __NUT_EMULATION__
  158. fprintf_P(stream, fmt1, (uintptr_t) tdp, tdp->td_name, tdp->td_priority,
  159. states[tdp->td_state], (uintptr_t) tdp->td_queue, (uintptr_t) tdp->td_timer, tdp->td_cs_level, 0, (unsigned int) NutThreadStackAvailable(tdp->td_name), "--");
  160. #else
  161. fprintf_P(stream, fmt1, (int) tdp, tdp->td_name, tdp->td_priority,
  162. states[tdp->td_state], (int) tdp->td_queue,
  163. (int) tdp->td_timer, (int) tdp->td_sp,
  164. (int) tdp->td_sp - (int) tdp->td_memory, (unsigned int) NutThreadStackAvailable(tdp->td_name),
  165. *((uint32_t *) tdp->td_memory) != DEADBEEF ? "FAIL" : "OK");
  166. #endif
  167. if (tdp->td_queue) {
  168. tqp = *(NUTTHREADINFO **) (tdp->td_queue);
  169. if (tqp == SIGNALED)
  170. fputs("SIGNALED", stream);
  171. else {
  172. while (tqp) {
  173. fprintf_P(stream, fmt2, (int) tqp);
  174. tqp = tqp->td_qnxt;
  175. }
  176. }
  177. }
  178. fputc('\n', stream);
  179. tdp = tdp->td_next;
  180. }
  181. }
  182. /*!
  183. * \brief Dump system timer list.
  184. *
  185. * \param stream Pointer to a previously opened stream associated to
  186. * a debug device.
  187. *
  188. * \warning Interrupts are disabled inside this funtion.
  189. */
  190. void NutDumpTimerList(FILE * stream)
  191. {
  192. static const char wname[] PROGMEM = "NutThreadWake";
  193. static const char tname[] PROGMEM = "NutEventTimeout";
  194. #ifdef ARCH_32BIT
  195. static const char theader[] PROGMEM = "Address Ticks Left Callback\n";
  196. static const char fmt1[] PROGMEM = "%08X%6lu%6lu ";
  197. static const char fmt2[] PROGMEM = "%09lX";
  198. static const char fmt3[] PROGMEM = "(%08X)\n";
  199. #else
  200. static const char theader[] PROGMEM = "Addr Ticks Left Callback\n";
  201. static const char fmt1[] PROGMEM = "%04X%6lu%6lu ";
  202. static const char fmt2[] PROGMEM = "%05lX";
  203. static const char fmt3[] PROGMEM = "(%04X)\n";
  204. #endif
  205. NUTTIMERINFO *tnp;
  206. if ((tnp = nutTimerList) != 0) {
  207. fputs_P(theader, stream);
  208. while (tnp) {
  209. fprintf_P(stream, fmt1, (int) tnp, tnp->tn_ticks, tnp->tn_ticks_left);
  210. if (tnp->tn_callback == NutThreadWake)
  211. fputs_P(wname, stream);
  212. else if (tnp->tn_callback == NutEventTimeout)
  213. fputs_P(tname, stream);
  214. else
  215. fprintf_P(stream, fmt2, (uint32_t) ((uintptr_t) tnp->tn_callback) << 1);
  216. fprintf_P(stream, fmt3, (int) tnp->tn_arg);
  217. tnp = tnp->tn_next;
  218. }
  219. }
  220. }
  221. /*!
  222. * \brief Control OS tracing.
  223. *
  224. * \param stream Pointer to a previously opened stream associated to
  225. * a debug device or null to disable trace output.
  226. * \param flags Flags to enable specific traces.
  227. */
  228. void NutTraceOs(FILE * stream, uint8_t flags)
  229. {
  230. if (stream)
  231. __os_trs = stream;
  232. if (__os_trs)
  233. __os_trf = flags;
  234. else
  235. __os_trf = 0;
  236. }
  237. /*!
  238. * \brief Dump free node list of heap memory.
  239. *
  240. * \param stream Pointer to a previously opened stream associated to
  241. * a debug device.
  242. */
  243. void NutDumpHeap(FILE * stream)
  244. {
  245. #ifdef ARCH_32BIT
  246. static const char fmt1[] PROGMEM = "%08x %9d\n";
  247. static const char fmt2[] PROGMEM = "%u counted, but %u reported\n";
  248. static const char fmt3[] PROGMEM = "%u bytes free\n";
  249. #else
  250. static const char fmt1[] PROGMEM = "%04x %5d\n";
  251. static const char fmt2[] PROGMEM = "%u counted, but %u reported\n";
  252. static const char fmt3[] PROGMEM = "%u bytes free\n";
  253. #endif
  254. HEAPNODE *node;
  255. size_t sum = 0;
  256. size_t avail;
  257. fputc('\n', stream);
  258. for (node = heapFreeList; node; node = node->hn_next) {
  259. sum += node->hn_size;
  260. fprintf_P(stream, fmt1, (int) node, (unsigned int) node->hn_size);
  261. /* TODO: Remove hardcoded RAMSTART and RAMEND */
  262. if ((uintptr_t) node < 0x60 || (uintptr_t) node > 0x7fff)
  263. break;
  264. }
  265. if ((avail = NutHeapAvailable()) != sum)
  266. fprintf_P(stream, fmt2, (unsigned int) sum, (unsigned int) avail);
  267. else
  268. fprintf_P(stream, fmt3, (unsigned int) avail);
  269. }
  270. /*!
  271. * \brief Control dynamic memory tracing.
  272. *
  273. * \param stream Pointer to a previously opened stream or null to
  274. * disable trace output.
  275. * \param flags Flags to enable specific traces.
  276. */
  277. void NutTraceHeap(FILE * stream, uint8_t flags)
  278. {
  279. if (stream)
  280. __heap_trs = stream;
  281. if (__heap_trs)
  282. __heap_trf = flags;
  283. else
  284. __heap_trf = 0;
  285. }