From 3e9913e88bfd03458d97920c8d693c441e1b5ef0 Mon Sep 17 00:00:00 2001 From: Anti Sullin Date: Mon, 26 Mar 2018 20:53:06 +0300 Subject: [PATCH] Implement semihosting debug output redirection to usb-uart port. --- src/include/general.h | 3 ++- src/platforms/hydrabus/platform.h | 1 + src/platforms/launchpad-icdi/platform.h | 1 + src/platforms/native/platform.h | 1 + src/platforms/stlink/platform.h | 1 + src/platforms/stm32/usbuart.c | 14 ++++++++++++++ src/platforms/swlink/platform.h | 1 + src/platforms/tm4c/usbuart.c | 19 ++++++++++++++++--- src/target/cortexm.c | 19 +++++++++++++++++-- src/target/target.c | 19 +++++++++++++++++++ src/target/target_internal.h | 3 +++ 11 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/include/general.h b/src/include/general.h index 25f83a4..829c2f6 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -74,6 +74,8 @@ enum BMP_DEBUG { # define DEBUG_PROBE(...) do {} while(0) # define DEBUG_WIRE(...) do {} while(0) # define DEBUG_GDB_WIRE(...) do {} while(0) + +void usbuart_send_stdout(const uint8_t *data, uint32_t len); #else # include extern int cl_debuglevel; @@ -171,4 +173,3 @@ static inline void DEBUG_WIRE(const char *format, ...) #define MORSECNT ((SYSTICKHZ / 10) - 1) #endif - diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index bdcd7d1..00fb90f 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -31,6 +31,7 @@ #include +#define PLATFORM_HAS_USBUART #define PLATFORM_HAS_TRACESWO #define PLATFORM_IDENT " (HydraBus))" diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 8fc37e2..026374a 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -22,6 +22,7 @@ #include "timing.h" +#define PLATFORM_HAS_USBUART #define PLATFORM_IDENT "(Launchpad ICDI) " extern uint8_t running_status; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index b38f91d..671e601 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -30,6 +30,7 @@ #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH +#define PLATFORM_HAS_USBUART #ifdef ENABLE_DEBUG # define PLATFORM_HAS_DEBUG diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 9e2d210..206f96b 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -39,6 +39,7 @@ extern bool debug_bmp; int usbuart_debug_write(const char *buf, size_t len); #endif +#define PLATFORM_HAS_USBUART #define PLATFORM_IDENT "(STLINK/V2) " /* Hardware definitions... */ diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 2ac7da9..9a35466 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -192,6 +192,20 @@ void usbuart_init(void) usart_enable_rx_dma(USBUSART); } +void usbuart_send_stdout(const uint8_t *data, uint32_t len) +{ + while (len) { + uint32_t cnt = CDCACM_PACKET_SIZE; + if (cnt > len) + cnt = len; + nvic_disable_irq(USB_IRQ); + cnt = usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, data, cnt); + nvic_enable_irq(USB_IRQ); + data += cnt; + len -= cnt; + } +} + void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) { usart_set_baudrate(USBUSART, coding->dwDTERate); diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 6e6eb7c..dab4ab5 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -36,6 +36,7 @@ extern bool debug_bmp; int usbuart_debug_write(const char *buf, size_t len); #endif +#define PLATFORM_HAS_USBUART #define PLATFORM_IDENT "(SWLINK) " /* Hardware definitions... */ diff --git a/src/platforms/tm4c/usbuart.c b/src/platforms/tm4c/usbuart.c index 2394684..e0ee624 100644 --- a/src/platforms/tm4c/usbuart.c +++ b/src/platforms/tm4c/usbuart.c @@ -41,10 +41,10 @@ static uint8_t buf_rx_out; void usbuart_init(void) { UART_PIN_SETUP(); - + periph_clock_enable(USBUART_CLK); __asm__("nop"); __asm__("nop"); __asm__("nop"); - + uart_disable(USBUART); /* Setup UART parameters. */ @@ -73,6 +73,20 @@ void usbuart_init(void) nvic_enable_irq(USBUART_IRQ); } +void usbuart_send_stdout(const uint8_t *data, uint32_t len) +{ + while (len) { + uint32_t cnt = CDCACM_PACKET_SIZE; + if (cnt > len) + cnt = len; + nvic_disable_irq(USBUART_IRQ); + cnt = usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, data, cnt); + nvic_enable_irq(USBUART_IRQ); + data += cnt; + len -= cnt; + } +} + void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) { uart_set_baudrate(USBUART, coding->dwDTERate); @@ -180,4 +194,3 @@ void USBUART_ISR(void) buf_rx_out %= FIFO_SIZE; } } - diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 3a60825..acee475 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -58,9 +58,15 @@ static const char cortexm_driver_str[] = "ARM Cortex-M"; static bool cortexm_vector_catch(target *t, int argc, char *argv[]); +#ifdef PLATFORM_HAS_USBUART +static bool cortexm_redirect_stdout(target *t, int argc, const char **argv); +#endif const struct command_s cortexm_cmd_list[] = { {"vector_catch", (cmd_handler)cortexm_vector_catch, "Catch exception vectors"}, +#ifdef PLATFORM_HAS_USBUART + {"redirect_stdout", (cmd_handler)cortexm_redirect_stdout, "Redirect semihosting stdout to USB UART"}, +#endif {NULL, NULL, NULL} }; @@ -1207,6 +1213,17 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) #define SYS_WRITEC 0x03 #define SYS_WRITE0 0x04 +#ifdef PLATFORM_HAS_USBUART +static bool cortexm_redirect_stdout(target *t, int argc, const char **argv) +{ + if (argc == 1) + gdb_outf("Semihosting stdout redirection: %s\n", t->stdout_redirected ? "enabled" : "disabled"); + else + t->stdout_redirected = !strncmp(argv[1], "enable", strlen(argv[1])); + return true; +} +#endif + #if PC_HOSTED == 0 /* probe memory access functions */ static void probe_mem_read(target *t __attribute__((unused)), void *probe_dest, target_addr target_src, size_t len) @@ -1216,7 +1233,6 @@ static void probe_mem_read(target *t __attribute__((unused)), void *probe_dest, DEBUG_INFO("probe_mem_read\n"); while (len--) *dst++=*src++; - return; } static void probe_mem_write(target *t __attribute__((unused)), target_addr target_dest, const void *probe_src, size_t len) @@ -1226,7 +1242,6 @@ static void probe_mem_write(target *t __attribute__((unused)), target_addr targe DEBUG_INFO("probe_mem_write\n"); while (len--) *dst++=*src++; - return; } #endif diff --git a/src/target/target.c b/src/target/target.c index dd4208a..b877825 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -22,9 +22,12 @@ #include "target_internal.h" #include +#include target *target_list = NULL; +#define STDOUT_READ_BUF_SIZE 64 + static int target_flash_write_buffered(struct target_flash *f, target_addr dest, const void *src, size_t len); static int target_flash_done_buffered(struct target_flash *f); @@ -630,6 +633,22 @@ int tc_read(target *t, int fd, target_addr buf, unsigned int count) int tc_write(target *t, int fd, target_addr buf, unsigned int count) { +#ifdef PLATFORM_HAS_USBUART + if (t->stdout_redirected && (fd == STDOUT_FILENO || fd == STDERR_FILENO)) { + while (count) { + uint8_t tmp[STDOUT_READ_BUF_SIZE]; + unsigned int cnt = sizeof(tmp); + if (cnt > count) + cnt = count; + target_mem_read(t, tmp, buf, cnt); + usbuart_send_stdout(tmp, cnt); + count -= cnt; + buf += cnt; + } + return 0; + } +#endif + if (t->tc->write == NULL) return 0; return t->tc->write(t->tc, fd, buf, count); diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 883d3b5..90233fe 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -129,6 +129,9 @@ struct target_s { char cmdline[MAX_CMDLINE]; target_addr heapinfo[4]; struct target_command_s *commands; +#ifdef PLATFORM_HAS_USBUART + bool stdout_redirected; +#endif struct target_s *next;