/* * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * */ /* * $Log$ * Revision 1.10 2009/03/05 22:16:57 freckle * use __NUT_EMULATION instead of __APPLE__, __linux__, or __CYGWIN__ * * Revision 1.9 2009/01/17 11:26:52 haraldkipp * Getting rid of two remaining BSD types in favor of stdint. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'. * * Revision 1.8 2008/08/11 07:00:34 haraldkipp * BSD types replaced by stdint types (feature request #1282721). * * Revision 1.7 2005/07/26 15:50:00 haraldkipp * Cygwin support added. * * Revision 1.6 2005/07/12 14:07:14 freckle * removed unnecessary critical sections * * Revision 1.5 2005/06/12 16:55:24 haraldkipp * Timer pool has been removed from the kernel. * * Revision 1.4 2004/04/07 12:13:58 haraldkipp * Matthias Ringwald's *nix emulation added * * Revision 1.3 2004/03/19 09:05:12 jdubiec * Fixed format strings declarations for AVR. * * Revision 1.2 2004/03/16 16:48:45 haraldkipp * Added Jan Dubiec's H8/300 port. * * Revision 1.1.1.1 2003/05/09 14:41:52 haraldkipp * Initial using 3.2.1 * * Revision 1.8 2003/04/21 17:09:01 harald * *** empty log message *** * * Revision 1.7 2003/02/04 18:15:57 harald * Version 3 released * * Revision 1.6 2002/06/26 17:29:44 harald * First pre-release with 2.4 stack * */ #include #include #include #include #include #include #include #if defined(__arm__) || defined(__AVR32__) || defined(__m68k__) || defined(__H8300H__) || defined(__H8300S__) || defined(__NUT_EMULATION__) #define ARCH_32BIT #endif FILE *__os_trs; uint_fast8_t __os_trf; FILE *__heap_trs; uint_fast8_t __heap_trf; static char *states[] = { "TRM", "RUN", "RDY", "SLP" }; #ifdef ARCH_32BIT /* 12345678 12345678 1234 123 12345678 12345678 12345678 1234556789 123456789*/ static const char qheader[] PROGMEM = "\nHandle Name Prio Sta Queue Timer StackPtr FreeMem MinStack\n"; #else /* 1234 12345678 1234 123 1234 1234 1234 1234567 12345678*/ static const char qheader[] PROGMEM = "\nHndl Name Prio Sta QUE Timr StkP FreeMem MinStack\n"; #endif /*! * \brief Dump system queue contents. * * \param stream Pointer to a previously opened stream associated to * a debug device. * \param tdp Pointer to the queue. * * \warning Interrupts are disabled inside this funtion. */ void NutDumpThreadQueue(FILE * stream, NUTTHREADINFO * tdp) { #ifdef ARCH_32BIT static const char fmt[] PROGMEM = "%08lX %-8s %4u %s %08lX %08lX %08lX %9lu %s\n"; #else static const char fmt[] PROGMEM = "%04lX %-8s %4u %s %04lX %04lX %04lX %5lu %s\n"; #endif if (tdp == SIGNALED) fputs("SIGNALED\n", stream); else { while (tdp) { #ifdef __NUT_EMULATION__ fprintf_P(stream, fmt, (uintptr_t) tdp, tdp->td_name, tdp->td_priority, states[tdp->td_state], (uintptr_t) tdp->td_queue, (uintptr_t) tdp->td_timer, tdp->td_cs_level, 0, "--"); #else fprintf_P(stream, fmt, (long) (intptr_t) tdp, tdp->td_name, tdp->td_priority, states[tdp->td_state], (long) (intptr_t) tdp->td_queue, (long) (intptr_t) tdp->td_timer, (long) tdp->td_sp, (long) tdp->td_sp - (long) (intptr_t) tdp->td_memory, *((uint32_t *) tdp->td_memory) != DEADBEEF && *((uint32_t *) (tdp->td_memory + 4)) != DEADBEEF && *((uint32_t *) (tdp->td_memory + 8)) != DEADBEEF && *((uint32_t *) (tdp->td_memory + 12)) != DEADBEEF ? "FAIL" : "OK"); #endif tdp = tdp->td_qnxt; } } } /*! * \brief Dump system thread list. * * \param stream Pointer to a previously opened stream associated to * a debug device. * * \warning Interrupts are disabled inside this funtion. */ void NutDumpThreadList(FILE * stream) { #ifdef ARCH_32BIT static const char fmt1[] PROGMEM = "%08X %-8s %4u %s %08X %08X %08X %9u %9u %s"; static const char fmt2[] PROGMEM = " %08X"; #else static const char fmt1[] PROGMEM = "%04X %-8s %4u %s %04X %04X %04X %7u %8u %s"; static const char fmt2[] PROGMEM = " %04X"; #endif NUTTHREADINFO *tqp; NUTTHREADINFO *tdp; fputs_P(qheader, stream); tdp = nutThreadList; while (tdp) { #ifdef __NUT_EMULATION__ fprintf_P(stream, fmt1, (uintptr_t) tdp, tdp->td_name, tdp->td_priority, 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), "--"); #else fprintf_P(stream, fmt1, (int) tdp, tdp->td_name, tdp->td_priority, states[tdp->td_state], (int) tdp->td_queue, (int) tdp->td_timer, (int) tdp->td_sp, (int) tdp->td_sp - (int) tdp->td_memory, (unsigned int) NutThreadStackAvailable(tdp->td_name), *((uint32_t *) tdp->td_memory) != DEADBEEF ? "FAIL" : "OK"); #endif if (tdp->td_queue) { tqp = *(NUTTHREADINFO **) (tdp->td_queue); if (tqp == SIGNALED) fputs("SIGNALED", stream); else { while (tqp) { fprintf_P(stream, fmt2, (int) tqp); tqp = tqp->td_qnxt; } } } fputc('\n', stream); tdp = tdp->td_next; } } /*! * \brief Dump system timer list. * * \param stream Pointer to a previously opened stream associated to * a debug device. * * \warning Interrupts are disabled inside this funtion. */ void NutDumpTimerList(FILE * stream) { static const char wname[] PROGMEM = "NutThreadWake"; static const char tname[] PROGMEM = "NutEventTimeout"; #ifdef ARCH_32BIT static const char theader[] PROGMEM = "Address Ticks Left Callback\n"; static const char fmt1[] PROGMEM = "%08X%6lu%6lu "; static const char fmt2[] PROGMEM = "%09lX"; static const char fmt3[] PROGMEM = "(%08X)\n"; #else static const char theader[] PROGMEM = "Addr Ticks Left Callback\n"; static const char fmt1[] PROGMEM = "%04X%6lu%6lu "; static const char fmt2[] PROGMEM = "%05lX"; static const char fmt3[] PROGMEM = "(%04X)\n"; #endif NUTTIMERINFO *tnp; if ((tnp = nutTimerList) != 0) { fputs_P(theader, stream); while (tnp) { fprintf_P(stream, fmt1, (int) tnp, tnp->tn_ticks, tnp->tn_ticks_left); if (tnp->tn_callback == NutThreadWake) fputs_P(wname, stream); else if (tnp->tn_callback == NutEventTimeout) fputs_P(tname, stream); else fprintf_P(stream, fmt2, (uint32_t) ((uintptr_t) tnp->tn_callback) << 1); fprintf_P(stream, fmt3, (int) tnp->tn_arg); tnp = tnp->tn_next; } } } /*! * \brief Control OS tracing. * * \param stream Pointer to a previously opened stream associated to * a debug device or null to disable trace output. * \param flags Flags to enable specific traces. */ void NutTraceOs(FILE * stream, uint8_t flags) { if (stream) __os_trs = stream; if (__os_trs) __os_trf = flags; else __os_trf = 0; } /*! * \brief Dump free node list of heap memory. * * \param stream Pointer to a previously opened stream associated to * a debug device. */ void NutDumpHeap(FILE * stream) { #ifdef ARCH_32BIT static const char fmt1[] PROGMEM = "%08x %9d\n"; static const char fmt2[] PROGMEM = "%u counted, but %u reported\n"; static const char fmt3[] PROGMEM = "%u bytes free\n"; #else static const char fmt1[] PROGMEM = "%04x %5d\n"; static const char fmt2[] PROGMEM = "%u counted, but %u reported\n"; static const char fmt3[] PROGMEM = "%u bytes free\n"; #endif HEAPNODE *node; size_t sum = 0; size_t avail; fputc('\n', stream); for (node = heapFreeList; node; node = node->hn_next) { sum += node->hn_size; fprintf_P(stream, fmt1, (int) node, (unsigned int) node->hn_size); /* TODO: Remove hardcoded RAMSTART and RAMEND */ if ((uintptr_t) node < 0x60 || (uintptr_t) node > 0x7fff) break; } if ((avail = NutHeapAvailable()) != sum) fprintf_P(stream, fmt2, (unsigned int) sum, (unsigned int) avail); else fprintf_P(stream, fmt3, (unsigned int) avail); } /*! * \brief Control dynamic memory tracing. * * \param stream Pointer to a previously opened stream or null to * disable trace output. * \param flags Flags to enable specific traces. */ void NutTraceHeap(FILE * stream, uint8_t flags) { if (stream) __heap_trs = stream; if (__heap_trs) __heap_trf = flags; else __heap_trf = 0; }