/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 by Linus Nielsen Feltzing * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include "config.h" #include "cpu.h" #ifdef HAVE_GDB_API #include "gdb_api.h" #endif #ifdef DEBUG static char debugmembuf[200]; #if CONFIG_CPU == SH7034 static char debugbuf[400]; #endif #endif #ifndef SIMULATOR /* allow non archos platforms to display output */ #include "kernel.h" #include "system.h" #include "debug.h" #ifdef DEBUG #if CONFIG_CPU == SH7034 /* these are still very SH-oriented */ void debug_init(void) { /* Clear it all! */ SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER); /* This enables the serial Rx interrupt, to be able to exit into the debugger when you hit CTRL-C */ SCR1 |= 0x40; SCR1 &= ~0x80; IPRE |= 0xf000; /* Set to highest priority */ } static int debug_tx_ready(void) { return (SSR1 & SCI_TDRE); } static void debug_tx_char(char ch) { while (!debug_tx_ready()) { ; } /* * Write data into TDR and clear TDRE */ TDR1 = ch; SSR1 &= ~SCI_TDRE; } static void debug_handle_error(char ssr) { (void)ssr; SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER); } static int debug_rx_ready(void) { char ssr; ssr = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER ); if ( ssr ) debug_handle_error ( ssr ); return SSR1 & SCI_RDRF; } static char debug_rx_char(void) { char ch; char ssr; while (!debug_rx_ready()) { ; } ch = RDR1; SSR1 &= ~SCI_RDRF; ssr = SSR1 & (SCI_PER | SCI_FER | SCI_ORER); if (ssr) debug_handle_error (ssr); return ch; } static const char hexchars[] = "0123456789abcdef"; static char highhex(int x) { return hexchars[(x >> 4) & 0xf]; } static char lowhex(int x) { return hexchars[x & 0xf]; } static void putpacket (const char *buffer) { register int checksum; const char *src = buffer; /* Special debug hack. Shut off the Rx IRQ during I/O to prevent the debug stub from interrupting the message */ SCR1 &= ~0x40; debug_tx_char ('$'); checksum = 0; while (*src) { int runlen; /* Do run length encoding */ for (runlen = 0; runlen < 100; runlen ++) { if (src[0] != src[runlen] || runlen == 99) { if (runlen > 3) { int encode; /* Got a useful amount */ debug_tx_char (*src); checksum += *src; debug_tx_char ('*'); checksum += '*'; checksum += (encode = runlen + ' ' - 4); debug_tx_char (encode); src += runlen; } else { debug_tx_char (*src); checksum += *src; src++; } break; } } } debug_tx_char ('#'); debug_tx_char (highhex(checksum)); debug_tx_char (lowhex(checksum)); /* Wait for the '+' */ debug_rx_char(); /* Special debug hack. Enable the IRQ again */ SCR1 |= 0x40; } /* convert the memory, pointed to by mem into hex, placing result in buf */ /* return a pointer to the last char put in buf (null) */ static char *mem2hex (const char *mem, char *buf, int count) { int i; int ch; for (i = 0; i < count; i++) { ch = *mem++; *buf++ = highhex (ch); *buf++ = lowhex (ch); } *buf = 0; return (buf); } static void debug(const char *msg) { debugbuf[0] = 'O'; mem2hex(msg, &debugbuf[1], strlen(msg)); putpacket(debugbuf); } #endif /* SH7034 */ #ifdef HAVE_GDB_API static void *get_api_function(int n) { struct gdb_api *api = (struct gdb_api *)GDB_API_ADDRESS; if (api->magic == GDB_API_MAGIC) return api->func[n]; else return NULL; } void breakpoint(void) { void (*f)(void) = get_api_function(0); if (f) (*f)(); } static void debug(char *msg) { void (*f)(char *) = get_api_function(1); if (f) (*f)(msg); } void debug_init(void) { } #endif /* HAVE_GDB_API */ #endif /* end of DEBUG section */ #ifdef __GNUC__ void debugf(const char *fmt, ...) #endif { #ifdef DEBUG va_list ap; va_start(ap, fmt); vsnprintf(debugmembuf, sizeof(debugmembuf), fmt, ap); va_end(ap); debug(debugmembuf); #else (void)fmt; #endif } #endif