Merge commit '541861e978ba88c80e7e2a0cbcd7ce55d574c97b' into sam-update
# Conflicts: # README.md
This commit is contained in:
commit
a89b2ead47
@ -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;
|
||||
|
@ -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
|
||||
|
@ -16,6 +16,7 @@ LDFLAGS = -lopencm3_stm32f4 \
|
||||
VPATH += platforms/stm32
|
||||
|
||||
SRC += cdcacm.c \
|
||||
traceswodecode.c \
|
||||
traceswo.c \
|
||||
usbuart.c \
|
||||
serialno.c \
|
||||
|
@ -16,6 +16,7 @@ LDFLAGS = -lopencm3_stm32f4 \
|
||||
VPATH += platforms/stm32
|
||||
|
||||
SRC += cdcacm.c \
|
||||
traceswodecode.c \
|
||||
traceswo.c \
|
||||
usbuart.c \
|
||||
serialno.c \
|
||||
|
@ -21,6 +21,7 @@ endif
|
||||
VPATH += platforms/stm32
|
||||
|
||||
SRC += cdcacm.c \
|
||||
traceswodecode.c \
|
||||
traceswo.c \
|
||||
usbuart.c \
|
||||
serialno.c \
|
||||
|
@ -32,6 +32,7 @@ SRC += cdcacm.c \
|
||||
serialno.c \
|
||||
timing.c \
|
||||
timing_stm32.c \
|
||||
traceswodecode.c \
|
||||
traceswoasync.c \
|
||||
stlink_common.c \
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
69
src/platforms/stm32/traceswodecode.c
Normal file
69
src/platforms/stm32/traceswodecode.c
Normal 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 */
|
@ -25,6 +25,7 @@ SRC += cdcacm.c \
|
||||
serialno.c \
|
||||
timing.c \
|
||||
timing_stm32.c \
|
||||
traceswodecode.c \
|
||||
traceswoasync.c \
|
||||
platform_common.c \
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user