diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index a67d286a..cdb06a68 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -761,9 +761,12 @@ extern uint32_t * _edata; // If you don't override a specific handler, it will just spin forever. void DefaultIRQHandler( void ) { -#if FUNCONF_DEBUG_HARDFAULT - // Wait indefinitely for a debugger to attach. - while( !DidDebuggerAttach() ); +#if FUNCONF_DEBUG_HARDFAULT && ( FUNCONF_USE_DEBUGPRINTF || FUNCONF_USE_UARTPRINTF ) +#if FUNCONF_USE_DEBUGPRINTF + // Wait indefinitely for a printf to become clear. + while( !DebugPrintfBufferFree() ); + +#endif printf( "DEAD MSTATUS:%08x MTVAL:%08x MCAUSE:%08x MEPC:%08x\n", (int)__get_MSTATUS(), (int)__get_MTVAL(), (int)__get_MCAUSE(), (int)__get_MEPC() ); #endif // Infinite Loop @@ -1587,7 +1590,7 @@ static void internal_handle_input( volatile uint32_t * dmdata0 ) { uint32_t dmd0 = *dmdata0; int bytes = (dmd0 & 0x3f) - 4; - if( bytes > 0 ) + if( bytes > 0 && bytes < 16 ) { handle_debug_input( bytes, ((uint8_t*)dmdata0) + 1 ); } @@ -1609,14 +1612,18 @@ void poll_input( void ) // MSB .... LSB // DMDATA0: char3 char2 char1 [status word] // where [status word] is: -// b7 = is a "printf" waiting? -// b0..b3 = # of bytes in printf (+4). (5 or higher indicates a print of some kind) +// bit 7 = is a "printf" waiting? +// bit 6 = printf has timed out. +// bit 0..bit 3 = # of bytes in printf (+4). (5 or higher indicates a print of some kind) // note: if b7 is 0 in reply, but b0..b3 have >=4 then we received data from host. +// Special sentinel: +// status word = 0x80 = default at start +// status word = 0xcx = timed out. // declare as weak to allow overriding. WEAK int _write(int fd, const char *buf, int size) { (void)fd; - if( !DidDebuggerAttach() ) return; + if( ( *DMDATA0 & 0xc0 ) == 0xc0 ) return 0; char buffer[4] = { 0 }; int place = 0; @@ -1634,7 +1641,13 @@ WEAK int _write(int fd, const char *buf, int size) if( tosend > 7 ) tosend = 7; while( ( lastdmd = (*DMDATA0) ) & 0x80 ) - if( timeout-- == 0 ) return place; + { + if( timeout-- == 0 ) + { + *DMDATA0 |= 0xc0; + return 0; + } + } if( lastdmd ) internal_handle_input( (uint32_t*)DMDATA0 ); @@ -1665,16 +1678,24 @@ WEAK int _write(int fd, const char *buf, int size) // single to debug intf WEAK int putchar(int c) { - if( !DidDebuggerAttach() ) return; + if( ( *DMDATA0 & 0xc0 ) == 0xc0 ) return 0; int timeout = FUNCONF_DEBUGPRINTF_TIMEOUT; uint32_t lastdmd = 0; while( ( lastdmd = (*DMDATA0) ) & 0x80 ) - if( timeout-- == 0 ) return 0; + { + if( timeout-- == 0 ) + { + *DMDATA0 |= 0xc0; + return 0; + } + } // Simply seeking input. if( lastdmd ) internal_handle_input( (uint32_t*)DMDATA0 ); + + // Write out character. *DMDATA0 = 0x85 | ((const char)c<<8); return 1; } diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 59bfc5a1..90162ecd 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -50,10 +50,10 @@ 8. Default debug behavior, when semihosting: a. You get access to DidDebuggerAttach() - so you can see if a debugger has attached. b. WaitForDebuggerToAttach( int timeout_ms ) - if timeout_ms == 0, will wait for forever. - c. If a debugger has attached, printf will wait 120ms (configurable) to make sure it - doesn't drop data. Otherwise, printf fast-path's to exit. It will still do the string + c. printf will wait 120ms (configurable) to make sure it doesn't drop data. Otherwise, + printf will fast-path to exit after the first timeout. It will still do the string formatting, but will not wait on output. Timeout is configured with - FUNCONF_DEBUGPRINTF_TIMEOUT + FUNCONF_DEBUGPRINTF_TIMEOUT. d. If you hard fault, it will wait indefinitely for a debugger to attach, once attached, will printf the fault cause, and the memory address of the fault. Space can be saved by setting FUNCONF_DEBUG_HARDFAULT to 0. @@ -14007,9 +14007,10 @@ void SetupUART( int uartBRR ); int WaitForDebuggerToAttach( int timeout_ms ); // Returns 1 if a debugger has activated the debug module. -#if defined(__riscv) || defined(__riscv__) -inline static int DidDebuggerAttach() { return !*DMSTATUS_SENTINEL; } -#endif +#define DidDebuggerAttach() (!*DMSTATUS_SENTINEL) + +// Returns 1 if a debugger has activated the debug module. +#define DebugPrintfBufferFree() (!(*DMDATA0 & 0x80)) // Just a definition to the internal _write function. int _write(int fd, const char *buf, int size); diff --git a/examples/debugprintfdemo/debugprintfdemo.c b/examples/debugprintfdemo/debugprintfdemo.c index c0040083..b33783db 100644 --- a/examples/debugprintfdemo/debugprintfdemo.c +++ b/examples/debugprintfdemo/debugprintfdemo.c @@ -17,6 +17,8 @@ int main() { SystemInit(); + while( !DebugPrintfBufferFree() ); + // Enable GPIOs RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC; diff --git a/examples/debugprintfdemo/funconfig.h b/examples/debugprintfdemo/funconfig.h index 5d54106e..bcc0cdbc 100644 --- a/examples/debugprintfdemo/funconfig.h +++ b/examples/debugprintfdemo/funconfig.h @@ -3,7 +3,7 @@ // Though this should be on by default we can extra force it on. #define FUNCONF_USE_DEBUGPRINTF 1 -#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. +//#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Optionally, wait for a very very long time on every printf. #define CH32V003 1