Merge commit '541861e978ba88c80e7e2a0cbcd7ce55d574c97b' into sam-update

# Conflicts:
#	README.md
This commit is contained in:
Jason Kotzin 2022-08-09 17:23:48 -07:00
commit a89b2ead47
12 changed files with 178 additions and 27 deletions

View File

@ -90,9 +90,9 @@ const struct command_s cmd_list[] = {
#endif
#ifdef PLATFORM_HAS_TRACESWO
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, NRZ mode: (baudrate)" },
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, NRZ mode: (baudrate) (decode channel ...)" },
#else
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, Manchester mode" },
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, Manchester mode: (decode channel ...)" },
#endif
#endif
{"heapinfo", (cmd_handler)cmd_heapinfo, "Set semihosting heapinfo" },
@ -381,19 +381,49 @@ static bool cmd_traceswo(target *t, int argc, const char **argv)
extern char serial_no[9];
#endif
(void)t;
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
if (argc > 1) {
uint32_t baudrate = atoi(argv[1]);
traceswo_init(baudrate);
} else {
gdb_outf("Missing baudrate parameter in command\n");
#if TRACESWO_PROTOCOL == 2
uint32_t baudrate = SWO_DEFAULT_BAUD;
#endif
uint32_t swo_channelmask = 0; /* swo decoding off */
uint8_t decode_arg = 1;
#if TRACESWO_PROTOCOL == 2
/* argument: optional baud rate for async mode */
if ((argc > 1) && (*argv[1] >= '0') && (*argv[1] <= '9')) {
baudrate = atoi(argv[1]);
if (baudrate == 0) baudrate = SWO_DEFAULT_BAUD;
decode_arg = 2;
}
#endif
/* argument: 'decode' literal */
if((argc > decode_arg) && !strncmp(argv[decode_arg], "decode", strlen(argv[decode_arg]))) {
swo_channelmask = 0xFFFFFFFF; /* decoding all channels */
/* arguments: channels to decode */
if (argc > decode_arg + 1) {
swo_channelmask = 0x0;
for (int i = decode_arg+1; i < argc; i++) { /* create bitmask of channels to decode */
int channel = atoi(argv[i]);
if ((channel >= 0) && (channel <= 31))
swo_channelmask |= (uint32_t)0x1 << channel;
}
}
}
#if defined(PLATFORM_HAS_DEBUG) && !defined(PC_HOSTED) && defined(ENABLE_DEBUG)
if (debug_bmp) {
#if TRACESWO_PROTOCOL == 2
gdb_outf("baudrate: %lu ", baudrate);
#endif
gdb_outf("channel mask: ");
for (int8_t i=31;i>=0;i--) {
uint8_t bit = (swo_channelmask >> i) & 0x1;
gdb_outf("%u", bit);
}
gdb_outf("\n");
}
#endif
#if TRACESWO_PROTOCOL == 2
traceswo_init(baudrate, swo_channelmask);
#else
(void)argv;
traceswo_init();
if (argc > 1) {
gdb_outf("Superfluous parameter(s) ignored\n");
}
traceswo_init(swo_channelmask);
#endif
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
return true;

View File

@ -23,11 +23,20 @@
#include <libopencm3/usb/usbd.h>
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
void traceswo_init(uint32_t baudrate);
/* Default line rate, used as default for a request without baudrate */
#define SWO_DEFAULT_BAUD (2250000)
void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask);
#else
void traceswo_init(void);
void traceswo_init(uint32_t swo_chan_bitmask);
#endif
void trace_buf_drain(usbd_device *dev, uint8_t ep);
/* set bitmask of swo channels to be decoded */
void traceswo_setmask(uint32_t mask);
/* print decoded swo packet on usb serial */
uint16_t traceswo_decode(usbd_device *usbd_dev, uint8_t addr,
const void *buf, uint16_t len);
#endif

View File

@ -16,6 +16,7 @@ LDFLAGS = -lopencm3_stm32f4 \
VPATH += platforms/stm32
SRC += cdcacm.c \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.c \

View File

@ -16,6 +16,7 @@ LDFLAGS = -lopencm3_stm32f4 \
VPATH += platforms/stm32
SRC += cdcacm.c \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.c \

View File

@ -21,6 +21,7 @@ endif
VPATH += platforms/stm32
SRC += cdcacm.c \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.c \

View File

@ -32,6 +32,7 @@ SRC += cdcacm.c \
serialno.c \
timing.c \
timing_stm32.c \
traceswodecode.c \
traceswoasync.c \
stlink_common.c \

View File

@ -39,7 +39,10 @@
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/rcc.h>
void traceswo_init(void)
/* SWO decoding */
static bool decoding = false;
void traceswo_init(uint32_t swo_chan_bitmask)
{
TRACE_TIM_CLK_EN();
@ -73,6 +76,9 @@ void traceswo_init(void)
timer_ic_enable(TRACE_TIM, TIM_IC2);
timer_enable_counter(TRACE_TIM);
traceswo_setmask(swo_chan_bitmask);
decoding = (swo_chan_bitmask != 0);
}
static uint8_t trace_usb_buf[64];
@ -80,7 +86,9 @@ static uint8_t trace_usb_buf_size;
void trace_buf_push(uint8_t *buf, int len)
{
if (usbd_ep_write_packet(usbdev, 0x85, buf, len) != len) {
if (decoding)
traceswo_decode(usbdev, CDCACM_UART_ENDPOINT, buf, len);
else if (usbd_ep_write_packet(usbdev, 0x85, buf, len) != len) {
if (trace_usb_buf_size + len > 64) {
/* Stall if upstream to too slow. */
usbd_ep_stall_set(usbdev, 0x85, 1);
@ -97,7 +105,10 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep)
if (!trace_usb_buf_size)
return;
usbd_ep_write_packet(dev, ep, trace_usb_buf, trace_usb_buf_size);
if (decoding)
traceswo_decode(dev, CDCACM_UART_ENDPOINT, trace_usb_buf, trace_usb_buf_size);
else
usbd_ep_write_packet(dev, ep, trace_usb_buf, trace_usb_buf_size);
trace_usb_buf_size = 0;
}

View File

@ -41,8 +41,6 @@
/* For speed this is set to the USB transfer size */
#define FULL_SWO_PACKET (64)
/* Default line rate....used as default for a request without baudrate */
#define DEFAULTSPEED (2250000)
static volatile uint32_t w; /* Packet currently received via UART */
static volatile uint32_t r; /* Packet currently waiting to transmit to USB */
@ -50,6 +48,8 @@ static volatile uint32_t r; /* Packet currently waiting to transmit to USB */
static uint8_t trace_rx_buf[NUM_TRACE_PACKETS * FULL_SWO_PACKET];
/* Packet pingpong buffer used for receiving packets */
static uint8_t pingpong_buf[2 * FULL_SWO_PACKET];
/* SWO decoding */
static bool decoding = false;
void trace_buf_drain(usbd_device *dev, uint8_t ep)
{
@ -59,10 +59,20 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep)
if (__atomic_test_and_set (&inBufDrain, __ATOMIC_RELAXED))
return;
/* Attempt to write everything we buffered */
if ((w != r) && (usbd_ep_write_packet(dev, ep,
if (w != r) {
uint16_t rc;
if (decoding)
/* write decoded swo packets to the uart port */
rc = traceswo_decode(dev, CDCACM_UART_ENDPOINT,
&trace_rx_buf[r * FULL_SWO_PACKET],
FULL_SWO_PACKET)))
r =(r + 1) % NUM_TRACE_PACKETS;
FULL_SWO_PACKET);
else
/* write raw swo packets to the trace port */
rc = usbd_ep_write_packet(dev, ep,
&trace_rx_buf[r * FULL_SWO_PACKET],
FULL_SWO_PACKET);
if (rc) r = (r + 1) % NUM_TRACE_PACKETS;
}
__atomic_clear (&inBufDrain, __ATOMIC_RELAXED);
}
@ -115,10 +125,10 @@ void SWO_DMA_ISR(void)
trace_buf_drain(usbdev, 0x85);
}
void traceswo_init(uint32_t baudrate)
void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask)
{
if (!baudrate)
baudrate = DEFAULTSPEED;
baudrate = SWO_DEFAULT_BAUD;
rcc_periph_clock_enable(SWO_UART_CLK);
rcc_periph_clock_enable(SWO_DMA_CLK);
@ -130,4 +140,6 @@ void traceswo_init(uint32_t baudrate)
nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA);
nvic_enable_irq(SWO_DMA_IRQ);
traceswo_setspeed(baudrate);
traceswo_setmask(swo_chan_bitmask);
decoding = (swo_chan_bitmask != 0);
}

View File

@ -0,0 +1,69 @@
/*
* This file is part of the Black Magic Debug project.
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Print decoded swo stream on the usb serial */
#include "general.h"
#include "cdcacm.h"
#include "traceswo.h"
/* SWO decoding */
/* data is static in case swo packet is astride two buffers */
static uint8_t swo_buf[CDCACM_PACKET_SIZE];
static int swo_buf_len = 0;
static uint32_t swo_decode = 0; /* bitmask of channels to print */
static int swo_pkt_len = 0; /* decoder state */
static bool swo_print = false;
/* print decoded swo packet on usb serial */
uint16_t traceswo_decode(usbd_device *usbd_dev, uint8_t addr,
const void *buf, uint16_t len) {
if (usbd_dev == NULL) return 0;
for (int i = 0; i<len; i++) {
uint8_t ch=((uint8_t*)buf)[i];
if (swo_pkt_len == 0) { /* header */
uint32_t channel = (uint32_t)ch >> 3; /* channel number */
uint32_t size = ch & 0x7; /* drop channel number */
if (size == 0x01) swo_pkt_len = 1; /* SWO packet 0x01XX */
else if (size == 0x02) swo_pkt_len = 2; /* SWO packet 0x02XXXX */
else if (size == 0x03) swo_pkt_len = 4; /* SWO packet 0x03XXXXXXXX */
swo_print = (swo_pkt_len != 0) && ((swo_decode & (1UL << channel)) != 0UL);
} else if (swo_pkt_len <= 4) { /* data */
if (swo_print) {
swo_buf[swo_buf_len++]=ch;
if (swo_buf_len == sizeof(swo_buf)) {
if (cdcacm_get_config() && cdcacm_get_dtr()) /* silently drop if usb not ready */
usbd_ep_write_packet(usbd_dev, addr, swo_buf, swo_buf_len);
swo_buf_len=0;
}
}
--swo_pkt_len;
} else { /* recover */
swo_buf_len=0;
swo_pkt_len=0;
}
}
return len;
}
/* set bitmask of swo channels to be decoded */
void traceswo_setmask(uint32_t mask) {
swo_decode = mask;
}
/* not truncated */

View File

@ -25,6 +25,7 @@ SRC += cdcacm.c \
serialno.c \
timing.c \
timing_stm32.c \
traceswodecode.c \
traceswoasync.c \
platform_common.c \

View File

@ -71,6 +71,10 @@ static target_addr cortexm_check_watch(target *t);
static int cortexm_hostio_request(target *t);
#if !defined(PC_HOSTED)
static uint32_t time0_sec = UINT32_MAX; /* sys_clock time origin */
#endif
struct cortexm_priv {
ADIv5_AP_t *ap;
bool stepping;
@ -1206,6 +1210,8 @@ static int cortexm_hostio_request(target *t)
if (syscall == SYS_TIME) { /* SYS_TIME: time in seconds */
ret = sec;
} else { /* SYS_CLOCK: time in hundredths of seconds */
if (time0_sec > sec) time0_sec = sec; /* set sys_clock time origin */
sec -= time0_sec;
uint64_t csec64 = (sec * 1000000ull + usec)/10000ull;
uint32_t csec = csec64 & 0x7fffffff;
ret = csec;

View File

@ -120,12 +120,21 @@ bool stm32f1_probe(target *t)
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
switch(t->idcode) {
case 0x410: /* Medium density */
case 0x412: /* Low denisty */
case 0x412: /* Low density */
case 0x420: /* Value Line, Low-/Medium density */
t->driver = "STM32F1 medium density";
target_add_ram(t, 0x20000000, 0x5000);
stm32f1_add_flash(t, 0x8000000, 0x20000, 0x400);
target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD");
/* Test for non-genuine parts with Core rev 2*/
ADIv5_AP_t *ap = cortexm_ap(t);
if ((ap->idr >> 28) > 1) {
t->driver = "STM32F1 (clone) medium density";
#if defined(PLATFORM_HAS_DEBUG)
DEBUG("Non-genuine STM32F1\n");
#endif
} else {
t->driver = "STM32F1 medium density";
}
return true;
case 0x414: /* High density */
case 0x418: /* Connectivity Line */