From 10448828a099522d8b8a781f2c2caa0830e8b181 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 12 Aug 2024 08:17:06 +0100 Subject: [PATCH 01/48] common/stm32/traceswo: Cleaned up the copyright notice and corrected the top of file comments, including the docs references --- src/platforms/common/stm32/traceswo.c | 28 ++++++++++++++++----------- src/target/adiv5.c | 4 ++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index 9b12840abc3..86e34ed2a74 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -1,8 +1,11 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Copyright (C) 2012 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Modified by Uwe Bonnes + * Copyright (C) 2024 1BitSquared + * Modified by Rachel Mant * * 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 @@ -18,19 +21,22 @@ * along with this program. If not, see . */ -/* This file implements capture of the TRACESWO output. +/* + * This file implements capture of Machester SWO trace output + * + * References: + * DDI0403 - ARMv7-M Architecture Reference Manual, version E.e + * - https://developer.arm.com/documentation/ddi0403/latest/ + * DDI0314 - CoreSight Components Technical Reference Manual, version 1.0, rev. H + * - https://developer.arm.com/documentation/ddi0314/latest/ * - * ARM DDI 0403D - ARMv7M Architecture Reference Manual - * ARM DDI 0337I - Cortex-M3 Technical Reference Manual - * ARM DDI 0314H - CoreSight Components Technical Reference Manual + * The basic idea is that SWO comes in on a pin connected to a timer block, + * and because Manchester coding is self-clocking we can determine the timing + * for that input signal when it's active, so: use the timer to capture edge + * transition timings; fire an interrupt each complete cycle; and then use some + * timing analysis on the CPU to extract the SWO data sequence. */ -/* TDO/TRACESWO signal comes into pin PA6/TIM3_CH1 - * Manchester coding is assumed on TRACESWO, so bit timing can be detected. - * The idea is to use TIM3 input capture modes to capture pulse timings. - * These can be capture directly to RAM by DMA. - * The core can then process the buffer to extract the frame. - */ #include "general.h" #include "platform.h" #include "usb.h" diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 968aab68eea..318aa84753c 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -1,9 +1,9 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Copyright (C) 2015 Black Sphere Technologies Ltd. * Written by Gareth McMullin - * Copyright (C) 2018-2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) + * Copyright (C) 2018-2021 Uwe Bonnes * Copyright (C) 2022-2024 1BitSquared * Modified by Rachel Mant * From 3bcdbcb001cdf7c92302660cb76c41ed21773bb7 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 13 Aug 2024 06:51:08 +0100 Subject: [PATCH 02/48] common/stm32/traceswo: Implement handling for deinitialising Machester-mode SWO --- src/command.c | 5 ----- src/platforms/common/stm32/traceswo.c | 9 +++++++-- src/platforms/common/traceswo.h | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/command.c b/src/command.c index 62a6baf926b..e9dfc5282f2 100644 --- a/src/command.c +++ b/src/command.c @@ -650,14 +650,9 @@ static bool cmd_traceswo_enable(int argc, const char **argv) static bool cmd_traceswo_disable(void) { -#if TRACESWO_PROTOCOL == 2 traceswo_deinit(); gdb_out("Trace disabled\n"); return true; -#else - gdb_out("Not implemented\n"); - return false; -#endif } static bool cmd_traceswo(target_s *t, int argc, const char **argv) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index 86e34ed2a74..086638c5453 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -52,7 +52,7 @@ static bool decoding = false; static uint8_t trace_usb_buf[64]; static uint8_t trace_usb_buf_size; -void traceswo_init(uint32_t swo_chan_bitmask) +void traceswo_init(const uint32_t swo_chan_bitmask) { TRACE_TIM_CLK_EN(); @@ -94,7 +94,12 @@ void traceswo_init(uint32_t swo_chan_bitmask) #endif traceswo_setmask(swo_chan_bitmask); - decoding = (swo_chan_bitmask != 0); + decoding = swo_chan_bitmask != 0; +} + +void traceswo_deinit(void) +{ + timer_disable_counter(TRACE_TIM); } void trace_buf_push(uint8_t *buf, int len) diff --git a/src/platforms/common/traceswo.h b/src/platforms/common/traceswo.h index ef8ac3a4eca..f4b356a87e8 100644 --- a/src/platforms/common/traceswo.h +++ b/src/platforms/common/traceswo.h @@ -1,8 +1,10 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Copyright (C) 2012 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Copyright (C) 2024 1BitSquared + * Modified by Rachel Mant * * 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 @@ -27,12 +29,12 @@ /* Default line rate, used as default for a request without baudrate */ #define SWO_DEFAULT_BAUD 2250000U void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask); -void traceswo_deinit(void); uint32_t traceswo_get_baudrate(void); void bmd_usart_set_baudrate(uint32_t usart, uint32_t baud_rate); #else void traceswo_init(uint32_t swo_chan_bitmask); #endif +void traceswo_deinit(void); void trace_buf_drain(usbd_device *dev, uint8_t ep); From 5286f294b500673a3b20ed2611fc12690f801bb1 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 13 Aug 2024 06:51:48 +0100 Subject: [PATCH 03/48] common/stm32/traceswo: Cleaned up and started sorting out the Manchester-mode SWO implementation --- src/platforms/96b_carbon/platform.h | 2 +- .../common/blackpill-f4/blackpill-f4.h | 45 ++++++++++++------- src/platforms/common/stm32/traceswo.c | 42 +++++++++-------- src/platforms/ctxlink/platform.h | 12 +++-- src/platforms/f072/platform.h | 30 +++++++++---- src/platforms/f3/platform.h | 30 +++++++++---- src/platforms/f4discovery/platform.h | 30 +++++++++---- src/platforms/hydrabus/platform.h | 32 ++++++++----- src/platforms/native/platform.c | 3 ++ src/platforms/native/platform.h | 24 +++++++--- src/platforms/stlink/platform.h | 23 +++++++--- src/platforms/stlinkv3/platform.c | 17 +++---- src/platforms/stlinkv3/platform.h | 16 ++++--- src/platforms/swlink/platform.h | 24 +++++++--- 14 files changed, 219 insertions(+), 111 deletions(-) diff --git a/src/platforms/96b_carbon/platform.h b/src/platforms/96b_carbon/platform.h index f3024737f1b..34c93001faf 100644 --- a/src/platforms/96b_carbon/platform.h +++ b/src/platforms/96b_carbon/platform.h @@ -28,7 +28,7 @@ #include "timing_stm32.h" #include "version.h" -#define PLATFORM_IDENT "(Carbon)" +#define PLATFORM_IDENT "(96b Carbon) " /* * Important pin mappings for Carbon implementation: diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index ddb82975eef..67a8e7d0fdb 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -64,6 +64,8 @@ extern bool debug_bmp; #if ALTERNATIVE_PINOUT < 1 || ALTERNATIVE_PINOUT > 3 #error "Invalid value for ALTERNATIVE_PINOUT. Value is smaller than 1, or larger than 3. Value must be between 1 and 3" #endif +#else +#define ALTERNATIVE_PINOUT 0 #endif /* ALTERNATIVE_PINOUT */ /* @@ -77,21 +79,21 @@ extern bool debug_bmp; * The maximum number of input arguments is 4. * The 3rd and 4th arguments to this function are optional. */ -#ifndef ALTERNATIVE_PINOUT // if ALTERNATIVE_PINOUT is not defined -#define PINOUT_SWITCH(opt0, ...) (opt0) // select the first argument +#if ALTERNATIVE_PINOUT == 0 +#define PINOUT_SWITCH(opt0, ...) (opt0) // Select the first argument #elif ALTERNATIVE_PINOUT == 1 -#define PINOUT_SWITCH(opt0, opt1, ...) (opt1) // select the second argument +#define PINOUT_SWITCH(opt0, opt1, ...) (opt1) // Select the second argument #elif ALTERNATIVE_PINOUT == 2 -#define PINOUT_SWITCH(opt0, opt1, opt2, ...) (opt2) // select the third argument +#define PINOUT_SWITCH(opt0, opt1, opt2, ...) (opt2) // Select the third argument #elif ALTERNATIVE_PINOUT == 3 -#define PINOUT_SWITCH(opt0, opt1, opt2, opt3, ...) (opt3) // select the fourth argument -#endif /* ALTERNATIVE_PINOUT */ +#define PINOUT_SWITCH(opt0, opt1, opt2, opt3, ...) (opt3) // Select the fourth argument +#endif /* * Important pin mappings for STM32 implementation: * * JTAG/SWD * * PB6 or PB5: TDI - * * PB7 or PB6: TDO/TRACESWO + * * PB7 or PB6: TDO/SWO * * PB8 or PB7: TCK/SWCLK * * PB9 or PB8: TMS/SWDIO * * PA6 or PB3: TRST @@ -154,6 +156,10 @@ extern bool debug_bmp; #define NRST_PORT PINOUT_SWITCH(GPIOA, GPIOB) #define NRST_PIN PINOUT_SWITCH(GPIO5, GPIO4) +/* SWO comes in on the same pin as TDO */ +#define SWO_PORT GPIOB +#define SWO_PIN PINOUT_SWITCH(GPIO7, GPIO6) + #define PWR_BR_PORT PINOUT_SWITCH(GPIOA, GPIOB) #define PWR_BR_PIN PINOUT_SWITCH(GPIO1, GPIO9) @@ -283,18 +289,25 @@ extern bool debug_bmp; #define PLATFORM_HAS_TRACESWO #define NUM_TRACE_PACKETS 256U /* 16K buffer */ -//#define TRACESWO_PROTOCOL 2U /* 1 = RZ/Manchester, 2 = NRZ/async/uart */ #if TRACESWO_PROTOCOL == 1 -/* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, trigger on Rising Edge */ -#define TRACE_TIM TIM4 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) -#define TRACE_IRQ NVIC_TIM4_IRQ -#define TRACE_ISR(x) tim4_isr(x) -#define TRACE_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +/* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, triggered on rising edge */ +#define TRACE_TIM TIM4 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) +#define TRACE_IRQ NVIC_TIM4_IRQ +#define TRACE_ISR(x) tim4_isr(x) +#define TRACE_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) +#define TRACE_TIM_PIN_AF GPIO_AF2 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index 086638c5453..5de1c7b7bfa 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -35,6 +35,9 @@ * for that input signal when it's active, so: use the timer to capture edge * transition timings; fire an interrupt each complete cycle; and then use some * timing analysis on the CPU to extract the SWO data sequence. + * + * We use the first capture channel of a pair to capture the cycle time and + * thee second to capture the high time (mark period). */ #include "general.h" @@ -54,26 +57,27 @@ static uint8_t trace_usb_buf_size; void traceswo_init(const uint32_t swo_chan_bitmask) { + /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ TRACE_TIM_CLK_EN(); - - /* Refer to ST doc RM0008 - STM32F10xx Reference Manual. - * Section 14.3.4 - 14.3.6 (General Purpose Timer - Input Capture) - * - * CCR1 captures cycle time, CCR2 captures high time + /* Then make sure the IO pin used is properly set up as an input routed to the timer */ + gpio_set_mode(SWO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_PIN); + + /* + * Start setting the timer block up by picking a pair of cross-linked capture channels suitable for the input, + * and configure them to consume the input channel for the SWO pin. We use one in rising edge mode and the + * other in falling to get the mark period and cycle period - together these define all elements of a wiggle. + * NB: "TRACE_IC" here refers to the Input Capture channels being used + */ + timer_ic_set_input(TRACE_TIM, TRACE_IC_RISING, TRACE_IC_IN); + timer_ic_set_polarity(TRACE_TIM, TRACE_IC_RISING, TIM_IC_RISING); + timer_ic_set_input(TRACE_TIM, TRACE_IC_FALLING, TRACE_IC_IN); + timer_ic_set_polarity(TRACE_TIM, TRACE_IC_FALLING, TIM_IC_FALLING); + + /* + * Use reset mode to trigger the timer, which makes the counter reset and start counting anew + * when a rising edge is detected on the input pin via the filtered input channel as a trigger source */ - - /* Use TI1 as capture input for CH1 and CH2 */ - timer_ic_set_input(TRACE_TIM, TIM_IC1, TRACE_IC_IN); - timer_ic_set_input(TRACE_TIM, TIM_IC2, TRACE_IC_IN); - - /* Capture CH1 on rising edge, CH2 on falling edge */ - timer_ic_set_polarity(TRACE_TIM, TIM_IC1, TIM_IC_RISING); - timer_ic_set_polarity(TRACE_TIM, TIM_IC2, TIM_IC_FALLING); - - /* Trigger on Filtered Timer Input 1 (TI1FP1) */ timer_slave_set_trigger(TRACE_TIM, TRACE_TRIG_IN); - - /* Slave reset mode: reset counter on trigger */ timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_RM); /* Enable capture interrupt */ @@ -82,8 +86,8 @@ void traceswo_init(const uint32_t swo_chan_bitmask) timer_enable_irq(TRACE_TIM, TIM_DIER_CC1IE); /* Enable the capture channels */ - timer_ic_enable(TRACE_TIM, TIM_IC1); - timer_ic_enable(TRACE_TIM, TIM_IC2); + timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); + timer_ic_enable(TRACE_TIM, TRACE_IC_FALLING); timer_enable_counter(TRACE_TIM); diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index 3df76450985..dfa2d8a2c17 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -46,7 +46,7 @@ * TDI = PA3 (output) * TMS = PA4 (input/output for SWDIO) * TCK = PA5 (output SWCLK) - * TDO = PC6 (input) + * TDO = PC7 (input SWO) * TMS_DIR = PA1 (output) controls target buffer direction * TPWR = PB0 (analog input) * VBAT = PA0 (analog input) @@ -81,6 +81,9 @@ #define NRST_SENSE_PORT GPIOA #define NRST_SENSE_PIN GPIO7 +#define SWO_PORT GPIOC +#define SWO_PIN GPIO7 + #define LED_PORT GPIOC #define LED_PORT_UART GPIOB #define LED_UART GPIO2 @@ -185,12 +188,12 @@ #if TRACESWO_PROTOCOL == 1 -/* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on Rising Edge */ +/* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ #define TRACE_TIM TIM3 #define TRACE_TIM_CLK_EN() #define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_IN TIM_IC_IN_TI2 #define TRACE_IC_RISING TIM_IC1 #define TRACE_CC_RISING TIM3_CCR1 #define TRACE_ITR_RISING TIM_DIER_CC1IE @@ -199,7 +202,8 @@ #define TRACE_CC_FALLING TIM3_CCR2 #define TRACE_STATUS_FALLING TIM_SR_CC2IF #define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TRIG_IN TIM_SMCR_TS_TI2FP2 +#define SWO_TIM_PIN_AF GPIO_AF2 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/f072/platform.h b/src/platforms/f072/platform.h index 70ca359e67e..5a720d388bf 100644 --- a/src/platforms/f072/platform.h +++ b/src/platforms/f072/platform.h @@ -38,9 +38,9 @@ * LED2 = PB7 (Red LED : Error) * * TDI = PA0 - * TMS = PA1 (input for SWDP) + * TMS = PA1 (input/output SWDIO) * TCK = PA7/SWCLK - * TDO = PA6 (input for TRACESWO + * TDO = PA6 (input SWO) * nRST = PA5 * * Force DFU mode button: BOOT0 @@ -65,6 +65,9 @@ #define NRST_PORT GPIOA #define NRST_PIN GPIO5 +#define SWO_PORT GPIOA +#define SWO_PIN GPIO6 + #define LED_PORT GPIOB #define LED_PORT_UART GPIOB #define LED_UART GPIO6 @@ -128,13 +131,22 @@ USART2_CR2 |= USART_CR2_SWAP; \ } while (0) -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR tim3_isr -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF1 +/* Use TIM3 Input 1 (from PA6/TDO on AF1) */ +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR tim3_isr +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM_PIN_AF GPIO_AF1 #if ENABLE_DEBUG == 1 extern bool debug_bmp; diff --git a/src/platforms/f3/platform.h b/src/platforms/f3/platform.h index 94983bd98da..530cf46897e 100644 --- a/src/platforms/f3/platform.h +++ b/src/platforms/f3/platform.h @@ -38,9 +38,9 @@ * LED2 = PB7 (Red LED : Error) * * TDI = PA0 - * TMS = PA1 (input for SWDP) + * TMS = PA1 (input/output SWDIO) * TCK = PA7/SWCLK - * TDO = PA6 (input for TRACESWO + * TDO = PA6 (input SWO) * nRST = PA5 * * Force DFU mode button: BOOT0 @@ -65,6 +65,9 @@ #define NRST_PORT GPIOA #define NRST_PIN GPIO5 +#define SWO_PORT GPIOA +#define SWO_PIN GPIO6 + #define LED_PORT GPIOB #define LED_PORT_UART GPIOB #define LED_UART GPIO6 @@ -121,13 +124,22 @@ USART2_CR2 |= USART_CR2_SWAP; \ } while (0) -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR tim3_isr -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +/* Use TIM3 Input 1 (from PA6/TDO) */ +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR tim3_isr +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM_PIN_AF GPIO_AF2 #if ENABLE_DEBUG == 1 extern bool debug_bmp; diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 0036e7c86da..c9bf54a124d 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -41,9 +41,9 @@ * nTRST = PC1 * nRST_OUT = PC8 * TDI = PC2 - * TMS = PC4 (input for SWDP) + * TMS = PC4 (input/output SWDIO) * TCK = PC5/SWCLK - * TDO = PC6 (input for TRACESWO + * TDO = PC6 (input SWO) * nRST = PC8 * * Force DFU mode button: PA0 @@ -70,6 +70,9 @@ #define NRST_PORT GPIOC #define NRST_PIN GPIO8 +#define SWO_PORT GPIOC +#define SWO_PIN GPIO6 + #define LED_PORT GPIOD #define LED_PORT_UART GPIOD #define LED_UART GPIO12 @@ -126,13 +129,22 @@ #define IRQ_PRI_USBUSART_DMA (2U << 4U) #define IRQ_PRI_TRACE (0U << 4U) -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +/* Use TIM3 Input 1 (from PC6/TDO) */ +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR(x) tim3_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM_PIN_AF GPIO_AF2 #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index 3a3ed298241..76295e51a81 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -29,7 +29,7 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO -#define PLATFORM_IDENT " (HydraBus))" +#define PLATFORM_IDENT "(HydraBus) " /* * Important pin mappings for STM32 implementation: @@ -41,10 +41,11 @@ * * TMS = PC0 (SWDIO) * TCK = PC1 (SWCLK) - * TDO = PC2 (input for TRACESWO) + * TDO = PC2 * TDI = PC3 * nRST = PC4 (nRST / nRESET / "System Reset") * nTRST = PC5 (Test Reset optional) + * SWO = PC6 * * USB VBUS detect: PB13 */ @@ -71,6 +72,9 @@ #define NRST_PORT GPIOC #define NRST_PIN GPIO4 +#define SWO_PORT GPIOC +#define SWO_PIN GPIO6 + #define LED_PORT GPIOA #define LED_PORT_UART GPIOA #define LED_UART GPIO4 @@ -124,14 +128,22 @@ /* For STM32F4 DMA trigger source must be specified */ #define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4 -/* Use TIM3 Input 1 (from PC6), AF2, trigger on Rising Edge. FIXME: TDO is on PC2. */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +/* Use TIM3 Input 1 (from PC6), AF2, trigger on rising edge. */ +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR(x) tim3_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM_PIN_AF GPIO_AF2 #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 055466fc25b..e6fb8b96dff 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -156,6 +156,8 @@ void platform_init(void) rcc_periph_clock_enable(RCC_GPIOC); if (hwversion >= 1) rcc_periph_clock_enable(RCC_TIM1); + /* Make sure to power up the timer used for trace */ + rcc_periph_clock_enable(RCC_TIM3); rcc_periph_clock_enable(RCC_AFIO); rcc_periph_clock_enable(RCC_CRC); @@ -165,6 +167,7 @@ void platform_init(void) gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_DIR_PIN | TCK_PIN | TDI_PIN); gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN); + gpio_set_mode(JTAG_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, TDO_PIN); /* This needs some fixing... */ /* Toggle required to sort out line drivers... */ diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 00a03d03d8f..c63d38e11ba 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -134,6 +134,14 @@ extern int hwversion; #define NRST_SENSE_PORT HW_SWITCH(6, GPIOA, GPIOC) #define NRST_SENSE_PIN HW_SWITCH(6, GPIO7, GPIO13) +/* + * SWO comes in on PB7 (TIM4 CH2) before HW6, and PA10 (TIM1 CH3) after - + * however, because of Shenanigans™ with timers and other pins, this has to + * reuse TDO (PA6, TIM3 CH1) to not wind up clobbering timers and timer pins + */ +#define SWO_PORT GPIOA +#define SWO_PIN GPIO6 + /* * These are the control output pin definitions for TPWR. * TPWR is sensed via PB0 by sampling ADC1's channel 8. @@ -288,14 +296,16 @@ extern int hwversion; #define USBUSART2_DMA_RX_IRQ NVIC_DMA1_CHANNEL6_IRQ #define USBUSART2_DMA_RX_ISR(x) dma1_channel6_isr(x) -#if TRACESWO_PROTOCOL == 1 +#if TRACESWO_PROTOCOL == 1U /* Use TIM3 Input 1 (from PA6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR(x) tim3_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 #endif #define SET_RUN_STATE(state) running_status = (state) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index a2cd754916f..b801d015671 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -67,6 +67,9 @@ extern bool debug_bmp; #define NRST_PIN_CLONE GPIO6 #endif +#define SWO_PORT GPIOA +#define SWO_PIN GPIO6 + #ifdef BLUEPILL #define LED_PORT GPIOC #else @@ -175,12 +178,20 @@ extern bool debug_bmp; #if TRACESWO_PROTOCOL == 1 /* Use TIM3 Input 1 (from PA6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_TIM TIM3 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR(x) tim3_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/stlinkv3/platform.c b/src/platforms/stlinkv3/platform.c index 3e58a0c7bd4..fd67914822f 100644 --- a/src/platforms/stlinkv3/platform.c +++ b/src/platforms/stlinkv3/platform.c @@ -1,8 +1,9 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2022-2023 1BitSquared + * Copyright (C) 2022-2024 1BitSquared * Portions (C) 2020-2021 Stoyan Shopov + * Modified by Rachel Mant * * 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 @@ -18,8 +19,8 @@ * along with this program. If not, see . */ -/* This file provides the platform specific functions for the STLINK-V3 - * implementation. +/* + * This file provides the platform specific functions for the ST-Link v3 implementation. */ #include "general.h" @@ -114,7 +115,7 @@ int platform_hwversion(void) void platform_nrst_set_val(bool assert) { - gpio_set_val(SRST_PORT, SRST_PIN, !assert); + gpio_set_val(NRST_PORT, NRST_PIN, !assert); if (assert) { for (volatile size_t i = 0; i < 10000; i++) continue; @@ -123,7 +124,7 @@ void platform_nrst_set_val(bool assert) bool platform_nrst_get_val() { - return gpio_get(SRST_PORT, SRST_PIN) == 0; + return gpio_get(NRST_PORT, NRST_PIN) == 0; } const char *platform_target_voltage(void) @@ -182,9 +183,9 @@ void platform_init(void) adc_power_on(ADC1); /* Configure srst pin. */ - gpio_set_output_options(SRST_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, SRST_PIN); - gpio_mode_setup(SRST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SRST_PIN); - gpio_set(SRST_PORT, SRST_PIN); + gpio_set_output_options(NRST_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, NRST_PIN); + gpio_mode_setup(NRST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, NRST_PIN); + gpio_set(NRST_PORT, NRST_PIN); gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); gpio_set_output_options(TMS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, TMS_PIN); diff --git a/src/platforms/stlinkv3/platform.h b/src/platforms/stlinkv3/platform.h index 48d6189d922..b43c14f1e36 100644 --- a/src/platforms/stlinkv3/platform.h +++ b/src/platforms/stlinkv3/platform.h @@ -32,12 +32,14 @@ #include #include +#define PLATFORM_HAS_TRACESWO + #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG extern bool debug_bmp; #endif -#define PLATFORM_IDENT "STLINK-V3 " +#define PLATFORM_IDENT "(ST-Link v3) " #define BOOTMAGIC0 0xb007da7aU #define BOOTMAGIC1 0xbaadfeedU @@ -61,8 +63,11 @@ extern bool debug_bmp; #define SWDIO_PIN TMS_PIN #define SWCLK_PIN TCK_PIN -#define SRST_PORT GPIOA -#define SRST_PIN GPIO6 +#define NRST_PORT GPIOA +#define NRST_PIN GPIO6 + +#define SWO_PORT GPIOD +#define SWO_PIN GPIO2 #define TMS_DRIVE_PORT GPIOA #define TMS_DRIVE_PIN GPIO7 @@ -79,11 +84,10 @@ extern bool debug_bmp; #define MCO1_PIN GPIO8 #define MCO1_AF 0 -#define PLATFORM_HAS_TRACESWO 1 -#define NUM_TRACE_PACKETS (16) +#define NUM_TRACE_PACKETS 16U #define SWDIO_MODE_REG GPIO_MODER(TMS_PORT) -#define SWDIO_MODE_REG_MULT (1 << (9 << 1)) +#define SWDIO_MODE_REG_MULT (1U << (9U << 1U)) #define TMS_SET_MODE() \ gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); \ diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 62a5f408665..ea1945414ce 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -52,6 +52,9 @@ extern bool debug_bmp; #define SWDIO_PIN TMS_PIN #define SWCLK_PIN TCK_PIN +#define SWO_PORT GPIOB +#define SWO_PIN GPIO3 + /* Use PC14 for a "dummy" UART LED so we can observere at least with scope */ #define LED_PORT_UART GPIOC #define LED_UART GPIO14 @@ -125,13 +128,20 @@ extern bool debug_bmp; #if TRACESWO_PROTOCOL == 1 /* Use TIM2 Input 2 (from PB3/TDO with Remap) */ -#define TRACE_TIM TIM2 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) -#define TRACE_IRQ NVIC_TIM2_IRQ -#define TRACE_ISR(x) tim2_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI2 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI2FP2 -/* was TIM_SMCR_TS_IT1FP2 from 2010 API */ +#define TRACE_TIM TIM2 +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) +#define TRACE_IRQ NVIC_TIM2_IRQ +#define TRACE_ISR(x) tim2_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI2 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI2FP2 #elif TRACESWO_PROTOCOL == 2 From 346381893aa9033de2f0e67a6d109cced8556247 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 13 Aug 2024 13:52:12 +0100 Subject: [PATCH 04/48] common/stm32/traceswo: Cleanup and documentation comments to try and light the way through the logic --- src/platforms/common/stm32/traceswo.c | 78 +++++++++++++++++---------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index 5de1c7b7bfa..a810aa9b95a 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -49,6 +49,9 @@ #include #include +/* How many timer clock cycles the half period of a cycle of the SWO signal is allowed to be off by */ +#define ALLOWED_PERIOD_ERROR 5U + /* SWO decoding */ static bool decoding = false; @@ -134,17 +137,15 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) trace_usb_buf_size = 0; } -#define ALLOWED_DUTY_ERROR 5 - void TRACE_ISR(void) { - uint16_t status = TIM_SR(TRACE_TIM); - static uint16_t bt; + static uint16_t bit_time = 0U; static uint8_t lastbit; - static uint8_t decbuf[17]; + static uint8_t decbuf[16U]; static uint8_t decbuf_pos; - static uint8_t halfbit; - static uint8_t notstart; + static bool halfbit = false; + static bool notstart = false; + const uint16_t status = TIM_SR(TRACE_TIM); /* Reset decoder state if capture overflowed */ if (status & (TIM_SR_CC1OF | TIM_SR_UIF)) { @@ -153,52 +154,73 @@ void TRACE_ISR(void) goto flush_and_reset; } - const uint16_t cycle = TIM_CCR1(TRACE_TIM); - uint16_t duty = TIM_CCR2(TRACE_TIM); + const uint32_t cycle_period = TRACE_CC_RISING; + const uint32_t mark_period = TRACE_CC_FALLING; /* Reset decoder state if crazy things happened */ - if ((bt && (duty / bt > 2U || duty / bt == 0)) || duty == 0) + if ((bit_time && (mark_period / bit_time > 2U || mark_period / bit_time == 0)) || mark_period == 0) goto flush_and_reset; if (!(status & TIM_SR_CC1IF)) - notstart = 1; + notstart = true; - if (!bt) { + /* If the bit time is not yet known */ + if (bit_time == 0U) { + /* Are we here because we got an interrupt but not for the rising edge capture channel? */ if (notstart) { - notstart = 0; + /* We're are, so leave early */ + notstart = false; return; } - /* First bit, sync decoder */ - duty -= ALLOWED_DUTY_ERROR; - const uint16_t duty_cycle = cycle / duty; - if (duty_cycle != 2U && duty_cycle != 3U) + /* + * We're here because of the rising edge, so we've got our first bit. + * Calculate the ratio of the mark period to the space period within a cycle + */ + const uint32_t duty_ratio = cycle_period / (mark_period - ALLOWED_PERIOD_ERROR); + /* + * Check that the duty cycle ratio is between 2:1 and 3:1, indicating an + * aproximately even mark-to-space ratio + */ + if (duty_ratio < 2U || duty_ratio > 3U) return; - bt = duty; + /* + * Now we've established a valid duty cycle ratio, store the mark period as the bit timing and + * initialise the capture engine: start with the last bit we decoded as a 1, that we're not dealing + * with a half bit (such as one caused by a stop bit), and configure the timer maximum period + * to 3x the current max bit period, enabling overflow checking now we have an overflow target for + * the timer + */ + bit_time = mark_period - ALLOWED_PERIOD_ERROR; lastbit = 1; - halfbit = 0; - timer_set_period(TRACE_TIM, duty * 6U); + halfbit = false; + timer_set_period(TRACE_TIM, cycle_period * 3U); timer_clear_flag(TRACE_TIM, TIM_SR_UIF); timer_enable_irq(TRACE_TIM, TIM_DIER_UIE); } else { - /* If high time is extended we need to flip the bit */ - if (duty / bt > 1U) { - if (!halfbit) /* lost sync somehow */ + /* + * We know the period of a half cycle, so check that the half period of the new bit isn't too long. + * If it is, then this was a bit flip (representing either a 0 -> 1, or 1 -> 0 transition). + */ + if (mark_period >= bit_time * 2U) { + /* If we're processing a half bit, then this probably actually means we lost sync */ + if (!halfbit) goto flush_and_reset; - halfbit = 0; + halfbit = false; lastbit ^= 1U; } + /* Store the new bit in the buffer and move along */ decbuf[decbuf_pos >> 3U] |= lastbit << (decbuf_pos & 7U); ++decbuf_pos; } - if (!(status & TIM_SR_CC1IF) || (cycle - duty) / bt > 2) + if (!(status & TIM_SR_CC1IF) || (cycle_period - mark_period) / bit_time > 2) goto flush_and_reset; - if ((cycle - duty) / bt > 1) { + if ((cycle_period - mark_period) / bit_time > 1) { /* If low time extended we need to pack another bit. */ if (halfbit) /* this is a valid stop-bit or we lost sync */ goto flush_and_reset; - halfbit = 1; + halfbit = true; lastbit ^= 1U; decbuf[decbuf_pos >> 3U] |= lastbit << (decbuf_pos & 7U); ++decbuf_pos; @@ -211,7 +233,7 @@ void TRACE_ISR(void) timer_set_period(TRACE_TIM, -1); timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); trace_buf_push(decbuf, decbuf_pos >> 3U); - bt = 0; + bit_time = 0; decbuf_pos = 0; memset(decbuf, 0, sizeof(decbuf)); } From 53ae959319fdcf302b7cbeaa129625bc496e0f18 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 14 Aug 2024 11:25:00 +0100 Subject: [PATCH 05/48] common/stm32/traceswo: More refinements and unbundling the capture buffer and state variables from the IRQ handler to allow `traceswo_deinit()` to reset state properly --- src/platforms/common/stm32/traceswo.c | 83 +++++++++++++++++---------- src/platforms/native/platform.h | 18 ++++-- 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index a810aa9b95a..b0a24bf8724 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -55,9 +55,16 @@ /* SWO decoding */ static bool decoding = false; -static uint8_t trace_usb_buf[64]; +/* Buffer and fill level for USB */ +static uint8_t trace_usb_buf[64U]; static uint8_t trace_usb_buf_size; +/* Manchester bit capture buffer and current bit index */ +static uint8_t trace_data[16U]; +static uint8_t trace_data_bit_index = 0; +/* Number of timer clock cycles that describe half a bit period as detected */ +static uint32_t trace_half_bit_period = 0U; + void traceswo_init(const uint32_t swo_chan_bitmask) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ @@ -86,7 +93,7 @@ void traceswo_init(const uint32_t swo_chan_bitmask) /* Enable capture interrupt */ nvic_set_priority(TRACE_IRQ, IRQ_PRI_TRACE); nvic_enable_irq(TRACE_IRQ); - timer_enable_irq(TRACE_TIM, TIM_DIER_CC1IE); + timer_enable_irq(TRACE_TIM, TRACE_ITR_RISING); /* Enable the capture channels */ timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); @@ -106,7 +113,13 @@ void traceswo_init(const uint32_t swo_chan_bitmask) void traceswo_deinit(void) { + /* Disable the timer capturing the incomming data stream */ timer_disable_counter(TRACE_TIM); + timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_OFF); + + /* Reset state so that when init is called we wind up in a fresh capture state */ + trace_data_bit_index = 0U; + trace_half_bit_period = 0U; } void trace_buf_push(uint8_t *buf, int len) @@ -139,18 +152,15 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) void TRACE_ISR(void) { - static uint16_t bit_time = 0U; static uint8_t lastbit; - static uint8_t decbuf[16U]; - static uint8_t decbuf_pos; static bool halfbit = false; static bool notstart = false; const uint16_t status = TIM_SR(TRACE_TIM); /* Reset decoder state if capture overflowed */ - if (status & (TIM_SR_CC1OF | TIM_SR_UIF)) { - timer_clear_flag(TRACE_TIM, TIM_SR_CC1OF | TIM_SR_UIF); - if (!(status & (TIM_SR_CC2IF | TIM_SR_CC1IF))) + if (status & (TRACE_STATUS_OVERFLOW | TIM_SR_UIF)) { + timer_clear_flag(TRACE_TIM, TRACE_STATUS_OVERFLOW | TIM_SR_UIF); + if (!(status & (TRACE_STATUS_RISING | TRACE_STATUS_FALLING))) goto flush_and_reset; } @@ -158,14 +168,17 @@ void TRACE_ISR(void) const uint32_t mark_period = TRACE_CC_FALLING; /* Reset decoder state if crazy things happened */ - if ((bit_time && (mark_period / bit_time > 2U || mark_period / bit_time == 0)) || mark_period == 0) + if ((trace_half_bit_period && + (mark_period / trace_half_bit_period > 2U || mark_period / trace_half_bit_period == 0)) || + mark_period == 0) goto flush_and_reset; - if (!(status & TIM_SR_CC1IF)) + /* Check if we're here for a reason other than a valid cycle capture */ + if (!(status & TRACE_STATUS_RISING)) notstart = true; /* If the bit time is not yet known */ - if (bit_time == 0U) { + if (trace_half_bit_period == 0U) { /* Are we here because we got an interrupt but not for the rising edge capture channel? */ if (notstart) { /* We're are, so leave early */ @@ -173,13 +186,19 @@ void TRACE_ISR(void) return; } /* - * We're here because of the rising edge, so we've got our first bit. + * We're here because of the rising edge, so we've got our first (start) bit. * Calculate the ratio of the mark period to the space period within a cycle + * + * At this point, the waveform for what's come in should look something like one of these two options: + * ▁▁┊╱▔╲▁┊╱▔ ▁▁┊╱▔╲▁┊▁▁╱▔ + * The first sequence is the start bit followed by a 1, and the second is followed instead by a 0 */ - const uint32_t duty_ratio = cycle_period / (mark_period - ALLOWED_PERIOD_ERROR); + const uint32_t adjusted_mark_period = mark_period - ALLOWED_PERIOD_ERROR; + const uint32_t duty_ratio = cycle_period / adjusted_mark_period; /* * Check that the duty cycle ratio is between 2:1 and 3:1, indicating an - * aproximately even mark-to-space ratio + * aproximately even mark-to-space ratio, taking into account the possibility of + * the double space bit time caused by start + 0 */ if (duty_ratio < 2U || duty_ratio > 3U) return; @@ -187,53 +206,59 @@ void TRACE_ISR(void) * Now we've established a valid duty cycle ratio, store the mark period as the bit timing and * initialise the capture engine: start with the last bit we decoded as a 1, that we're not dealing * with a half bit (such as one caused by a stop bit), and configure the timer maximum period - * to 3x the current max bit period, enabling overflow checking now we have an overflow target for + * to 6x the current max half bit period, enabling overflow checking now we have an overflow target for * the timer */ - bit_time = mark_period - ALLOWED_PERIOD_ERROR; + trace_half_bit_period = adjusted_mark_period; lastbit = 1; halfbit = false; - timer_set_period(TRACE_TIM, cycle_period * 3U); + /* XXX: Need to make sure that this isn't setting a value outside the range of the timer */ + timer_set_period(TRACE_TIM, mark_period * 6U); timer_clear_flag(TRACE_TIM, TIM_SR_UIF); timer_enable_irq(TRACE_TIM, TIM_DIER_UIE); } else { /* * We know the period of a half cycle, so check that the half period of the new bit isn't too long. * If it is, then this was a bit flip (representing either a 0 -> 1, or 1 -> 0 transition). + * + * 0 -> 1 transition: ▁▁╱▔┊▔▔╲▁ + * 1 -> 0 transition: ▔▔╲▁┊▁▁╱▔ */ - if (mark_period >= bit_time * 2U) { + if (mark_period >= trace_half_bit_period * 2U) { /* If we're processing a half bit, then this probably actually means we lost sync */ if (!halfbit) goto flush_and_reset; halfbit = false; lastbit ^= 1U; } + /* If this would start a new byte in the data buffer, zero it to start with */ + if ((trace_data_bit_index & 7U) == 0U) + trace_data[trace_data_bit_index >> 3U] = 0U; /* Store the new bit in the buffer and move along */ - decbuf[decbuf_pos >> 3U] |= lastbit << (decbuf_pos & 7U); - ++decbuf_pos; + trace_data[trace_data_bit_index >> 3U] |= lastbit << (trace_data_bit_index & 7U); + ++trace_data_bit_index; } - if (!(status & TIM_SR_CC1IF) || (cycle_period - mark_period) / bit_time > 2) + if (!(status & TRACE_STATUS_RISING) || (cycle_period - mark_period) / trace_half_bit_period > 2) goto flush_and_reset; - if ((cycle_period - mark_period) / bit_time > 1) { + if ((cycle_period - mark_period) / trace_half_bit_period > 1) { /* If low time extended we need to pack another bit. */ if (halfbit) /* this is a valid stop-bit or we lost sync */ goto flush_and_reset; halfbit = true; lastbit ^= 1U; - decbuf[decbuf_pos >> 3U] |= lastbit << (decbuf_pos & 7U); - ++decbuf_pos; + trace_data[trace_data_bit_index >> 3U] |= lastbit << (trace_data_bit_index & 7U); + ++trace_data_bit_index; } - if (decbuf_pos < 128U) + if (trace_data_bit_index < 128U) return; flush_and_reset: timer_set_period(TRACE_TIM, -1); timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); - trace_buf_push(decbuf, decbuf_pos >> 3U); - bit_time = 0; - decbuf_pos = 0; - memset(decbuf, 0, sizeof(decbuf)); + trace_buf_push(trace_data, trace_data_bit_index >> 3U); + trace_data_bit_index = 0; + trace_half_bit_period = 0; } diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index c63d38e11ba..632df911d59 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -300,12 +300,18 @@ extern int hwversion; /* Use TIM3 Input 1 (from PA6/TDO) */ #define TRACE_TIM TIM3 #define TRACE_TIM_CLK_EN() -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define TRACE_IRQ NVIC_TIM3_IRQ +#define TRACE_ISR(x) tim3_isr(x) +#define TRACE_IC_IN TIM_IC_IN_TI1 +#define TRACE_IC_RISING TIM_IC1 +#define TRACE_CC_RISING TIM3_CCR1 +#define TRACE_ITR_RISING TIM_DIER_CC1IE +#define TRACE_STATUS_RISING TIM_SR_CC1IF +#define TRACE_IC_FALLING TIM_IC2 +#define TRACE_CC_FALLING TIM3_CCR2 +#define TRACE_STATUS_FALLING TIM_SR_CC2IF +#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 #endif #define SET_RUN_STATE(state) running_status = (state) From e30317cad79a86d7a8e16f38ee7d8e0d140121b2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 15 Aug 2024 11:14:22 +0100 Subject: [PATCH 06/48] common/stm32/traceswo: Fixed some initialisation order issues and made sure to de-init the SWO GPIO in `traceswo_deinit()` --- src/platforms/common/stm32/traceswo.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index b0a24bf8724..c3aae298203 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -69,8 +69,15 @@ void traceswo_init(const uint32_t swo_chan_bitmask) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ TRACE_TIM_CLK_EN(); + +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) + /* Set any required pin alt-function configuration - TIM3/TIM4/TIM5 are AF2 */ + gpio_mode_setup(SWO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SWO_PIN); + gpio_set_af(SWO_PORT, SWO_TIM_PIN_AF, SWO_PIN); +#else /* Then make sure the IO pin used is properly set up as an input routed to the timer */ gpio_set_mode(SWO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_PIN); +#endif /* * Start setting the timer block up by picking a pair of cross-linked capture channels suitable for the input, @@ -99,16 +106,10 @@ void traceswo_init(const uint32_t swo_chan_bitmask) timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); timer_ic_enable(TRACE_TIM, TRACE_IC_FALLING); - timer_enable_counter(TRACE_TIM); - -#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) - /* AF2: TIM3/TIM4/TIM5 */ - gpio_mode_setup(TDO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, TDO_PIN); - gpio_set_af(TDO_PORT, TRACE_TIM_PIN_AF, TDO_PIN); -#endif - + /* Configure the capture decoder and state, then enable the timer */ traceswo_setmask(swo_chan_bitmask); decoding = swo_chan_bitmask != 0; + timer_enable_counter(TRACE_TIM); } void traceswo_deinit(void) @@ -120,6 +121,13 @@ void traceswo_deinit(void) /* Reset state so that when init is called we wind up in a fresh capture state */ trace_data_bit_index = 0U; trace_half_bit_period = 0U; + +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) + gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); +#else + /* Put the GPIO back into normal service as TDO */ + gpio_set_mode(SWO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_PIN); +#endif } void trace_buf_push(uint8_t *buf, int len) From 70a12f8a791266d52a4ebcaa3563e574db2521b9 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 15 Aug 2024 11:16:45 +0100 Subject: [PATCH 07/48] common/stm32/traceswo: Rebuilt the Manchester decoding logic with plently of comments --- src/platforms/common/stm32/traceswo.c | 121 +++++++++++++++++--------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index c3aae298203..8d464565b4e 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -105,6 +105,8 @@ void traceswo_init(const uint32_t swo_chan_bitmask) /* Enable the capture channels */ timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); timer_ic_enable(TRACE_TIM, TRACE_IC_FALLING); + /* Set the period to an improbable value */ + timer_set_period(TRACE_TIM, UINT32_MAX); /* Configure the capture decoder and state, then enable the timer */ traceswo_setmask(swo_chan_bitmask); @@ -160,9 +162,7 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) void TRACE_ISR(void) { - static uint8_t lastbit; - static bool halfbit = false; - static bool notstart = false; + static uint8_t bit_value; const uint16_t status = TIM_SR(TRACE_TIM); /* Reset decoder state if capture overflowed */ @@ -174,6 +174,7 @@ void TRACE_ISR(void) const uint32_t cycle_period = TRACE_CC_RISING; const uint32_t mark_period = TRACE_CC_FALLING; + const uint32_t space_period = cycle_period - mark_period; /* Reset decoder state if crazy things happened */ if ((trace_half_bit_period && @@ -181,18 +182,12 @@ void TRACE_ISR(void) mark_period == 0) goto flush_and_reset; - /* Check if we're here for a reason other than a valid cycle capture */ - if (!(status & TRACE_STATUS_RISING)) - notstart = true; - /* If the bit time is not yet known */ if (trace_half_bit_period == 0U) { /* Are we here because we got an interrupt but not for the rising edge capture channel? */ - if (notstart) { + if (!(status & TRACE_STATUS_RISING)) /* We're are, so leave early */ - notstart = false; return; - } /* * We're here because of the rising edge, so we've got our first (start) bit. * Calculate the ratio of the mark period to the space period within a cycle @@ -212,59 +207,101 @@ void TRACE_ISR(void) return; /* * Now we've established a valid duty cycle ratio, store the mark period as the bit timing and - * initialise the capture engine: start with the last bit we decoded as a 1, that we're not dealing - * with a half bit (such as one caused by a stop bit), and configure the timer maximum period - * to 6x the current max half bit period, enabling overflow checking now we have an overflow target for - * the timer + * initialise the capture engine: check whether we captured, the start of a 0 bit to set the next + * bit value, and configure the timer maximum period to 6x the current max half bit period, enabling + * overflow checking now we have an overflow target for the timer */ trace_half_bit_period = adjusted_mark_period; - lastbit = 1; - halfbit = false; + bit_value = space_period >= trace_half_bit_period * 2U ? 0U : 1U; /* XXX: Need to make sure that this isn't setting a value outside the range of the timer */ timer_set_period(TRACE_TIM, mark_period * 6U); - timer_clear_flag(TRACE_TIM, TIM_SR_UIF); + timer_clear_flag(TRACE_TIM, TIM_SR_UIF | TRACE_STATUS_OVERFLOW); timer_enable_irq(TRACE_TIM, TIM_DIER_UIE); } else { /* - * We know the period of a half cycle, so check that the half period of the new bit isn't too long. - * If it is, then this was a bit flip (representing either a 0 -> 1, or 1 -> 0 transition). + * We start off needing to store a newly captured bit - the value of which is determined in the *previous* + * traversal of this function. We don't yet worry about whether we're starting half way through a bit or not. * - * 0 -> 1 transition: ▁▁╱▔┊▔▔╲▁ - * 1 -> 0 transition: ▔▔╲▁┊▁▁╱▔ + * If this would start a new byte in the data buffer, zero it to start with */ - if (mark_period >= trace_half_bit_period * 2U) { - /* If we're processing a half bit, then this probably actually means we lost sync */ - if (!halfbit) - goto flush_and_reset; - halfbit = false; - lastbit ^= 1U; - } - /* If this would start a new byte in the data buffer, zero it to start with */ if ((trace_data_bit_index & 7U) == 0U) trace_data[trace_data_bit_index >> 3U] = 0U; /* Store the new bit in the buffer and move along */ - trace_data[trace_data_bit_index >> 3U] |= lastbit << (trace_data_bit_index & 7U); + trace_data[trace_data_bit_index >> 3U] |= bit_value << (trace_data_bit_index & 7U); ++trace_data_bit_index; - } - if (!(status & TRACE_STATUS_RISING) || (cycle_period - mark_period) / trace_half_bit_period > 2) - goto flush_and_reset; + /* + * Having stored a bit, check if we've got a long cycle period - this can happen due to any sequence + * involving at least one bit transition (0 -> 1, 1 -> 0), or a 1 -> STOP sequence: + * 0 -> 1: ▁▁╱▔┊▔▔╲▁ + * 1 -> 0: ▔▔╲▁┊▁▁╱▔ + * 1 -> STOP: ▔▔╲▁┊▁▁▁▁ + * + * An even longer non-stop cycle time occurs when a 0 -> 1 -> 0 sequence is encountered: + * ▁▁╱▔┊▔▔╲▁┊▁▁╱▔ + * + * All of these cases need special handling and can appear to this decoder as part of one of the following: + * 0 -> 1 -> 0: ▁▁╱▔┊▔▔╲▁┊▁▁╱▔ (4x half bit periods) + * 0 -> 1 -> 1: ▁▁╱▔┊▔▔╲▁┊╱▔╲▁ (3x half bit periods) + * 0 -> 1 -> STOP: ▁▁╱▔┊▔▔╲▁┊▁▁▁▁ + * 1 -> 1 -> 0: ▔▔╲▁┊╱▔╲▁┊▁▁╱▔ (3x half bit periods) + * 1 -> 1 -> STOP: ▔▔╲▁┊╱▔╲▁┊▁▁▁▁ + * 1 -> 0 -> STOP: ▔▔╲▁┊▁▁╱▔┊╲▁▁▁ + * + * The bit write that has already occured deals with the lead-in part of all of these. + */ + if (cycle_period >= trace_half_bit_period * 3U) { + /* + * Having determined that we're in a long cycle, we need to figure out which kind. + * If the mark period is short, then whether we're starting half way into a bit determines + * if the next is a 1 (not half way in) or a 0 (half way in). This copies the current bit value. + * If the mark period is long, then this can only occur from a 0 -> 1 transition where we're + * half way into the cycle. Anything else indicates a fault occured. + */ + if (mark_period >= trace_half_bit_period * 2U) { + if (bit_value == 1U) + goto flush_and_reset; /* Something bad happened and we lost sync */ + bit_value = 1U; + } - if ((cycle_period - mark_period) / trace_half_bit_period > 1) { - /* If low time extended we need to pack another bit. */ - if (halfbit) /* this is a valid stop-bit or we lost sync */ - goto flush_and_reset; - halfbit = true; - lastbit ^= 1U; - trace_data[trace_data_bit_index >> 3U] |= lastbit << (trace_data_bit_index & 7U); - ++trace_data_bit_index; + /* + * We now know the value of the extra bit, if it's from anything other than a short mark, long space, + * then we need to store that next bit. + */ + if (mark_period >= trace_half_bit_period * 2U || space_period < trace_half_bit_period * 2U) { + /* If this would overflow the buffer, then do nothing */ + if (trace_data_bit_index < 128U) { + /* If this would start a new byte in the data buffer, zero it to start with */ + if ((trace_data_bit_index & 7U) == 0U) + trace_data[trace_data_bit_index >> 3U] = 0U; + /* Store the new bit in the buffer and move along */ + trace_data[trace_data_bit_index >> 3U] |= bit_value << (trace_data_bit_index & 7U); + ++trace_data_bit_index; + } + } + /* If it's a long space, we just saw a 1 -> 0 transition */ + if (space_period >= trace_half_bit_period * 2U) { + /* Unless of course this was acompanied by a short mark period, in which case it's a STOP bit */ + if (bit_value == 0U) + goto flush_and_reset; + bit_value = 0U; + } + + /* + * We've now written enough data to the buffer, so we have one final check: + * If the cycle has a long space, we need to determine how long to check for STOP bits. + */ + if (space_period >= trace_half_bit_period * 3U) + goto flush_and_reset; + } } + /* If the buffer is not full, and we haven't encountered a STOP bit, we're done here */ if (trace_data_bit_index < 128U) return; flush_and_reset: - timer_set_period(TRACE_TIM, -1); + timer_set_period(TRACE_TIM, UINT32_MAX); timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); trace_buf_push(trace_data, trace_data_bit_index >> 3U); trace_data_bit_index = 0; From 18e47a94cd15ad832ef8c88bde8ae71697761c3c Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 21 Aug 2024 22:15:08 +0100 Subject: [PATCH 08/48] common/stm32/traceswo: Fixed some of the entry conditions and decoder state reset conditions for the IRQ handler --- src/platforms/common/stm32/traceswo.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/traceswo.c index 8d464565b4e..bb3995364d3 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/traceswo.c @@ -52,6 +52,10 @@ /* How many timer clock cycles the half period of a cycle of the SWO signal is allowed to be off by */ #define ALLOWED_PERIOD_ERROR 5U +#define TIM_SR_MASK \ + (TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF | TIM_SR_TIF | TIM_SR_CC1OF | \ + TIM_SR_CC2OF | TIM_SR_CC3OF | TIM_SR_CC4OF) + /* SWO decoding */ static bool decoding = false; @@ -105,6 +109,8 @@ void traceswo_init(const uint32_t swo_chan_bitmask) /* Enable the capture channels */ timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); timer_ic_enable(TRACE_TIM, TRACE_IC_FALLING); + /* Make sure all the status register bits are cleared prior to enabling the counter */ + timer_clear_flag(TRACE_TIM, TIM_SR_MASK); /* Set the period to an improbable value */ timer_set_period(TRACE_TIM, UINT32_MAX); @@ -165,21 +171,22 @@ void TRACE_ISR(void) static uint8_t bit_value; const uint16_t status = TIM_SR(TRACE_TIM); - /* Reset decoder state if capture overflowed */ - if (status & (TRACE_STATUS_OVERFLOW | TIM_SR_UIF)) { - timer_clear_flag(TRACE_TIM, TRACE_STATUS_OVERFLOW | TIM_SR_UIF); - if (!(status & (TRACE_STATUS_RISING | TRACE_STATUS_FALLING))) - goto flush_and_reset; + const uint32_t cycle_period = TRACE_CC_RISING; + /* Check that we entered the handler because of a fresh trigger but have not yet had a chance to capture data */ + if ((status & TRACE_STATUS_RISING) && cycle_period == 0U) { + /* Clear the rising edge flag and wait for it to set again */ + timer_clear_flag(TRACE_TIM, TRACE_STATUS_RISING | TRACE_STATUS_FALLING | TRACE_STATUS_OVERFLOW); + return; } - const uint32_t cycle_period = TRACE_CC_RISING; + timer_clear_flag(TRACE_TIM, TRACE_STATUS_RISING | TRACE_STATUS_FALLING | TRACE_STATUS_OVERFLOW | TIM_SR_UIF); + const uint32_t mark_period = TRACE_CC_FALLING; const uint32_t space_period = cycle_period - mark_period; /* Reset decoder state if crazy things happened */ - if ((trace_half_bit_period && - (mark_period / trace_half_bit_period > 2U || mark_period / trace_half_bit_period == 0)) || - mark_period == 0) + if (cycle_period <= mark_period || (trace_half_bit_period && mark_period < trace_half_bit_period) || + mark_period == 0U) goto flush_and_reset; /* If the bit time is not yet known */ From 5780c8cab3defb3a407838b64f7711727e4abe46 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 8 Sep 2024 14:21:39 +0100 Subject: [PATCH 09/48] command: Cleanup in the SWO command implementation and correction of the command help text --- src/command.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/command.c b/src/command.c index e9dfc5282f2..9a78857b5aa 100644 --- a/src/command.c +++ b/src/command.c @@ -110,9 +110,9 @@ const command_s cmd_list[] = { #endif #ifdef PLATFORM_HAS_TRACESWO #if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2 - {"traceswo", cmd_traceswo, "Start trace capture, NRZ mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, + {"traceswo", cmd_traceswo, "Start SWO capture, NRZ mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, #else - {"traceswo", cmd_traceswo, "Start trace capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, + {"traceswo", cmd_traceswo, "Start SWO capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, #endif #endif {"heapinfo", cmd_heapinfo, "Set semihosting heapinfo: HEAP_BASE HEAP_LIMIT STACK_BASE STACK_LIMIT"}, @@ -659,17 +659,15 @@ static bool cmd_traceswo(target_s *t, int argc, const char **argv) { (void)t; bool mode = false; - if (argc >= 2) { - if (!parse_enable_or_disable(argv[1], &mode)) { - gdb_out("Usage: traceswo [2000000] [decode [0 1 3 31]]\n"); - return false; - } + if (argc >= 2 && !parse_enable_or_disable(argv[1], &mode)) { + gdb_out("Usage: traceswo [2000000] [decode [0 1 3 31]]\n"); + return false; } - if (mode) { + + if (mode) return cmd_traceswo_enable(argc - 1, argv + 1); - } else { + else return cmd_traceswo_disable(); - } } #endif @@ -677,10 +675,9 @@ static bool cmd_traceswo(target_s *t, int argc, const char **argv) static bool cmd_debug_bmp(target_s *t, int argc, const char **argv) { (void)t; - if (argc == 2) { - if (!parse_enable_or_disable(argv[1], &debug_bmp)) - return false; - } else if (argc > 2) { + if (argc == 2 && !parse_enable_or_disable(argv[1], &debug_bmp)) + return false; + if (argc > 2) { gdb_outf("usage: monitor debug [enable|disable]\n"); return false; } From e37ca730d8e19f60131aa71a79546d754014995b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 00:04:38 +0100 Subject: [PATCH 10/48] common/stm32: Renamed the SWO implementations to make it clearer which does what --- src/Makefile | 8 ++- src/command.c | 2 +- src/platforms/common/aux_serial.c | 4 +- .../common/blackpill-f4/Makefile.inc | 28 +++++++--- src/platforms/common/blackpill-f4/meson.build | 4 +- src/platforms/common/stm32/meson.build | 10 ++-- .../{traceswodecode.c => swo_itm_decode.c} | 2 +- .../stm32/{traceswo.c => swo_manchester.c} | 2 +- .../stm32/{traceswoasync.c => swo_uart.c} | 2 +- .../{traceswoasync_f723.c => swo_uart_f723.c} | 2 +- src/platforms/common/{traceswo.h => swo.h} | 6 +-- src/platforms/common/tm4c/meson.build | 2 +- .../common/tm4c/{traceswo.c => swo_uart.c} | 0 src/platforms/common/usb_serial.c | 2 +- src/platforms/ctxlink/Makefile.inc | 36 ++++++++----- src/platforms/ctxlink/meson.build | 4 +- src/platforms/f072/Makefile.inc | 13 ++--- src/platforms/f072/meson.build | 2 +- src/platforms/f3/Makefile.inc | 13 ++--- src/platforms/f3/meson.build | 2 +- src/platforms/f4discovery/Makefile.inc | 13 ++--- src/platforms/f4discovery/meson.build | 2 +- src/platforms/hydrabus/Makefile.inc | 13 ++--- src/platforms/hydrabus/meson.build | 2 +- src/platforms/launchpad-icdi/Makefile.inc | 6 +-- src/platforms/native/Makefile.inc | 31 ++++++++--- src/platforms/native/meson.build | 2 +- src/platforms/stlink/Makefile.inc | 53 +++++++++++-------- src/platforms/stlink/meson.build | 6 +-- src/platforms/stlinkv3/Makefile.inc | 15 +++--- src/platforms/stlinkv3/meson.build | 4 +- src/platforms/swlink/Makefile.inc | 40 +++++++++----- src/platforms/swlink/meson.build | 2 +- 33 files changed, 205 insertions(+), 128 deletions(-) rename src/platforms/common/stm32/{traceswodecode.c => swo_itm_decode.c} (99%) rename src/platforms/common/stm32/{traceswo.c => swo_manchester.c} (99%) rename src/platforms/common/stm32/{traceswoasync.c => swo_uart.c} (99%) rename src/platforms/common/stm32/{traceswoasync_f723.c => swo_uart_f723.c} (99%) rename src/platforms/common/{traceswo.h => swo.h} (93%) rename src/platforms/common/tm4c/{traceswo.c => swo_uart.c} (100%) diff --git a/src/Makefile b/src/Makefile index 28f12fe6bb1..d75ef1e8e9c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,7 +41,7 @@ SRC = \ adiv5.c \ adiv5_jtag.c \ adiv5_swd.c \ - apollo3.c \ + apollo3.c \ adiv6.c \ command.c \ cortex.c \ @@ -106,6 +106,12 @@ ifneq ($(PROBE_HOST), ctxLink) SRC += gdb_if.c endif +# Check if the old name for the SWO encoding setting has been used +ifdef TRACESWO_PROTOCOL + $(warning the TRACESWO_PROTOCOL variable is deprecated, please use SWO_ENCODING instead) + SWO_ENCODING = $(TRACESWO_PROTOCOL) +endif + ifeq (,$(filter all_platforms,$(MAKECMDGOALS))) include $(PLATFORM_DIR)/Makefile.inc endif diff --git a/src/command.c b/src/command.c index 9a78857b5aa..040d8a3f41e 100644 --- a/src/command.c +++ b/src/command.c @@ -47,7 +47,7 @@ #ifdef PLATFORM_HAS_TRACESWO #include "serialno.h" -#include "traceswo.h" +#include "swo.h" #include "usb.h" #endif diff --git a/src/platforms/common/aux_serial.c b/src/platforms/common/aux_serial.c index 12d5bf065da..5d44dfb37d1 100644 --- a/src/platforms/common/aux_serial.c +++ b/src/platforms/common/aux_serial.c @@ -37,9 +37,9 @@ #include "aux_serial.h" static char aux_serial_receive_buffer[AUX_UART_BUFFER_SIZE]; -/* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ +/* FIFO in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ static uint16_t aux_serial_receive_write_index = 0; -/* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ +/* FIFO out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ static uint16_t aux_serial_receive_read_index = 0; #if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F4) || defined(STM32F7) diff --git a/src/platforms/common/blackpill-f4/Makefile.inc b/src/platforms/common/blackpill-f4/Makefile.inc index 79cbd5e768d..34bdbcfb389 100644 --- a/src/platforms/common/blackpill-f4/Makefile.inc +++ b/src/platforms/common/blackpill-f4/Makefile.inc @@ -57,18 +57,30 @@ VPATH += \ SRC += \ blackpill-f4.c \ - traceswodecode.c \ serialno.c \ timing.c \ - timing_stm32.c + timing_stm32.c \ + swo.c \ + swo_itm_decode.c -ifeq ($(TRACESWO_PROTOCOL), 1) -SRC += traceswo.c -CFLAGS += -DTRACESWO_PROTOCOL=1 -else -SRC += traceswoasync.c -CFLAGS += -DTRACESWO_PROTOCOL=2 +# If SWO_ENCODING has not been given, default it to including both modes +ifndef SWO_ENCODING + SWO_ENCODING = 3 +endif + +# Include the files for either: Manchester-only (1), UART-only (2) or both modes (3) +ifeq ($(SWO_ENCODING), 1) + SRC += swo_manchester.c +else ifeq ($(SWO_ENCODING), 2) + SRC += swo_uart.c +else ifeq ($(SWO_ENCODING), 3) + SRC += \ + swo_manchester.c \ + swo_uart.c +else # If we got some other value, that's an error so report it + $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif +CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) ifneq ($(BMD_BOOTLOADER), 1) all: blackmagic.bin diff --git a/src/platforms/common/blackpill-f4/meson.build b/src/platforms/common/blackpill-f4/meson.build index a554b3f1d03..154e9811b1d 100644 --- a/src/platforms/common/blackpill-f4/meson.build +++ b/src/platforms/common/blackpill-f4/meson.build @@ -72,9 +72,9 @@ if trace_protocol == '3' endif probe_blackpill_args += [f'-DTRACESWO_PROTOCOL=@trace_protocol@'] if trace_protocol == '1' - probe_blackpill_dependencies = fixme_platform_stm32_traceswo + probe_blackpill_dependencies = platform_stm32_swo_manchester else - probe_blackpill_dependencies = fixme_platform_stm32_traceswoasync + probe_blackpill_dependencies = platform_stm32_swo_uart endif if bmd_bootloader diff --git a/src/platforms/common/stm32/meson.build b/src/platforms/common/stm32/meson.build index 1cd416fcb56..e2f9ebb5515 100644 --- a/src/platforms/common/stm32/meson.build +++ b/src/platforms/common/stm32/meson.build @@ -34,14 +34,14 @@ platform_stm32_sources = files( 'gdb_if.c', 'serialno.c', 'timing_stm32.c', - 'traceswodecode.c', + 'swo_itm_decode.c', ) # TODO: add proper traceswoasync support -# This is a temporary hack to allow selecting traceswoasync vs traceswo implementation -fixme_platform_stm32_traceswo = declare_dependency(sources: files('traceswo.c')) -fixme_platform_stm32_traceswoasync = declare_dependency(sources: files('traceswoasync.c')) -fixme_platform_stm32f7_traceswoasync = declare_dependency(sources: files('traceswoasync_f723.c')) +# This is a temporary hack to allow selecting swo_manchester vs swo_uart implementation +platform_stm32_swo_manchester = declare_dependency(sources: files('swo_manchester.c')) +platform_stm32_swo_uart = declare_dependency(sources: files('swo_uart.c')) +platform_stm32f7_swo_uart = declare_dependency(sources: files('swo_uart_f723.c')) # RTT support handling if get_option('rtt_support') diff --git a/src/platforms/common/stm32/traceswodecode.c b/src/platforms/common/stm32/swo_itm_decode.c similarity index 99% rename from src/platforms/common/stm32/traceswodecode.c rename to src/platforms/common/stm32/swo_itm_decode.c index 6d04447bcce..ee853f3adfd 100644 --- a/src/platforms/common/stm32/traceswodecode.c +++ b/src/platforms/common/stm32/swo_itm_decode.c @@ -20,7 +20,7 @@ #include "general.h" #include "usb_serial.h" -#include "traceswo.h" +#include "swo.h" /* SWO decoding */ /* data is static in case swo packet is astride two buffers */ diff --git a/src/platforms/common/stm32/traceswo.c b/src/platforms/common/stm32/swo_manchester.c similarity index 99% rename from src/platforms/common/stm32/traceswo.c rename to src/platforms/common/stm32/swo_manchester.c index bb3995364d3..a1de67f72e6 100644 --- a/src/platforms/common/stm32/traceswo.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -43,7 +43,7 @@ #include "general.h" #include "platform.h" #include "usb.h" -#include "traceswo.h" +#include "swo.h" #include #include diff --git a/src/platforms/common/stm32/traceswoasync.c b/src/platforms/common/stm32/swo_uart.c similarity index 99% rename from src/platforms/common/stm32/traceswoasync.c rename to src/platforms/common/stm32/swo_uart.c index af8f58225a9..8f24b8bfa16 100644 --- a/src/platforms/common/stm32/traceswoasync.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -31,7 +31,7 @@ #include "general.h" #include "platform.h" #include "usb.h" -#include "traceswo.h" +#include "swo.h" #include #include diff --git a/src/platforms/common/stm32/traceswoasync_f723.c b/src/platforms/common/stm32/swo_uart_f723.c similarity index 99% rename from src/platforms/common/stm32/traceswoasync_f723.c rename to src/platforms/common/stm32/swo_uart_f723.c index 59c439d3cb8..08a3617c143 100644 --- a/src/platforms/common/stm32/traceswoasync_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -33,7 +33,7 @@ #include "general.h" #include "platform.h" #include "usb.h" -#include "traceswo.h" +#include "swo.h" #include #include diff --git a/src/platforms/common/traceswo.h b/src/platforms/common/swo.h similarity index 93% rename from src/platforms/common/traceswo.h rename to src/platforms/common/swo.h index f4b356a87e8..3fed28bc348 100644 --- a/src/platforms/common/traceswo.h +++ b/src/platforms/common/swo.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef PLATFORMS_COMMON_TRACESWO_H -#define PLATFORMS_COMMON_TRACESWO_H +#ifndef PLATFORMS_COMMON_SWO_H +#define PLATFORMS_COMMON_SWO_H #include @@ -44,4 +44,4 @@ 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 /* PLATFORMS_COMMON_TRACESWO_H */ +#endif /* PLATFORMS_COMMON_SWO_H */ diff --git a/src/platforms/common/tm4c/meson.build b/src/platforms/common/tm4c/meson.build index 0834ced13aa..61e0363f636 100644 --- a/src/platforms/common/tm4c/meson.build +++ b/src/platforms/common/tm4c/meson.build @@ -32,7 +32,7 @@ platform_tm4c_includes = include_directories('.') platform_tm4c_sources = files( 'gdb_if.c', - 'traceswo.c', + 'swo_uart.c', ) platform_tm4c_args = [ diff --git a/src/platforms/common/tm4c/traceswo.c b/src/platforms/common/tm4c/swo_uart.c similarity index 100% rename from src/platforms/common/tm4c/traceswo.c rename to src/platforms/common/tm4c/swo_uart.c diff --git a/src/platforms/common/usb_serial.c b/src/platforms/common/usb_serial.c index 46550a3b4d4..b7ebddf9a66 100644 --- a/src/platforms/common/usb_serial.c +++ b/src/platforms/common/usb_serial.c @@ -46,7 +46,7 @@ #include "gdb_if.h" #include "usb_serial.h" #ifdef PLATFORM_HAS_TRACESWO -#include "traceswo.h" +#include "swo.h" #endif #include "aux_serial.h" #include "rtt.h" diff --git a/src/platforms/ctxlink/Makefile.inc b/src/platforms/ctxlink/Makefile.inc index 5c6279415ee..efec7905b65 100644 --- a/src/platforms/ctxlink/Makefile.inc +++ b/src/platforms/ctxlink/Makefile.inc @@ -17,19 +17,31 @@ LDFLAGS = -lopencm3_stm32f4 \ VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - serialno.c \ - timing.c \ - timing_stm32.c - -ifeq ($(TRACESWO_PROTOCOL), 1) -SRC += traceswo.c -CFLAGS += -DTRACESWO_PROTOCOL=1 -else -SRC += traceswoasync.c -CFLAGS += -DTRACESWO_PROTOCOL=2 + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_itm_decode.c + +# If SWO_ENCODING has not been given, default it to including both modes +ifndef SWO_ENCODING + SWO_ENCODING = 3 +endif + +# Include the files for either: Manchester-only (1), UART-only (2) or both modes (3) +ifeq ($(SWO_ENCODING), 1) + SRC += swo_manchester.c +else ifeq ($(SWO_ENCODING), 2) + SRC += swo_uart.c +else ifeq ($(SWO_ENCODING), 3) + SRC += \ + swo_manchester.c \ + swo_uart.c +else # If we got some other value, that's an error so report it + $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif +CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) all: blackmagic.bin diff --git a/src/platforms/ctxlink/meson.build b/src/platforms/ctxlink/meson.build index 4a4c1418cba..46f3e2b4506 100644 --- a/src/platforms/ctxlink/meson.build +++ b/src/platforms/ctxlink/meson.build @@ -42,9 +42,9 @@ if trace_protocol == '3' endif probe_ctxlink_args += [f'-DTRACESWO_PROTOCOL=@trace_protocol@'] if trace_protocol == '1' - probe_ctxlink_dependencies = fixme_platform_stm32_traceswo + probe_ctxlink_dependencies = platform_stm32_swo_manchester else - probe_ctxlink_dependencies = fixme_platform_stm32_traceswoasync + probe_ctxlink_dependencies = platform_stm32_swo_uart endif probe_ctxlink_commonn_link_args = [ diff --git a/src/platforms/f072/Makefile.inc b/src/platforms/f072/Makefile.inc index 5e07ad24f47..846d1fc6998 100644 --- a/src/platforms/f072/Makefile.inc +++ b/src/platforms/f072/Makefile.inc @@ -14,12 +14,13 @@ LDFLAGS = -lopencm3_stm32f0 -Lplatforms/f072 \ VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - traceswo.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_manchester.c \ + swo_itm_decode.c all: blackmagic.bin blackmagic.elf: libopencm3_stm32f0 diff --git a/src/platforms/f072/meson.build b/src/platforms/f072/meson.build index 383594906cb..8678cdc56b3 100644 --- a/src/platforms/f072/meson.build +++ b/src/platforms/f072/meson.build @@ -46,7 +46,7 @@ probe_host = declare_dependency( sources: probe_f072_sources, compile_args: probe_f072_args, link_args: probe_f072_link_args, - dependencies: [platform_common, platform_stm32f0, fixme_platform_stm32_traceswo], + dependencies: [platform_common, platform_stm32f0, platform_stm32_swo_manchester], ) summary( diff --git a/src/platforms/f3/Makefile.inc b/src/platforms/f3/Makefile.inc index 5ebc633a017..95fbda10181 100644 --- a/src/platforms/f3/Makefile.inc +++ b/src/platforms/f3/Makefile.inc @@ -16,12 +16,13 @@ LDFLAGS = --specs=nano.specs -lopencm3_stm32f3 -Lplatforms/f3 \ VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - traceswo.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_manchester.c \ + swo_itm_decode.c all: blackmagic.bin blackmagic.elf: libopencm3_stm32f3 diff --git a/src/platforms/f3/meson.build b/src/platforms/f3/meson.build index 717da951aeb..aa230a53a59 100644 --- a/src/platforms/f3/meson.build +++ b/src/platforms/f3/meson.build @@ -46,7 +46,7 @@ probe_host = declare_dependency( sources: probe_f3_sources, compile_args: probe_f3_args, link_args: probe_f3_link_args, - dependencies: [platform_common, platform_stm32f3, fixme_platform_stm32_traceswo], + dependencies: [platform_common, platform_stm32f3, platform_stm32_swo_manchester], ) summary( diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 2525742a9bf..b12c8743992 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -26,12 +26,13 @@ endif VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - traceswo.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_manchester.c \ + swo_itm_decode.c ifneq ($(BMP_BOOTLOADER), 1) all: blackmagic.bin diff --git a/src/platforms/f4discovery/meson.build b/src/platforms/f4discovery/meson.build index ca7089b6034..302ebd3f644 100644 --- a/src/platforms/f4discovery/meson.build +++ b/src/platforms/f4discovery/meson.build @@ -57,7 +57,7 @@ probe_host = declare_dependency( sources: probe_f4discovery_sources, compile_args: probe_f4discovery_args, link_args: probe_f4discovery_commonn_link_args + probe_f4discovery_link_args, - dependencies: [platform_common, platform_stm32f4, fixme_platform_stm32_traceswo], + dependencies: [platform_common, platform_stm32f4, platform_stm32_swo_manchester], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/hydrabus/Makefile.inc b/src/platforms/hydrabus/Makefile.inc index 66b21464047..a2f7c66d193 100644 --- a/src/platforms/hydrabus/Makefile.inc +++ b/src/platforms/hydrabus/Makefile.inc @@ -16,12 +16,13 @@ LDFLAGS = -lopencm3_stm32f4 -Lplatforms/hydrabus \ VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - traceswo.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_manchester.c \ + swo_itm_decode.c all: blackmagic.bin blackmagic.hex diff --git a/src/platforms/hydrabus/meson.build b/src/platforms/hydrabus/meson.build index 83a5c245045..d80924d33ae 100644 --- a/src/platforms/hydrabus/meson.build +++ b/src/platforms/hydrabus/meson.build @@ -48,7 +48,7 @@ probe_host = declare_dependency( sources: probe_hydrabus_sources, compile_args: probe_hydrabus_args, link_args: probe_hydrabus_link_args, - dependencies: [platform_common, platform_stm32f4, fixme_platform_stm32_traceswo], + dependencies: [platform_common, platform_stm32f4, platform_stm32_swo_manchester], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/launchpad-icdi/Makefile.inc b/src/platforms/launchpad-icdi/Makefile.inc index f74471643c1..7d378d25128 100644 --- a/src/platforms/launchpad-icdi/Makefile.inc +++ b/src/platforms/launchpad-icdi/Makefile.inc @@ -16,9 +16,9 @@ LDFLAGS = -lopencm3_lm4f -Lplatforms/launchpad-icdi \ VPATH += platforms/common/tm4c -SRC += \ +SRC += \ platform.c \ - timing.c \ - traceswo.o + timing.c \ + swo_uart.o all: blackmagic.bin diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 8eb8047dcf5..8555a56325c 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -21,12 +21,31 @@ endif VPATH += platforms/common/stm32 SRC += \ - platform.c \ - traceswodecode.c \ - traceswo.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_itm_decode.c + +# If SWO_ENCODING has not been given, default it to including both modes +ifndef SWO_ENCODING + SWO_ENCODING = 3 +endif + +# Include the files for either: Manchester-only (1), UART-only (2) or both modes (3) +ifeq ($(SWO_ENCODING), 1) + SRC += swo_manchester.c +else ifeq ($(SWO_ENCODING), 2) + SRC += swo_uart.c +else ifeq ($(SWO_ENCODING), 3) + SRC += \ + swo_manchester.c \ + swo_uart.c +else # If we got some other value, that's an error so report it + $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) +endif +CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/native/meson.build b/src/platforms/native/meson.build index 525c8e9cacb..9ab3f90d0c0 100644 --- a/src/platforms/native/meson.build +++ b/src/platforms/native/meson.build @@ -42,7 +42,7 @@ probe_native_args = [ trace_protocol = get_option('trace_protocol') if trace_protocol in ['1', '3'] probe_native_args += [f'-DTRACESWO_PROTOCOL=1'] - probe_native_dependencies = fixme_platform_stm32_traceswo + probe_native_dependencies = platform_stm32_swo_manchester else error('Unsupported SWO mode requested') endif diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index ff3ce06ba29..7d0baa843df 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -3,55 +3,66 @@ ST_BOOTLOADER ?= CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy -OPT_FLAGS = -Os CFLAGS += -mcpu=cortex-m3 -mthumb -DSTM32F1 -I../deps/libopencm3/include \ -I platforms/common/stm32 LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Lplatforms/stlink \ -Tstlink.ld --specs=nano.specs -nostartfiles -lc \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../deps/libopencm3/lib + ifeq ($(ST_BOOTLOADER), 1) -$(info Load address 0x08004000 for original ST-LinkV2 Bootloader) -CFLAGS += -DST_BOOTLOADER -DDFU_SERIAL_LENGTH=25 -LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8004000 + $(info Load address 0x08004000 for original ST-LinkV2 Bootloader) + CFLAGS += -DST_BOOTLOADER -DDFU_SERIAL_LENGTH=25 + LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8004000 else -CFLAGS += -DDFU_SERIAL_LENGTH=9 -LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 + CFLAGS += -DDFU_SERIAL_LENGTH=9 + LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 endif ifeq ($(ENABLE_DEBUG), 1) -LDFLAGS += --specs=rdimon.specs + LDFLAGS += --specs=rdimon.specs else -LDFLAGS += --specs=nosys.specs + LDFLAGS += --specs=nosys.specs endif ifeq ($(SWIM_AS_UART), 1) -SWIM_NRST_AS_UART=1 -$(warning Deprecation: SWIM_AS_UART has been renamed to SWIM_NRST_AS_UART; it might be ignored in the future) + SWIM_NRST_AS_UART=1 + $(warning Deprecation: SWIM_AS_UART has been renamed to SWIM_NRST_AS_UART; it might be ignored in the future) endif ifeq ($(SWIM_NRST_AS_UART), 1) -CFLAGS += -DSWIM_NRST_AS_UART=1 -else -ifeq ($(TRACESWO_PROTOCOL), 1) -SRC += traceswo.c -CFLAGS += -DTRACESWO_PROTOCOL=1 + CFLAGS += -DSWIM_NRST_AS_UART=1 else -SRC += traceswoasync.c -CFLAGS += -DTRACESWO_PROTOCOL=2 -endif + # If SWO_ENCODING has not been given, default it to including both modes + ifndef SWO_ENCODING + SWO_ENCODING = 3 + endif + + # Include the files for either: Manchester-only (1), UART-only (2) or both modes (3) + ifeq ($(SWO_ENCODING), 1) + SRC += swo_manchester.c + else ifeq ($(SWO_ENCODING), 2) + SRC += swo_uart.c + else ifeq ($(SWO_ENCODING), 3) + SRC += \ + swo_manchester.c \ + swo_uart.c + else # If we got some other value, that's an error so report it + $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) + endif + CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) endif ifeq ($(BLUEPILL), 1) -CFLAGS += -DBLUEPILL=1 + CFLAGS += -DBLUEPILL=1 endif ifeq ($(STLINK_FORCE_CLONE), 1) -CFLAGS += -DSTLINK_FORCE_CLONE=1 + CFLAGS += -DSTLINK_FORCE_CLONE=1 endif ifeq ($(STLINK_V2_ISOL), 1) -CFLAGS += -DSTLINK_V2_ISOL=1 + CFLAGS += -DSTLINK_V2_ISOL=1 endif VPATH += platforms/common/stm32 diff --git a/src/platforms/stlink/meson.build b/src/platforms/stlink/meson.build index 8ec3c5901b7..a70936f06ed 100644 --- a/src/platforms/stlink/meson.build +++ b/src/platforms/stlink/meson.build @@ -75,13 +75,13 @@ if trace_protocol == '3' endif if probe == 'stlink' and stlink_swim_nrst_as_uart probe_stlink_args += ['-DSWIM_NRST_AS_UART=1'] - probe_stlink_dependencies += fixme_platform_stm32_traceswo + probe_stlink_dependencies += platform_stm32_swo_manchester probe_stlink_args += ['-DTRACESWO_PROTOCOL=1'] elif trace_protocol == '1' - probe_stlink_dependencies += fixme_platform_stm32_traceswo + probe_stlink_dependencies += platform_stm32_swo_manchester probe_stlink_args += ['-DTRACESWO_PROTOCOL=1'] elif trace_protocol == '2' - probe_stlink_dependencies += fixme_platform_stm32_traceswoasync + probe_stlink_dependencies += platform_stm32_swo_uart probe_stlink_args += ['-DTRACESWO_PROTOCOL=2'] else error('Unsupported SWO mode requested') diff --git a/src/platforms/stlinkv3/Makefile.inc b/src/platforms/stlinkv3/Makefile.inc index 55ed6709cfb..9256a6990a1 100644 --- a/src/platforms/stlinkv3/Makefile.inc +++ b/src/platforms/stlinkv3/Makefile.inc @@ -30,13 +30,14 @@ endif VPATH += platforms/common/stm32 -SRC += \ - platform.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ - traceswoasync_f723.c \ - traceswodecode.c \ +SRC += \ + platform.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_uart.c \ + swo_itm_decode.c .PHONY: libopencm3_stm32f7 diff --git a/src/platforms/stlinkv3/meson.build b/src/platforms/stlinkv3/meson.build index 7299637a141..a26db5b04cf 100644 --- a/src/platforms/stlinkv3/meson.build +++ b/src/platforms/stlinkv3/meson.build @@ -63,7 +63,7 @@ if trace_protocol == '3' trace_protocol = '2' endif if trace_protocol == '2' - probe_stlinkv3_dependencies = fixme_platform_stm32f7_traceswoasync + probe_stlinkv3_dependencies = platform_stm32f7_swo_uart probe_stlinkv3_args += ['-DTRACESWO_PROTOCOL=2'] else error('Unsupported SWO protocol requested') @@ -74,7 +74,7 @@ probe_host = declare_dependency( sources: probe_stlinkv3_sources, compile_args: probe_stlinkv3_args, link_args: probe_stlinkv3_common_link_args + probe_stlinkv3_link_args, - dependencies: [platform_common, platform_stm32f7, fixme_platform_stm32f7_traceswoasync], + dependencies: [platform_common, platform_stm32f7, probe_stlinkv3_dependencies], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index 00fbf5336be..e85bf9ee1b7 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -19,21 +19,33 @@ endif VPATH += platforms/common/stm32 -SRC += \ - platform.c \ - serialno.c \ - timing.c \ - timing_stm32.c \ - traceswodecode.c \ - platform_common.c - -ifeq ($(TRACESWO_PROTOCOL), 1) -SRC += traceswo.c -CFLAGS += -DTRACESWO_PROTOCOL=1 -else -SRC += traceswoasync.c -CFLAGS += -DTRACESWO_PROTOCOL=2 +SRC += \ + platform.c \ + platform_common.c \ + serialno.c \ + timing.c \ + timing_stm32.c \ + swo.c \ + swo_itm_decode.c + +# If SWO_ENCODING has not been given, default it to including both modes +ifndef SWO_ENCODING + SWO_ENCODING = 3 +endif + +# Include the files for either: Manchester-only (1), UART-only (2) or both modes (3) +ifeq ($(SWO_ENCODING), 1) + SRC += swo_manchester.c +else ifeq ($(SWO_ENCODING), 2) + SRC += swo_uart.c +else ifeq ($(SWO_ENCODING), 3) + SRC += \ + swo_manchester.c \ + swo_uart.c +else # If we got some other value, that's an error so report it + $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif +CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/swlink/meson.build b/src/platforms/swlink/meson.build index 389a1098755..46a8661e7d0 100644 --- a/src/platforms/swlink/meson.build +++ b/src/platforms/swlink/meson.build @@ -68,7 +68,7 @@ probe_host = declare_dependency( sources: probe_swlink_sources, compile_args: probe_swlink_args, link_args: probe_swlink_common_link_args + probe_swlink_link_args, - dependencies: [platform_common, platform_stm32f1, fixme_platform_stm32_traceswoasync], + dependencies: [platform_common, platform_stm32f1, platform_stm32_swo_uart], ) probe_bootloader = declare_dependency( From cf2aeaa52b60cd67d6f2ab27df531ec39c95b290 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 01:30:05 +0100 Subject: [PATCH 11/48] common/stm32/swo_itm_decode: Nomenclature and types corrections for the decoder w/ code simplifications as appropriate --- src/platforms/common/stm32/swo_itm_decode.c | 85 +++++++++++---------- src/platforms/common/stm32/swo_manchester.c | 10 +-- src/platforms/common/stm32/swo_uart.c | 4 +- src/platforms/common/swo.h | 10 +-- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/src/platforms/common/stm32/swo_itm_decode.c b/src/platforms/common/stm32/swo_itm_decode.c index ee853f3adfd..1a34f8cea27 100644 --- a/src/platforms/common/stm32/swo_itm_decode.c +++ b/src/platforms/common/stm32/swo_itm_decode.c @@ -16,60 +16,65 @@ * along with this program. If not, see . */ -/* Print decoded swo stream on the usb serial */ +/* + * This file implements decoding of SWO data when that data is an ITM SWIT data stream. + * It puts the decoded data onto the aux USB serial interface for consumption. + */ #include "general.h" #include "usb_serial.h" #include "swo.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; +static uint8_t itm_decoded_buffer[CDCACM_PACKET_SIZE]; +static uint16_t itm_decoded_buffer_index = 0; +static uint32_t itm_decode_mask = 0; /* bitmask of channels to print */ +static uint8_t itm_packet_length = 0; /* decoder state */ +static bool itm_decode_packet = 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) +uint16_t swo_itm_decode(usbd_device *usbd_dev, uint8_t ep, const uint8_t *data, uint16_t len) { + /* Check if we've got a valid USB device */ + /* XXX: Can this ever actually be false?! */ if (usbd_dev == NULL) - return 0; - const uint8_t *const data = (const uint8_t *)buf; - for (uint16_t i = 0; i < len; i++) { - const uint8_t ch = data[i]; - if (swo_pkt_len == 0) { /* header */ - uint32_t channel = (uint32_t)ch >> 3U; /* channel number */ - uint32_t size = ch & 0x7U; /* drop channel number */ - if (size == 0x01U) - swo_pkt_len = 1; /* SWO packet 0x01XX */ - else if (size == 0x02U) - swo_pkt_len = 2; /* SWO packet 0x02XXXX */ - else if (size == 0x03U) - 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 (usb_get_config() && gdb_serial_get_dtr()) /* silently drop if usb not ready */ - usbd_ep_write_packet(usbd_dev, addr, swo_buf, swo_buf_len); - swo_buf_len = 0; + return 0U; + + /* Step through each byte in the SWO data buffer */ + for (uint16_t idx = 0; idx < len; ++idx) { + /* If we're waiting for a new ITM packet, start decoding the new byte as a header */ + if (itm_packet_length == 0) { + /* Check that the required to be 0 bit of the SWIT packet is, and that the size bits aren't 0 */ + if ((data[idx] & 0x04U) == 0U && (data[idx] & 0x03U) != 0U) { + /* Now extract the stimulus port address (stream number) and payload size */ + uint8_t stream = data[idx] >> 3U; + /* Map 1 -> 1, 2 -> 2, and 3 -> 4 */ + itm_packet_length = 1U << ((data[idx] & 3U) - 1U); + /* Determine if the packet should be displayed */ + itm_decode_packet = (itm_decode_mask & (1U << stream)) != 0U; + } else { + /* If the bit is not 0, this is an invalid SWIT packet, so reset state */ + itm_decode_packet = false; + itm_decoded_buffer_index = 0; + } + } else { + /* If we should actually decode this packet, then forward the data to the decoded data buffer */ + if (itm_decode_packet) { + itm_decoded_buffer[itm_decoded_buffer_index++] = data[idx]; + /* If the buffer has filled up and needs flushing, try to flush the data to the serial endpoint */ + if (itm_decoded_buffer_index == sizeof(itm_decoded_buffer)) { + /* However, if the link is not yet up, drop the packet data silently */ + if (usb_get_config() && gdb_serial_get_dtr()) + usbd_ep_write_packet(usbd_dev, ep, itm_decoded_buffer, itm_decoded_buffer_index); + itm_decoded_buffer_index = 0U; } } - --swo_pkt_len; - } else { /* recover */ - swo_buf_len = 0; - swo_pkt_len = 0; + /* Mark the byte consumed regardless */ + --itm_packet_length; } } return len; } -/* set bitmask of swo channels to be decoded */ -void traceswo_setmask(uint32_t mask) +void swo_itm_decode_set_mask(uint32_t mask) { - swo_decode = mask; + itm_decode_mask = mask; } - -/* not truncated */ diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index a1de67f72e6..3346c2e7e43 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -69,7 +69,7 @@ static uint8_t trace_data_bit_index = 0; /* Number of timer clock cycles that describe half a bit period as detected */ static uint32_t trace_half_bit_period = 0U; -void traceswo_init(const uint32_t swo_chan_bitmask) +void traceswo_init(const uint32_t itm_stream_bitmask) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ TRACE_TIM_CLK_EN(); @@ -115,8 +115,8 @@ void traceswo_init(const uint32_t swo_chan_bitmask) timer_set_period(TRACE_TIM, UINT32_MAX); /* Configure the capture decoder and state, then enable the timer */ - traceswo_setmask(swo_chan_bitmask); - decoding = swo_chan_bitmask != 0; + swo_itm_decode_set_mask(itm_stream_bitmask); + decoding = itm_stream_bitmask != 0; timer_enable_counter(TRACE_TIM); } @@ -141,7 +141,7 @@ void traceswo_deinit(void) void trace_buf_push(uint8_t *buf, int len) { if (decoding) - traceswo_decode(usbdev, CDCACM_UART_ENDPOINT, buf, len); + swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, buf, len); else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, buf, len) != len) { if (trace_usb_buf_size + len > 64) { /* Stall if upstream to too slow. */ @@ -160,7 +160,7 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) return; if (decoding) - traceswo_decode(dev, CDCACM_UART_ENDPOINT, trace_usb_buf, trace_usb_buf_size); + swo_itm_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; diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 8f24b8bfa16..efdc30a3eec 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -79,7 +79,7 @@ void trace_buf_drain(usbd_device *dev, uint8_t ep) uint16_t result; if (decoding) /* write decoded swo packets to the uart port */ - result = traceswo_decode( + result = swo_itm_decode( dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); else /* write raw swo packets to the trace port */ @@ -182,7 +182,7 @@ void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); nvic_enable_irq(SWO_DMA_IRQ); traceswo_setspeed(baudrate); - traceswo_setmask(swo_chan_bitmask); + swo_itm_decode_set_mask(swo_chan_bitmask); decoding = (swo_chan_bitmask != 0); } diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 3fed28bc348..14b32055ed9 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -32,16 +32,16 @@ void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask); uint32_t traceswo_get_baudrate(void); void bmd_usart_set_baudrate(uint32_t usart, uint32_t baud_rate); #else -void traceswo_init(uint32_t swo_chan_bitmask); +void traceswo_init(uint32_t itm_stream_bitmask); #endif void traceswo_deinit(void); void trace_buf_drain(usbd_device *dev, uint8_t ep); -/* Set bitmask of SWO channels to be decoded */ -void traceswo_setmask(uint32_t mask); +/* Set a bitmask of SWO ITM streams to be decoded */ +void swo_itm_decode_set_mask(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); +/* Decode a new block of ITM data from SWO */ +uint16_t swo_itm_decode(usbd_device *usbd_dev, uint8_t ep, const uint8_t *data, uint16_t len); #endif /* PLATFORMS_COMMON_SWO_H */ From b4f3bd2499240b9231e4ccafd3113217eeb09ce1 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 06:36:13 +0100 Subject: [PATCH 12/48] common: Nomenclature corrections for the SWO buffer send USB callback function --- src/platforms/common/stm32/swo_manchester.c | 2 +- src/platforms/common/stm32/swo_uart.c | 6 +++--- src/platforms/common/stm32/swo_uart_f723.c | 6 +++--- src/platforms/common/swo.h | 2 +- src/platforms/common/tm4c/swo_uart.c | 2 +- src/platforms/common/usb_serial.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 3346c2e7e43..845cd44354f 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -154,7 +154,7 @@ void trace_buf_push(uint8_t *buf, int len) } } -void trace_buf_drain(usbd_device *dev, uint8_t ep) +void swo_send_buffer(usbd_device *dev, uint8_t ep) { if (!trace_usb_buf_size) return; diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index efdc30a3eec..6b709ec9ca1 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -67,7 +67,7 @@ static uint8_t pingpong_buf[2 * TRACE_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; -void trace_buf_drain(usbd_device *dev, uint8_t ep) +void swo_send_buffer(usbd_device *dev, uint8_t ep) { static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; @@ -147,7 +147,7 @@ void SWO_DMA_ISR(void) &trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], &pingpong_buf[TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); } write_index = (write_index + 1U) % NUM_TRACE_PACKETS; - trace_buf_drain(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); } void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) @@ -193,7 +193,7 @@ void traceswo_deinit(void) dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_disable(SWO_UART); /* Dump the buffered remains */ - trace_buf_drain(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); /* Return this contiguous chunk of SRAM to unshrinkable heap */ if (trace_rx_buf != NULL) { free(trace_rx_buf); diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c index 08a3617c143..06a1bc6dfc0 100644 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -51,7 +51,7 @@ static uint8_t pingpong_buf[2 * TRACE_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; -void trace_buf_drain(usbd_device *dev, uint8_t ep) +void swo_send_buffer(usbd_device *dev, uint8_t ep) { static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; @@ -125,7 +125,7 @@ void SWO_DMA_ISR(void) &trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], &pingpong_buf[TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); } write_index = (write_index + 1) % NUM_TRACE_PACKETS; - trace_buf_drain(usbdev, TRACE_ENDPOINT); + swo_send_buffer(usbdev, TRACE_ENDPOINT); } void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) @@ -155,5 +155,5 @@ void traceswo_deinit(void) dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); usart_disable(SWO_UART); /* Dump the buffered remains */ - trace_buf_drain(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); } diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 14b32055ed9..31d00926edd 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -36,7 +36,7 @@ void traceswo_init(uint32_t itm_stream_bitmask); #endif void traceswo_deinit(void); -void trace_buf_drain(usbd_device *dev, uint8_t ep); +void swo_send_buffer(usbd_device *dev, uint8_t ep); /* Set a bitmask of SWO ITM streams to be decoded */ void swo_itm_decode_set_mask(uint32_t mask); diff --git a/src/platforms/common/tm4c/swo_uart.c b/src/platforms/common/tm4c/swo_uart.c index c7a2c8d300d..3668a1c35e5 100644 --- a/src/platforms/common/tm4c/swo_uart.c +++ b/src/platforms/common/tm4c/swo_uart.c @@ -122,7 +122,7 @@ void trace_buf_push(void) } } -void trace_buf_drain(usbd_device *dev, uint8_t ep) +void swo_send_buffer(usbd_device *dev, uint8_t ep) { (void)dev; (void)ep; diff --git a/src/platforms/common/usb_serial.c b/src/platforms/common/usb_serial.c index b7ebddf9a66..0063c616d5d 100644 --- a/src/platforms/common/usb_serial.c +++ b/src/platforms/common/usb_serial.c @@ -211,7 +211,7 @@ void usb_serial_set_config(usbd_device *dev, uint16_t value) #ifdef PLATFORM_HAS_TRACESWO /* Trace interface */ - usbd_ep_setup(dev, TRACE_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK, TRACE_ENDPOINT_SIZE, trace_buf_drain); + usbd_ep_setup(dev, TRACE_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK, TRACE_ENDPOINT_SIZE, swo_send_buffer); #endif usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, From ba4ed1d9fc67741892343cc90d27bd59c3404cae Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 06:41:29 +0100 Subject: [PATCH 13/48] common/stm32/swo_manchester: Completed the nomenclature cleanup for the functions and variables of the implementation --- src/command.c | 6 +- src/platforms/common/stm32/swo_manchester.c | 90 +++++++++++---------- src/platforms/common/swo.h | 6 +- 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/command.c b/src/command.c index 040d8a3f41e..c15c0ef30da 100644 --- a/src/command.c +++ b/src/command.c @@ -635,7 +635,7 @@ static bool cmd_traceswo_enable(int argc, const char **argv) traceswo_init(baudrate, swo_channelmask); gdb_outf("Baudrate: %lu ", traceswo_get_baudrate()); #else - traceswo_init(swo_channelmask); + swo_manchester_init(swo_channelmask); #endif gdb_outf("Channel mask: "); for (size_t i = 0; i < 32U; ++i) { @@ -650,7 +650,11 @@ static bool cmd_traceswo_enable(int argc, const char **argv) static bool cmd_traceswo_disable(void) { +#if TRACESWO_PROTOCOL == 1 + swo_manchester_deinit(); +#else traceswo_deinit(); +#endif gdb_out("Trace disabled\n"); return true; } diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 845cd44354f..c389578e75f 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -59,17 +59,19 @@ /* SWO decoding */ static bool decoding = false; +#define SWO_BUFFER_SIZE 64U + /* Buffer and fill level for USB */ -static uint8_t trace_usb_buf[64U]; -static uint8_t trace_usb_buf_size; +static uint8_t swo_transmit_buffer[SWO_BUFFER_SIZE]; +static uint8_t swo_transmit_buffer_index; /* Manchester bit capture buffer and current bit index */ -static uint8_t trace_data[16U]; -static uint8_t trace_data_bit_index = 0; +static uint8_t swo_data[16U]; +static uint8_t swo_data_bit_index = 0; /* Number of timer clock cycles that describe half a bit period as detected */ -static uint32_t trace_half_bit_period = 0U; +static uint32_t swo_half_bit_period = 0U; -void traceswo_init(const uint32_t itm_stream_bitmask) +void swo_manchester_init(const uint32_t itm_stream_bitmask) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ TRACE_TIM_CLK_EN(); @@ -120,15 +122,15 @@ void traceswo_init(const uint32_t itm_stream_bitmask) timer_enable_counter(TRACE_TIM); } -void traceswo_deinit(void) +void swo_manchester_deinit(void) { /* Disable the timer capturing the incomming data stream */ timer_disable_counter(TRACE_TIM); timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_OFF); /* Reset state so that when init is called we wind up in a fresh capture state */ - trace_data_bit_index = 0U; - trace_half_bit_period = 0U; + swo_data_bit_index = 0U; + swo_half_bit_period = 0U; #if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); @@ -138,32 +140,34 @@ void traceswo_deinit(void) #endif } -void trace_buf_push(uint8_t *buf, int len) +void swo_buffer_data(void) { + const uint8_t byte_count = swo_data_bit_index >> 3U; if (decoding) - swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, buf, len); - else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, buf, len) != len) { - if (trace_usb_buf_size + len > 64) { + swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, swo_data, byte_count); + else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, swo_data, byte_count) != byte_count) { + if (swo_transmit_buffer_index + byte_count > SWO_BUFFER_SIZE) { /* Stall if upstream to too slow. */ - usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, 1); - trace_usb_buf_size = 0; + usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, 1U); + swo_transmit_buffer_index = 0; return; } - memcpy(trace_usb_buf + trace_usb_buf_size, buf, len); - trace_usb_buf_size += len; + memcpy(swo_transmit_buffer + swo_transmit_buffer_index, swo_data, byte_count); + swo_transmit_buffer_index += byte_count; } + swo_data_bit_index = 0U; } void swo_send_buffer(usbd_device *dev, uint8_t ep) { - if (!trace_usb_buf_size) + if (!swo_transmit_buffer_index) return; if (decoding) - swo_itm_decode(dev, CDCACM_UART_ENDPOINT, trace_usb_buf, trace_usb_buf_size); + swo_itm_decode(dev, CDCACM_UART_ENDPOINT, swo_transmit_buffer, swo_transmit_buffer_index); else - usbd_ep_write_packet(dev, ep, trace_usb_buf, trace_usb_buf_size); - trace_usb_buf_size = 0; + usbd_ep_write_packet(dev, ep, swo_transmit_buffer, swo_transmit_buffer_index); + swo_transmit_buffer_index = 0; } void TRACE_ISR(void) @@ -185,12 +189,11 @@ void TRACE_ISR(void) const uint32_t space_period = cycle_period - mark_period; /* Reset decoder state if crazy things happened */ - if (cycle_period <= mark_period || (trace_half_bit_period && mark_period < trace_half_bit_period) || - mark_period == 0U) + if (cycle_period <= mark_period || (swo_half_bit_period && mark_period < swo_half_bit_period) || mark_period == 0U) goto flush_and_reset; /* If the bit time is not yet known */ - if (trace_half_bit_period == 0U) { + if (swo_half_bit_period == 0U) { /* Are we here because we got an interrupt but not for the rising edge capture channel? */ if (!(status & TRACE_STATUS_RISING)) /* We're are, so leave early */ @@ -218,8 +221,8 @@ void TRACE_ISR(void) * bit value, and configure the timer maximum period to 6x the current max half bit period, enabling * overflow checking now we have an overflow target for the timer */ - trace_half_bit_period = adjusted_mark_period; - bit_value = space_period >= trace_half_bit_period * 2U ? 0U : 1U; + swo_half_bit_period = adjusted_mark_period; + bit_value = space_period >= swo_half_bit_period * 2U ? 0U : 1U; /* XXX: Need to make sure that this isn't setting a value outside the range of the timer */ timer_set_period(TRACE_TIM, mark_period * 6U); timer_clear_flag(TRACE_TIM, TIM_SR_UIF | TRACE_STATUS_OVERFLOW); @@ -231,11 +234,11 @@ void TRACE_ISR(void) * * If this would start a new byte in the data buffer, zero it to start with */ - if ((trace_data_bit_index & 7U) == 0U) - trace_data[trace_data_bit_index >> 3U] = 0U; + if ((swo_data_bit_index & 7U) == 0U) + swo_data[swo_data_bit_index >> 3U] = 0U; /* Store the new bit in the buffer and move along */ - trace_data[trace_data_bit_index >> 3U] |= bit_value << (trace_data_bit_index & 7U); - ++trace_data_bit_index; + swo_data[swo_data_bit_index >> 3U] |= bit_value << (swo_data_bit_index & 7U); + ++swo_data_bit_index; /* * Having stored a bit, check if we've got a long cycle period - this can happen due to any sequence @@ -257,7 +260,7 @@ void TRACE_ISR(void) * * The bit write that has already occured deals with the lead-in part of all of these. */ - if (cycle_period >= trace_half_bit_period * 3U) { + if (cycle_period >= swo_half_bit_period * 3U) { /* * Having determined that we're in a long cycle, we need to figure out which kind. * If the mark period is short, then whether we're starting half way into a bit determines @@ -265,7 +268,7 @@ void TRACE_ISR(void) * If the mark period is long, then this can only occur from a 0 -> 1 transition where we're * half way into the cycle. Anything else indicates a fault occured. */ - if (mark_period >= trace_half_bit_period * 2U) { + if (mark_period >= swo_half_bit_period * 2U) { if (bit_value == 1U) goto flush_and_reset; /* Something bad happened and we lost sync */ bit_value = 1U; @@ -275,19 +278,19 @@ void TRACE_ISR(void) * We now know the value of the extra bit, if it's from anything other than a short mark, long space, * then we need to store that next bit. */ - if (mark_period >= trace_half_bit_period * 2U || space_period < trace_half_bit_period * 2U) { + if (mark_period >= swo_half_bit_period * 2U || space_period < swo_half_bit_period * 2U) { /* If this would overflow the buffer, then do nothing */ - if (trace_data_bit_index < 128U) { + if (swo_data_bit_index < 128U) { /* If this would start a new byte in the data buffer, zero it to start with */ - if ((trace_data_bit_index & 7U) == 0U) - trace_data[trace_data_bit_index >> 3U] = 0U; + if ((swo_data_bit_index & 7U) == 0U) + swo_data[swo_data_bit_index >> 3U] = 0U; /* Store the new bit in the buffer and move along */ - trace_data[trace_data_bit_index >> 3U] |= bit_value << (trace_data_bit_index & 7U); - ++trace_data_bit_index; + swo_data[swo_data_bit_index >> 3U] |= bit_value << (swo_data_bit_index & 7U); + ++swo_data_bit_index; } } /* If it's a long space, we just saw a 1 -> 0 transition */ - if (space_period >= trace_half_bit_period * 2U) { + if (space_period >= swo_half_bit_period * 2U) { /* Unless of course this was acompanied by a short mark period, in which case it's a STOP bit */ if (bit_value == 0U) goto flush_and_reset; @@ -298,19 +301,18 @@ void TRACE_ISR(void) * We've now written enough data to the buffer, so we have one final check: * If the cycle has a long space, we need to determine how long to check for STOP bits. */ - if (space_period >= trace_half_bit_period * 3U) + if (space_period >= swo_half_bit_period * 3U) goto flush_and_reset; } } /* If the buffer is not full, and we haven't encountered a STOP bit, we're done here */ - if (trace_data_bit_index < 128U) + if (swo_data_bit_index < 128U) return; flush_and_reset: timer_set_period(TRACE_TIM, UINT32_MAX); timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); - trace_buf_push(trace_data, trace_data_bit_index >> 3U); - trace_data_bit_index = 0; - trace_half_bit_period = 0; + swo_buffer_data(); + swo_half_bit_period = 0; } diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 31d00926edd..0799dd25a27 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -29,12 +29,14 @@ /* Default line rate, used as default for a request without baudrate */ #define SWO_DEFAULT_BAUD 2250000U void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask); +void traceswo_deinit(void); + uint32_t traceswo_get_baudrate(void); void bmd_usart_set_baudrate(uint32_t usart, uint32_t baud_rate); #else -void traceswo_init(uint32_t itm_stream_bitmask); +void swo_manchester_init(uint32_t itm_stream_bitmask); +void swo_manchester_deinit(void); #endif -void traceswo_deinit(void); void swo_send_buffer(usbd_device *dev, uint8_t ep); From 441eea42f72f7ac413be04527400c5cca7f0ae6f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 06:44:43 +0100 Subject: [PATCH 14/48] common/stm32/swo_uart: Cleaned up the nomenclature of the external functions --- src/command.c | 6 +++--- src/platforms/common/stm32/swo_uart.c | 6 +++--- src/platforms/common/stm32/swo_uart_f723.c | 6 +++--- src/platforms/common/swo.h | 6 +++--- src/platforms/common/tm4c/swo_uart.c | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/command.c b/src/command.c index c15c0ef30da..53728f955f7 100644 --- a/src/command.c +++ b/src/command.c @@ -632,8 +632,8 @@ static bool cmd_traceswo_enable(int argc, const char **argv) } #if TRACESWO_PROTOCOL == 2 - traceswo_init(baudrate, swo_channelmask); - gdb_outf("Baudrate: %lu ", traceswo_get_baudrate()); + swo_uart_init(baudrate, swo_channelmask); + gdb_outf("Baudrate: %lu ", swo_uart_get_baudrate()); #else swo_manchester_init(swo_channelmask); #endif @@ -653,7 +653,7 @@ static bool cmd_traceswo_disable(void) #if TRACESWO_PROTOCOL == 1 swo_manchester_deinit(); #else - traceswo_deinit(); + swo_uart_deinit(); #endif gdb_out("Trace disabled\n"); return true; diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 6b709ec9ca1..01bcbda78e1 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -91,7 +91,7 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); } -uint32_t traceswo_get_baudrate(void) +uint32_t swo_uart_get_baudrate(void) { return usart_get_baudrate(SWO_UART); } @@ -150,7 +150,7 @@ void SWO_DMA_ISR(void) swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); } -void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) +void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) { /* Skip initial allocation on commands for mode change */ if (trace_rx_buf == NULL) { @@ -186,7 +186,7 @@ void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) decoding = (swo_chan_bitmask != 0); } -void traceswo_deinit(void) +void swo_uart_deinit(void) { /* Stop peripherals servicing */ nvic_disable_irq(SWO_DMA_IRQ); diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c index 06a1bc6dfc0..b75d48b8063 100644 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -75,7 +75,7 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); } -uint32_t traceswo_get_baudrate(void) +uint32_t swo_uart_get_baudrate(void) { return usart_get_baudrate(SWO_UART); } @@ -128,7 +128,7 @@ void SWO_DMA_ISR(void) swo_send_buffer(usbdev, TRACE_ENDPOINT); } -void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) +void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) { if (!baudrate) baudrate = SWO_DEFAULT_BAUD; @@ -148,7 +148,7 @@ void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask) decoding = swo_chan_bitmask != 0; } -void traceswo_deinit(void) +void swo_uart_deinit(void) { /* Stop peripherals servicing */ nvic_disable_irq(SWO_DMA_IRQ); diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 0799dd25a27..34e780e7d54 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -28,10 +28,10 @@ #if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2 /* Default line rate, used as default for a request without baudrate */ #define SWO_DEFAULT_BAUD 2250000U -void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask); -void traceswo_deinit(void); +void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask); +void swo_uart_deinit(void); -uint32_t traceswo_get_baudrate(void); +uint32_t swo_uart_get_baudrate(void); void bmd_usart_set_baudrate(uint32_t usart, uint32_t baud_rate); #else void swo_manchester_init(uint32_t itm_stream_bitmask); diff --git a/src/platforms/common/tm4c/swo_uart.c b/src/platforms/common/tm4c/swo_uart.c index 3668a1c35e5..4e2b1d9e7d6 100644 --- a/src/platforms/common/tm4c/swo_uart.c +++ b/src/platforms/common/tm4c/swo_uart.c @@ -37,7 +37,7 @@ #include #include -void traceswo_init(void) +void swo_uart_init(void) { periph_clock_enable(RCC_GPIOD); periph_clock_enable(TRACEUART_CLK); @@ -87,7 +87,7 @@ void traceswo_baud(unsigned int baud) uart_set_databits(TRACEUART, 8); } -uint32_t traceswo_get_baudrate(void) +uint32_t swo_uart_get_baudrate(void) { return uart_get_baudrate(TRACEUART); } From 076a15ce2376080907c566dbcf1b69809ca7c1b6 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 06:45:58 +0100 Subject: [PATCH 15/48] command: Switched the SWO command to the new consitent nomenclature --- src/command.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index 53728f955f7..e253af107c0 100644 --- a/src/command.c +++ b/src/command.c @@ -68,7 +68,7 @@ static bool cmd_tdi_low_reset(target_s *t, int argc, const char **argv); static bool cmd_target_power(target_s *t, int argc, const char **argv); #endif #ifdef PLATFORM_HAS_TRACESWO -static bool cmd_traceswo(target_s *t, int argc, const char **argv); +static bool cmd_swo(target_s *t, int argc, const char **argv); #endif static bool cmd_heapinfo(target_s *t, int argc, const char **argv); #ifdef ENABLE_RTT @@ -110,10 +110,11 @@ const command_s cmd_list[] = { #endif #ifdef PLATFORM_HAS_TRACESWO #if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2 - {"traceswo", cmd_traceswo, "Start SWO capture, NRZ mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, + {"swo", cmd_swo, "Start SWO capture, UART mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, #else - {"traceswo", cmd_traceswo, "Start SWO capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, + {"swo", cmd_swo, "Start SWO capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, #endif + {"traceswo", cmd_swo, "Deprecated: use swo instead"}, #endif {"heapinfo", cmd_heapinfo, "Set semihosting heapinfo: HEAP_BASE HEAP_LIMIT STACK_BASE STACK_LIMIT"}, #if defined(PLATFORM_HAS_DEBUG) && PC_HOSTED == 0 @@ -603,7 +604,7 @@ static bool cmd_rtt(target_s *t, int argc, const char **argv) #endif #ifdef PLATFORM_HAS_TRACESWO -static bool cmd_traceswo_enable(int argc, const char **argv) +static bool cmd_swo_enable(int argc, const char **argv) { uint32_t swo_channelmask = 0; /* swo decoding off */ uint8_t decode_arg = 1; @@ -648,7 +649,7 @@ static bool cmd_traceswo_enable(int argc, const char **argv) return true; } -static bool cmd_traceswo_disable(void) +static bool cmd_swo_disable(void) { #if TRACESWO_PROTOCOL == 1 swo_manchester_deinit(); @@ -659,7 +660,7 @@ static bool cmd_traceswo_disable(void) return true; } -static bool cmd_traceswo(target_s *t, int argc, const char **argv) +static bool cmd_swo(target_s *t, int argc, const char **argv) { (void)t; bool mode = false; @@ -669,9 +670,9 @@ static bool cmd_traceswo(target_s *t, int argc, const char **argv) } if (mode) - return cmd_traceswo_enable(argc - 1, argv + 1); + return cmd_swo_enable(argc - 1, argv + 1); else - return cmd_traceswo_disable(); + return cmd_swo_disable(); } #endif From aee4c014d7478b21ba54f7f39cfad612118c89ed Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 06:59:01 +0100 Subject: [PATCH 16/48] command: Cleaned up and better documented the SWO enable function --- src/command.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/command.c b/src/command.c index e253af107c0..24dc8e81970 100644 --- a/src/command.c +++ b/src/command.c @@ -606,45 +606,54 @@ static bool cmd_rtt(target_s *t, int argc, const char **argv) #ifdef PLATFORM_HAS_TRACESWO static bool cmd_swo_enable(int argc, const char **argv) { - uint32_t swo_channelmask = 0; /* swo decoding off */ - uint8_t decode_arg = 1; + /* + * Before we can enable SWO data recovery, potentially with decoding, + * start with the assumption ITM decoding is off + */ + uint32_t itm_stream_mask = 0U; + uint8_t decode_arg = 1U; #if TRACESWO_PROTOCOL == 2 uint32_t baudrate = SWO_DEFAULT_BAUD; - /* argument: optional baud rate for async mode */ + /* Handle the optional baud rate argument if present */ if (argc > 1 && argv[1][0] >= '0' && argv[1][0] <= '9') { baudrate = strtoul(argv[1], NULL, 0); - if (baudrate == 0) + if (baudrate == 0U) baudrate = SWO_DEFAULT_BAUD; - decode_arg = 2; + decode_arg = 2U; } #endif - /* argument: 'decode' literal */ + /* Check if `decode` has been given and if it has, enable ITM decoding */ if (argc > decode_arg && !strncmp(argv[decode_arg], "decode", strlen(argv[decode_arg]))) { - swo_channelmask = 0xffffffffU; /* decoding all channels */ - /* arguments: channels to decode */ + /* Check if there are specific ITM streams to enable and build a bitmask of them */ if (argc > decode_arg + 1) { - swo_channelmask = 0U; - for (size_t i = decode_arg + 1U; i < (size_t)argc; ++i) { /* create bitmask of channels to decode */ - const uint32_t channel = strtoul(argv[i], NULL, 0); - if (channel < 32U) - swo_channelmask |= 1U << channel; + /* For each of the specified streams */ + for (size_t i = decode_arg + 1U; i < (size_t)argc; ++i) { + /* Figure out which the next one is */ + const uint32_t stream = strtoul(argv[i], NULL, 0); + /* If it's a valid ITM stream number, set it in the mask */ + if (stream < 32U) + itm_stream_mask |= 1U << stream; } - } + } else + /* Decode all ITM streams if non given */ + itm_stream_mask = 0xffffffffU; } + /* Now enable SWO data recovery */ #if TRACESWO_PROTOCOL == 2 - swo_uart_init(baudrate, swo_channelmask); + swo_uart_init(baudrate, itm_stream_mask); gdb_outf("Baudrate: %lu ", swo_uart_get_baudrate()); #else - swo_manchester_init(swo_channelmask); + swo_manchester_init(itm_stream_mask); #endif + /* Now show the user what we've done - first the channel mask from MSb to LSb */ gdb_outf("Channel mask: "); for (size_t i = 0; i < 32U; ++i) { - const uint32_t bit = (swo_channelmask >> (31U - i)) & 1U; - gdb_outf("%" PRIu32, bit); + const char bit = '0' + ((itm_stream_mask >> (31U - i)) & 1U); + gdb_outf("%c", bit); } gdb_outf("\n"); - + /* Then the connection information for programs that are scraping BMD's output to know what to connect to */ gdb_outf("Trace enabled for BMP serial %s, USB EP %u\n", serial_no, TRACE_ENDPOINT); return true; } From 9950cd3f004b11183e3aca5f8a2c97cf545aef0d Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 07:00:36 +0100 Subject: [PATCH 17/48] command: Fixed a clang-tidy lint in cmd_swo() --- src/command.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/command.c b/src/command.c index 24dc8e81970..d505aeb2076 100644 --- a/src/command.c +++ b/src/command.c @@ -672,16 +672,15 @@ static bool cmd_swo_disable(void) static bool cmd_swo(target_s *t, int argc, const char **argv) { (void)t; - bool mode = false; - if (argc >= 2 && !parse_enable_or_disable(argv[1], &mode)) { + bool enable_swo = false; + if (argc >= 2 && !parse_enable_or_disable(argv[1], &enable_swo)) { gdb_out("Usage: traceswo [2000000] [decode [0 1 3 31]]\n"); return false; } - if (mode) + if (enable_swo) return cmd_swo_enable(argc - 1, argv + 1); - else - return cmd_swo_disable(); + return cmd_swo_disable(); } #endif From f1afe013a93dedf123e343b407027a94973999a4 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 07:08:27 +0100 Subject: [PATCH 18/48] common: Switched the SWO definitions nomenclature to be consistent by using SWO everywhere --- src/command.c | 2 +- .../common/blackpill-f4/blackpill-f4.h | 34 +++++----- src/platforms/common/stm32/swo_manchester.c | 66 +++++++++---------- src/platforms/common/stm32/swo_uart.c | 24 ++++--- src/platforms/common/stm32/swo_uart_f723.c | 24 ++++--- src/platforms/common/tm4c/swo_uart.c | 46 ++++++------- src/platforms/common/usb.h | 12 ++-- src/platforms/common/usb_descriptors.h | 18 ++--- src/platforms/common/usb_serial.c | 2 +- src/platforms/ctxlink/platform.h | 34 +++++----- src/platforms/f072/platform.h | 32 ++++----- src/platforms/f3/platform.h | 32 ++++----- src/platforms/f4discovery/platform.h | 32 ++++----- src/platforms/hydrabus/platform.h | 32 ++++----- src/platforms/launchpad-icdi/platform.h | 8 +-- src/platforms/native/platform.h | 30 ++++----- src/platforms/stlink/platform.h | 32 ++++----- src/platforms/stlinkv3/platform.h | 2 +- src/platforms/swlink/platform.h | 32 ++++----- 19 files changed, 245 insertions(+), 249 deletions(-) diff --git a/src/command.c b/src/command.c index d505aeb2076..8df082677e6 100644 --- a/src/command.c +++ b/src/command.c @@ -654,7 +654,7 @@ static bool cmd_swo_enable(int argc, const char **argv) } gdb_outf("\n"); /* Then the connection information for programs that are scraping BMD's output to know what to connect to */ - gdb_outf("Trace enabled for BMP serial %s, USB EP %u\n", serial_no, TRACE_ENDPOINT); + gdb_outf("Trace enabled for BMP serial %s, USB EP %u\n", serial_no, SWO_ENDPOINT); return true; } diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index 67a8e7d0fdb..4154b1511a8 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -284,30 +284,30 @@ extern bool debug_bmp; #define IRQ_PRI_USB (1U << 4U) #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) #define PLATFORM_HAS_TRACESWO -#define NUM_TRACE_PACKETS 256U /* 16K buffer */ +#define NUM_SWO_PACKETS 256U /* 16K buffer */ #if TRACESWO_PROTOCOL == 1 /* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, triggered on rising edge */ -#define TRACE_TIM TIM4 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) -#define TRACE_IRQ NVIC_TIM4_IRQ -#define TRACE_ISR(x) tim4_isr(x) -#define TRACE_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) -#define TRACE_TIM_PIN_AF GPIO_AF2 +#define SWO_TIM TIM4 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) +#define SWO_TIM_IRQ NVIC_TIM4_IRQ +#define SWO_TIM_ISR(x) tim4_isr(x) +#define SWO_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) +#define SWO_TIM_PIN_AF GPIO_AF2 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index c389578e75f..23cabafa7e1 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -74,7 +74,7 @@ static uint32_t swo_half_bit_period = 0U; void swo_manchester_init(const uint32_t itm_stream_bitmask) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ - TRACE_TIM_CLK_EN(); + SWO_TIM_CLK_EN(); #if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) /* Set any required pin alt-function configuration - TIM3/TIM4/TIM5 are AF2 */ @@ -89,44 +89,44 @@ void swo_manchester_init(const uint32_t itm_stream_bitmask) * Start setting the timer block up by picking a pair of cross-linked capture channels suitable for the input, * and configure them to consume the input channel for the SWO pin. We use one in rising edge mode and the * other in falling to get the mark period and cycle period - together these define all elements of a wiggle. - * NB: "TRACE_IC" here refers to the Input Capture channels being used + * NB: "SWO_IC" here refers to the Input Capture channels being used */ - timer_ic_set_input(TRACE_TIM, TRACE_IC_RISING, TRACE_IC_IN); - timer_ic_set_polarity(TRACE_TIM, TRACE_IC_RISING, TIM_IC_RISING); - timer_ic_set_input(TRACE_TIM, TRACE_IC_FALLING, TRACE_IC_IN); - timer_ic_set_polarity(TRACE_TIM, TRACE_IC_FALLING, TIM_IC_FALLING); + timer_ic_set_input(SWO_TIM, SWO_IC_RISING, SWO_IC_IN); + timer_ic_set_polarity(SWO_TIM, SWO_IC_RISING, TIM_IC_RISING); + timer_ic_set_input(SWO_TIM, SWO_IC_FALLING, SWO_IC_IN); + timer_ic_set_polarity(SWO_TIM, SWO_IC_FALLING, TIM_IC_FALLING); /* * Use reset mode to trigger the timer, which makes the counter reset and start counting anew * when a rising edge is detected on the input pin via the filtered input channel as a trigger source */ - timer_slave_set_trigger(TRACE_TIM, TRACE_TRIG_IN); - timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_RM); + timer_slave_set_trigger(SWO_TIM, SWO_TRIG_IN); + timer_slave_set_mode(SWO_TIM, TIM_SMCR_SMS_RM); /* Enable capture interrupt */ - nvic_set_priority(TRACE_IRQ, IRQ_PRI_TRACE); - nvic_enable_irq(TRACE_IRQ); - timer_enable_irq(TRACE_TIM, TRACE_ITR_RISING); + nvic_set_priority(SWO_TIM_IRQ, IRQ_PRI_SWO_TIM); + nvic_enable_irq(SWO_TIM_IRQ); + timer_enable_irq(SWO_TIM, SWO_ITR_RISING); /* Enable the capture channels */ - timer_ic_enable(TRACE_TIM, TRACE_IC_RISING); - timer_ic_enable(TRACE_TIM, TRACE_IC_FALLING); + timer_ic_enable(SWO_TIM, SWO_IC_RISING); + timer_ic_enable(SWO_TIM, SWO_IC_FALLING); /* Make sure all the status register bits are cleared prior to enabling the counter */ - timer_clear_flag(TRACE_TIM, TIM_SR_MASK); + timer_clear_flag(SWO_TIM, TIM_SR_MASK); /* Set the period to an improbable value */ - timer_set_period(TRACE_TIM, UINT32_MAX); + timer_set_period(SWO_TIM, UINT32_MAX); /* Configure the capture decoder and state, then enable the timer */ swo_itm_decode_set_mask(itm_stream_bitmask); decoding = itm_stream_bitmask != 0; - timer_enable_counter(TRACE_TIM); + timer_enable_counter(SWO_TIM); } void swo_manchester_deinit(void) { /* Disable the timer capturing the incomming data stream */ - timer_disable_counter(TRACE_TIM); - timer_slave_set_mode(TRACE_TIM, TIM_SMCR_SMS_OFF); + timer_disable_counter(SWO_TIM); + timer_slave_set_mode(SWO_TIM, TIM_SMCR_SMS_OFF); /* Reset state so that when init is called we wind up in a fresh capture state */ swo_data_bit_index = 0U; @@ -145,10 +145,10 @@ void swo_buffer_data(void) const uint8_t byte_count = swo_data_bit_index >> 3U; if (decoding) swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, swo_data, byte_count); - else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, swo_data, byte_count) != byte_count) { + else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, swo_data, byte_count) != byte_count) { if (swo_transmit_buffer_index + byte_count > SWO_BUFFER_SIZE) { /* Stall if upstream to too slow. */ - usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, 1U); + usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, 1U); swo_transmit_buffer_index = 0; return; } @@ -170,22 +170,22 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) swo_transmit_buffer_index = 0; } -void TRACE_ISR(void) +void SWO_TIM_ISR(void) { static uint8_t bit_value; - const uint16_t status = TIM_SR(TRACE_TIM); + const uint16_t status = TIM_SR(SWO_TIM); - const uint32_t cycle_period = TRACE_CC_RISING; + const uint32_t cycle_period = SWO_CC_RISING; /* Check that we entered the handler because of a fresh trigger but have not yet had a chance to capture data */ - if ((status & TRACE_STATUS_RISING) && cycle_period == 0U) { + if ((status & SWO_STATUS_RISING) && cycle_period == 0U) { /* Clear the rising edge flag and wait for it to set again */ - timer_clear_flag(TRACE_TIM, TRACE_STATUS_RISING | TRACE_STATUS_FALLING | TRACE_STATUS_OVERFLOW); + timer_clear_flag(SWO_TIM, SWO_STATUS_RISING | SWO_STATUS_FALLING | SWO_STATUS_OVERFLOW); return; } - timer_clear_flag(TRACE_TIM, TRACE_STATUS_RISING | TRACE_STATUS_FALLING | TRACE_STATUS_OVERFLOW | TIM_SR_UIF); + timer_clear_flag(SWO_TIM, SWO_STATUS_RISING | SWO_STATUS_FALLING | SWO_STATUS_OVERFLOW | TIM_SR_UIF); - const uint32_t mark_period = TRACE_CC_FALLING; + const uint32_t mark_period = SWO_CC_FALLING; const uint32_t space_period = cycle_period - mark_period; /* Reset decoder state if crazy things happened */ @@ -195,7 +195,7 @@ void TRACE_ISR(void) /* If the bit time is not yet known */ if (swo_half_bit_period == 0U) { /* Are we here because we got an interrupt but not for the rising edge capture channel? */ - if (!(status & TRACE_STATUS_RISING)) + if (!(status & SWO_STATUS_RISING)) /* We're are, so leave early */ return; /* @@ -224,9 +224,9 @@ void TRACE_ISR(void) swo_half_bit_period = adjusted_mark_period; bit_value = space_period >= swo_half_bit_period * 2U ? 0U : 1U; /* XXX: Need to make sure that this isn't setting a value outside the range of the timer */ - timer_set_period(TRACE_TIM, mark_period * 6U); - timer_clear_flag(TRACE_TIM, TIM_SR_UIF | TRACE_STATUS_OVERFLOW); - timer_enable_irq(TRACE_TIM, TIM_DIER_UIE); + timer_set_period(SWO_TIM, mark_period * 6U); + timer_clear_flag(SWO_TIM, TIM_SR_UIF | SWO_STATUS_OVERFLOW); + timer_enable_irq(SWO_TIM, TIM_DIER_UIE); } else { /* * We start off needing to store a newly captured bit - the value of which is determined in the *previous* @@ -311,8 +311,8 @@ void TRACE_ISR(void) return; flush_and_reset: - timer_set_period(TRACE_TIM, UINT32_MAX); - timer_disable_irq(TRACE_TIM, TIM_DIER_UIE); + timer_set_period(SWO_TIM, UINT32_MAX); + timer_disable_irq(SWO_TIM, TIM_DIER_UIE); swo_buffer_data(); swo_half_bit_period = 0; } diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 01bcbda78e1..2cb504adbdf 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -63,7 +63,7 @@ static volatile uint32_t read_index; /* Packet currently waiting to transmit to /* Packets arrived from the SWO interface */ static uint8_t *trace_rx_buf = NULL; /* Packet pingpong buffer used for receiving packets */ -static uint8_t pingpong_buf[2 * TRACE_ENDPOINT_SIZE]; +static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; @@ -80,13 +80,12 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) if (decoding) /* write decoded swo packets to the uart port */ result = swo_itm_decode( - dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); else /* write raw swo packets to the trace port */ - result = - usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + result = usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); if (result) - read_index = (read_index + 1U) % NUM_TRACE_PACKETS; + read_index = (read_index + 1U) % NUM_SWO_PACKETS; } atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); } @@ -130,7 +129,7 @@ void traceswo_setspeed(uint32_t baudrate) nvic_enable_irq(SWO_DMA_IRQ); write_index = read_index = 0; dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uint32_t)pingpong_buf); - dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, 2 * TRACE_ENDPOINT_SIZE); + dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, 2 * SWO_ENDPOINT_SIZE); dma_enable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_enable_rx_dma(SWO_UART); } @@ -139,15 +138,14 @@ void SWO_DMA_ISR(void) { if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF); - memcpy(&trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], pingpong_buf, TRACE_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], pingpong_buf, SWO_ENDPOINT_SIZE); } if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF); - memcpy( - &trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], &pingpong_buf[TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], &pingpong_buf[SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); } - write_index = (write_index + 1U) % NUM_TRACE_PACKETS; - swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + write_index = (write_index + 1U) % NUM_SWO_PACKETS; + swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); } void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) @@ -155,7 +153,7 @@ void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) /* Skip initial allocation on commands for mode change */ if (trace_rx_buf == NULL) { /* Alignment (bytes): 1 for UART DMA, 2-4 for memcpy in usb code, 8 provided by malloc. Not 64 */ - uint8_t *const newbuf = malloc(NUM_TRACE_PACKETS * TRACE_ENDPOINT_SIZE); + uint8_t *const newbuf = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); if (!newbuf) { DEBUG_ERROR("malloc: failed in %s\n", __func__); return; @@ -193,7 +191,7 @@ void swo_uart_deinit(void) dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_disable(SWO_UART); /* Dump the buffered remains */ - swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); /* Return this contiguous chunk of SRAM to unshrinkable heap */ if (trace_rx_buf != NULL) { free(trace_rx_buf); diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c index b75d48b8063..a059497c326 100644 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -45,9 +45,9 @@ static volatile uint32_t write_index; /* Packet currently received via UART */ static volatile uint32_t read_index; /* Packet currently waiting to transmit to USB */ /* Packets arrived from the SWO interface */ -static uint8_t trace_rx_buf[NUM_TRACE_PACKETS * TRACE_ENDPOINT_SIZE]; +static uint8_t trace_rx_buf[NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE]; /* Packet pingpong buffer used for receiving packets */ -static uint8_t pingpong_buf[2 * TRACE_ENDPOINT_SIZE]; +static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; @@ -64,13 +64,12 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) if (decoding) /* write decoded swo packets to the uart port */ result = traceswo_decode( - dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); else /* write raw swo packets to the trace port */ - result = - usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + result = usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); if (result) - read_index = (read_index + 1U) % NUM_TRACE_PACKETS; + read_index = (read_index + 1U) % NUM_SWO_PACKETS; } atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); } @@ -107,7 +106,7 @@ void traceswo_setspeed(uint32_t baudrate) nvic_enable_irq(SWO_DMA_IRQ); write_index = read_index = 0; dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_STREAM, (uint32_t)pingpong_buf); - dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_STREAM, 2 * TRACE_ENDPOINT_SIZE); + dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_STREAM, 2 * SWO_ENDPOINT_SIZE); dma_channel_select(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_CHSEL_4); dma_enable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); usart_enable_rx_dma(SWO_UART); @@ -117,15 +116,14 @@ void SWO_DMA_ISR(void) { if (DMA_LISR(SWO_DMA_BUS) & DMA_LISR_HTIF0) { DMA_LIFCR(SWO_DMA_BUS) |= DMA_LISR_HTIF0; - memcpy(&trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], pingpong_buf, TRACE_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], pingpong_buf, SWO_ENDPOINT_SIZE); } if (DMA_LISR(SWO_DMA_BUS) & DMA_LISR_TCIF0) { DMA_LIFCR(SWO_DMA_BUS) |= DMA_LISR_TCIF0; - memcpy( - &trace_rx_buf[write_index * TRACE_ENDPOINT_SIZE], &pingpong_buf[TRACE_ENDPOINT_SIZE], TRACE_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], &pingpong_buf[SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); } - write_index = (write_index + 1) % NUM_TRACE_PACKETS; - swo_send_buffer(usbdev, TRACE_ENDPOINT); + write_index = (write_index + 1) % NUM_SWO_PACKETS; + swo_send_buffer(usbdev, SWO_ENDPOINT); } void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) @@ -155,5 +153,5 @@ void swo_uart_deinit(void) dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); usart_disable(SWO_UART); /* Dump the buffered remains */ - swo_send_buffer(usbdev, TRACE_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); } diff --git a/src/platforms/common/tm4c/swo_uart.c b/src/platforms/common/tm4c/swo_uart.c index 4e2b1d9e7d6..a19be476e91 100644 --- a/src/platforms/common/tm4c/swo_uart.c +++ b/src/platforms/common/tm4c/swo_uart.c @@ -40,7 +40,7 @@ void swo_uart_init(void) { periph_clock_enable(RCC_GPIOD); - periph_clock_enable(TRACEUART_CLK); + periph_clock_enable(SWO_UART_CLK); __asm__("nop"); __asm__("nop"); __asm__("nop"); @@ -48,48 +48,48 @@ void swo_uart_init(void) gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); gpio_set_af(SWO_PORT, 1, SWO_PIN); /* U2RX */ - uart_disable(TRACEUART); + uart_disable(SWO_UART); /* Setup UART parameters. */ - uart_clock_from_sysclk(TRACEUART); - uart_set_baudrate(TRACEUART, 800000); - uart_set_databits(TRACEUART, 8); - uart_set_stopbits(TRACEUART, 1); - uart_set_parity(TRACEUART, UART_PARITY_NONE); + uart_clock_from_sysclk(SWO_UART); + uart_set_baudrate(SWO_UART, 800000); + uart_set_databits(SWO_UART, 8); + uart_set_stopbits(SWO_UART, 1); + uart_set_parity(SWO_UART, UART_PARITY_NONE); // Enable FIFO - uart_enable_fifo(TRACEUART); + uart_enable_fifo(SWO_UART); // Set FIFO interrupt trigger levels to 4/8 full for RX buffer and // 7/8 empty (1/8 full) for TX buffer - uart_set_fifo_trigger_levels(TRACEUART, UART_FIFO_RX_TRIG_1_2, UART_FIFO_TX_TRIG_7_8); + uart_set_fifo_trigger_levels(SWO_UART, UART_FIFO_RX_TRIG_1_2, UART_FIFO_TX_TRIG_7_8); - uart_clear_interrupt_flag(TRACEUART, UART_INT_RX | UART_INT_RT); + uart_clear_interrupt_flag(SWO_UART, UART_INT_RX | UART_INT_RT); /* Enable interrupts */ - uart_enable_interrupts(TRACEUART, UART_INT_RX | UART_INT_RT); + uart_enable_interrupts(SWO_UART, UART_INT_RX | UART_INT_RT); /* Finally enable the USART. */ - uart_enable(TRACEUART); + uart_enable(SWO_UART); - nvic_set_priority(TRACEUART_IRQ, 0); - nvic_enable_irq(TRACEUART_IRQ); + nvic_set_priority(SWO_UART_IRQ, 0); + nvic_enable_irq(SWO_UART_IRQ); /* Un-stall USB endpoint */ - usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, 0); + usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, 0); gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3); } void traceswo_baud(unsigned int baud) { - uart_set_baudrate(TRACEUART, baud); - uart_set_databits(TRACEUART, 8); + uart_set_baudrate(SWO_UART, baud); + uart_set_databits(SWO_UART, 8); } uint32_t swo_uart_get_baudrate(void) { - return uart_get_baudrate(TRACEUART); + return uart_get_baudrate(SWO_UART); } #define FIFO_SIZE 256U @@ -116,7 +116,7 @@ void trace_buf_push(void) if (len > 64U) len = 64; - if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | TRACE_ENDPOINT, (uint8_t *)&buf_rx[buf_rx_out], len) == len) { + if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, (uint8_t *)&buf_rx[buf_rx_out], len) == len) { buf_rx_out += len; buf_rx_out %= FIFO_SIZE; } @@ -134,12 +134,12 @@ void trace_tick(void) trace_buf_push(); } -void TRACEUART_ISR(void) +void SWO_UART_ISR(void) { - uint32_t flush = uart_is_interrupt_source(TRACEUART, UART_INT_RT); + uint32_t flush = uart_is_interrupt_source(SWO_UART, UART_INT_RT); - while (!uart_is_rx_fifo_empty(TRACEUART)) { - const uint32_t c = uart_recv(TRACEUART); + while (!uart_is_rx_fifo_empty(SWO_UART)) { + const uint32_t c = uart_recv(SWO_UART); /* If the next increment of rx_in would put it at the same point * as rx_out, the FIFO is considered full. diff --git a/src/platforms/common/usb.h b/src/platforms/common/usb.h index 4ac49108185..e07815b8932 100644 --- a/src/platforms/common/usb.h +++ b/src/platforms/common/usb.h @@ -28,11 +28,11 @@ extern usbd_device *usbdev; extern uint16_t usb_config; #if defined(USB_HS) -#define CDCACM_PACKET_SIZE 512U -#define TRACE_ENDPOINT_SIZE 512U +#define CDCACM_PACKET_SIZE 512U +#define SWO_ENDPOINT_SIZE 512U #else -#define CDCACM_PACKET_SIZE 64U -#define TRACE_ENDPOINT_SIZE 64U +#define CDCACM_PACKET_SIZE 64U +#define SWO_ENDPOINT_SIZE 64U #endif #if !defined(USB_MAX_INTERVAL) @@ -41,7 +41,7 @@ extern uint16_t usb_config; #define CDCACM_GDB_ENDPOINT 1U #define CDCACM_UART_ENDPOINT 2U -#define TRACE_ENDPOINT 3U +#define SWO_ENDPOINT 3U /* * AN4879, table 6: most STM32F4 families (excluding F412, F413, F423) * have OTG_FS DWC2 configured with "4 bidirectional endpoints" (including EP0), @@ -57,7 +57,7 @@ extern uint16_t usb_config; #define UART_IF_NO 2U #define DFU_IF_NO 4U #ifdef PLATFORM_HAS_TRACESWO -#define TRACE_IF_NO 5U +#define SWO_IF_NO 5U #define TOTAL_INTERFACES 6U #else #define TOTAL_INTERFACES 5U diff --git a/src/platforms/common/usb_descriptors.h b/src/platforms/common/usb_descriptors.h index 9595460cff9..af99d576ba6 100644 --- a/src/platforms/common/usb_descriptors.h +++ b/src/platforms/common/usb_descriptors.h @@ -337,16 +337,16 @@ static const usb_iface_assoc_descriptor_s dfu_assoc = { static const usb_endpoint_descriptor_s trace_endp = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = TRACE_ENDPOINT | USB_REQ_TYPE_IN, + .bEndpointAddress = SWO_ENDPOINT | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = TRACE_ENDPOINT_SIZE, + .wMaxPacketSize = SWO_ENDPOINT_SIZE, .bInterval = 0, }; const usb_interface_descriptor_s trace_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = TRACE_IF_NO, + .bInterfaceNumber = SWO_IF_NO, .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = 0xff, @@ -360,7 +360,7 @@ const usb_interface_descriptor_s trace_iface = { static const usb_iface_assoc_descriptor_s trace_assoc = { .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = TRACE_IF_NO, + .bFirstInterface = SWO_IF_NO, .bInterfaceCount = 1, .bFunctionClass = 0xff, .bFunctionSubClass = 0xff, @@ -443,7 +443,7 @@ static const char *const usb_strings[] = { #define PROPERTY_DEVICE_INTERFACE_GUID u"DeviceInterfaceGUID" #define VALUE_DFU_INTERFACE_GUID u"{76be5ca1-e304-4b32-be5f-d9369d3d201a}" #ifdef PLATFORM_HAS_TRACESWO -#define VALUE_TRACE_INTERFACE_GUID u"{76be5ca1-e305-4b32-be5f-d9369d3d201a}" +#define VALUE_SWO_INTERFACE_GUID u"{76be5ca1-e305-4b32-be5f-d9369d3d201a}" #endif static const struct { @@ -498,8 +498,8 @@ static const struct { .wPropertyDataType = REG_SZ, .wPropertyNameLength = ARRAY_LENGTH(PROPERTY_DEVICE_INTERFACE_GUID) * 2U, .PropertyName = PROPERTY_DEVICE_INTERFACE_GUID, - .wPropertyDataLength = ARRAY_LENGTH(VALUE_TRACE_INTERFACE_GUID) * 2U, - .PropertyData = VALUE_TRACE_INTERFACE_GUID, + .wPropertyDataLength = ARRAY_LENGTH(VALUE_SWO_INTERFACE_GUID) * 2U, + .PropertyData = VALUE_SWO_INTERFACE_GUID, }, }; #endif @@ -519,7 +519,7 @@ static const microsoft_os_descriptor_function_subset_header microsoft_os_descrip { .wLength = MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE, .wDescriptorType = MICROSOFT_OS_SUBSET_HEADER_FUNCTION, - .bFirstInterface = TRACE_IF_NO, + .bFirstInterface = SWO_IF_NO, .bReserved = 0, .wTotalLength = 0, @@ -560,7 +560,7 @@ static const microsoft_os_descriptor_set_information microsoft_os_descriptor_set #ifdef PLATFORM_HAS_TRACESWO MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE + MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE + MICROSOFT_OS_FEATURE_REGISTRY_PROPERTY_DESCRIPTOR_SIZE_BASE + - (ARRAY_LENGTH(PROPERTY_DEVICE_INTERFACE_GUID) * 2U) + (ARRAY_LENGTH(VALUE_TRACE_INTERFACE_GUID) * 2U) + + (ARRAY_LENGTH(PROPERTY_DEVICE_INTERFACE_GUID) * 2U) + (ARRAY_LENGTH(VALUE_SWO_INTERFACE_GUID) * 2U) + #endif MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE + MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE + MICROSOFT_OS_FEATURE_REGISTRY_PROPERTY_DESCRIPTOR_SIZE_BASE + diff --git a/src/platforms/common/usb_serial.c b/src/platforms/common/usb_serial.c index 0063c616d5d..0502c832c90 100644 --- a/src/platforms/common/usb_serial.c +++ b/src/platforms/common/usb_serial.c @@ -211,7 +211,7 @@ void usb_serial_set_config(usbd_device *dev, uint16_t value) #ifdef PLATFORM_HAS_TRACESWO /* Trace interface */ - usbd_ep_setup(dev, TRACE_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK, TRACE_ENDPOINT_SIZE, swo_send_buffer); + usbd_ep_setup(dev, SWO_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK, SWO_ENDPOINT_SIZE, swo_send_buffer); #endif usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index dfa2d8a2c17..a2123d86f6c 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -180,30 +180,30 @@ #define IRQ_PRI_USB (1U << 4U) #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) #define PLATFORM_HAS_TRACESWO -#define NUM_TRACE_PACKETS 256U /* 16K buffer */ +#define NUM_SWO_PACKETS 256U /* 16K buffer */ #if TRACESWO_PROTOCOL == 1 /* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI2 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI2FP2 -#define SWO_TIM_PIN_AF GPIO_AF2 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR(x) tim3_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI2 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 +#define SWO_TIM_PIN_AF GPIO_AF2 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/f072/platform.h b/src/platforms/f072/platform.h index 5a720d388bf..ab8453642d5 100644 --- a/src/platforms/f072/platform.h +++ b/src/platforms/f072/platform.h @@ -95,7 +95,7 @@ #define IRQ_PRI_USB (1U << 6U) #define IRQ_PRI_USBUSART (2U << 6U) #define IRQ_PRI_USBUSART_DMA (2U << 6U) -#define IRQ_PRI_TRACE (0U << 6U) +#define IRQ_PRI_SWO_TIM (0U << 6U) #define USBUSART USART2 #define USBUSART_CR1 USART2_CR1 @@ -132,21 +132,21 @@ } while (0) /* Use TIM3 Input 1 (from PA6/TDO on AF1) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR tim3_isr -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF1 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR tim3_isr +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM_PIN_AF GPIO_AF1 #if ENABLE_DEBUG == 1 extern bool debug_bmp; diff --git a/src/platforms/f3/platform.h b/src/platforms/f3/platform.h index 530cf46897e..2915e55e72a 100644 --- a/src/platforms/f3/platform.h +++ b/src/platforms/f3/platform.h @@ -94,7 +94,7 @@ #define IRQ_PRI_USB (1U << 4U) #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define USBUSART USART2 #define USBUSART_CR1 USART2_CR1 @@ -125,21 +125,21 @@ } while (0) /* Use TIM3 Input 1 (from PA6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR tim3_isr -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR tim3_isr +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM_PIN_AF GPIO_AF2 #if ENABLE_DEBUG == 1 extern bool debug_bmp; diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index c9bf54a124d..8f71a710612 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -127,24 +127,24 @@ #define IRQ_PRI_USB (1U << 4U) #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) /* Use TIM3 Input 1 (from PC6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR(x) tim3_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM_PIN_AF GPIO_AF2 #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index 76295e51a81..5e505299f56 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -106,7 +106,7 @@ #define IRQ_PRI_USB (1U << 4U) #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 @@ -129,21 +129,21 @@ #define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4 /* Use TIM3 Input 1 (from PC6), AF2, trigger on rising edge. */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 -#define TRACE_TIM_PIN_AF GPIO_AF2 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR(x) tim3_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM_PIN_AF GPIO_AF2 #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 929112a8e95..846f504c065 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -89,10 +89,10 @@ extern uint8_t running_status; gpio_mode_setup(GPIOA_BASE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); \ } while (0) -#define TRACEUART UART2 -#define TRACEUART_CLK RCC_UART2 -#define TRACEUART_IRQ NVIC_UART2_IRQ -#define TRACEUART_ISR uart2_isr +#define SWO_UART UART2 +#define SWO_UART_CLK RCC_UART2 +#define SWO_UART_IRQ NVIC_UART2_IRQ +#define SWO_UART_ISR uart2_isr #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 632df911d59..475ec91de7a 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -260,7 +260,7 @@ extern int hwversion; #define IRQ_PRI_USBUSART (2U << 4U) #define IRQ_PRI_USBUSART_DMA (2U << 4U) #define IRQ_PRI_USB_VBUS (14U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define USBUSART HW_SWITCH(6, USBUSART1, USBUSART2) #define USBUSART_IRQ HW_SWITCH(6, NVIC_USART1_IRQ, NVIC_USART2_IRQ) @@ -298,20 +298,20 @@ extern int hwversion; #if TRACESWO_PROTOCOL == 1U /* Use TIM3 Input 1 (from PA6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR(x) tim3_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 #endif #define SET_RUN_STATE(state) running_status = (state) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index b801d015671..5339a30f0e4 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -130,7 +130,7 @@ extern bool debug_bmp; #define IRQ_PRI_USBUSART_DMA (2U << 4U) #define IRQ_PRI_USB_VBUS (14U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #ifdef SWIM_NRST_AS_UART #define USBUSART USART1 @@ -172,26 +172,26 @@ extern bool debug_bmp; #ifndef SWIM_AS_UART #define PLATFORM_HAS_TRACESWO 1 #endif -#define NUM_TRACE_PACKETS 128U /* This is an 8K buffer */ +#define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ //#define TRACESWO_PROTOCOL 2U /* 1 = Manchester, 2 = NRZ / async */ #if TRACESWO_PROTOCOL == 1 /* Use TIM3 Input 1 (from PA6/TDO) */ -#define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) -#define TRACE_IRQ NVIC_TIM3_IRQ -#define TRACE_ISR(x) tim3_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI1 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI1FP1 +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) +#define SWO_TIM_IRQ NVIC_TIM3_IRQ +#define SWO_TIM_ISR(x) tim3_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI1 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 #elif TRACESWO_PROTOCOL == 2 diff --git a/src/platforms/stlinkv3/platform.h b/src/platforms/stlinkv3/platform.h index b43c14f1e36..eee2eb7d75e 100644 --- a/src/platforms/stlinkv3/platform.h +++ b/src/platforms/stlinkv3/platform.h @@ -84,7 +84,7 @@ extern bool debug_bmp; #define MCO1_PIN GPIO8 #define MCO1_AF 0 -#define NUM_TRACE_PACKETS 16U +#define NUM_SWO_PACKETS 16U #define SWDIO_MODE_REG GPIO_MODER(TMS_PORT) #define SWDIO_MODE_REG_MULT (1U << (9U << 1U)) diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index ea1945414ce..e32ab9be5e5 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -99,7 +99,7 @@ extern bool debug_bmp; #define IRQ_PRI_USBUSART_DMA (2U << 4U) #define IRQ_PRI_USB_VBUS (14U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#define IRQ_PRI_TRACE (0U << 4U) +#define IRQ_PRI_SWO_TIM (0U << 4U) #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 @@ -122,26 +122,26 @@ extern bool debug_bmp; #define USBUSART_DMA_RX_ISR(x) dma1_channel5_isr(x) #define PLATFORM_HAS_TRACESWO 1 -#define NUM_TRACE_PACKETS 128U /* This is an 8K buffer */ +#define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ //#define TRACESWO_PROTOCOL 2U /* 1 = Manchester, 2 = NRZ / async */ #if TRACESWO_PROTOCOL == 1 /* Use TIM2 Input 2 (from PB3/TDO with Remap) */ -#define TRACE_TIM TIM2 -#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) -#define TRACE_IRQ NVIC_TIM2_IRQ -#define TRACE_ISR(x) tim2_isr(x) -#define TRACE_IC_IN TIM_IC_IN_TI2 -#define TRACE_IC_RISING TIM_IC1 -#define TRACE_CC_RISING TIM3_CCR1 -#define TRACE_ITR_RISING TIM_DIER_CC1IE -#define TRACE_STATUS_RISING TIM_SR_CC1IF -#define TRACE_IC_FALLING TIM_IC2 -#define TRACE_CC_FALLING TIM3_CCR2 -#define TRACE_STATUS_FALLING TIM_SR_CC2IF -#define TRACE_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) -#define TRACE_TRIG_IN TIM_SMCR_TS_TI2FP2 +#define SWO_TIM TIM2 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) +#define SWO_TIM_IRQ NVIC_TIM2_IRQ +#define SWO_TIM_ISR(x) tim2_isr(x) +#define SWO_IC_IN TIM_IC_IN_TI2 +#define SWO_IC_RISING TIM_IC1 +#define SWO_CC_RISING TIM3_CCR1 +#define SWO_ITR_RISING TIM_DIER_CC1IE +#define SWO_STATUS_RISING TIM_SR_CC1IF +#define SWO_IC_FALLING TIM_IC2 +#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) +#define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 #elif TRACESWO_PROTOCOL == 2 From ff690e263a0b293f88a2025087b70743a003e134 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 07:22:21 +0100 Subject: [PATCH 19/48] native/platform: Added defines for UART-encoded SWO data recovery --- src/platforms/native/platform.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 475ec91de7a..3af7c4dd35f 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -261,6 +261,7 @@ extern int hwversion; #define IRQ_PRI_USBUSART_DMA (2U << 4U) #define IRQ_PRI_USB_VBUS (14U << 4U) #define IRQ_PRI_SWO_TIM (0U << 4U) +#define IRQ_PRI_SWO_DMA (0U << 4U) #define USBUSART HW_SWITCH(6, USBUSART1, USBUSART2) #define USBUSART_IRQ HW_SWITCH(6, NVIC_USART1_IRQ, NVIC_USART2_IRQ) @@ -296,8 +297,9 @@ extern int hwversion; #define USBUSART2_DMA_RX_IRQ NVIC_DMA1_CHANNEL6_IRQ #define USBUSART2_DMA_RX_ISR(x) dma1_channel6_isr(x) -#if TRACESWO_PROTOCOL == 1U -/* Use TIM3 Input 1 (from PA6/TDO) */ +#define NUM_SWO_PACKETS 8U /* 512B buffer */ + +/* Use TIM3 Input 1 (from PA6/TDO) for Manchester data recovery */ #define SWO_TIM TIM3 #define SWO_TIM_CLK_EN() #define SWO_TIM_IRQ NVIC_TIM3_IRQ @@ -312,7 +314,19 @@ extern int hwversion; #define SWO_STATUS_FALLING TIM_SR_CC2IF #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 -#endif + +/* Use PA10 (USART1) on HW6+ for UART/NRZ/Async data recovery */ +#define SWO_UART HW_SWITCH(6, 0U, USART1) +#define SWO_UART_CLK RCC_USART1 +#define SWO_UART_DR USART1_DR +#define SWO_UART_PORT GPIOA +#define SWO_UART_RX_PIN GPIO10 + +#define SWO_DMA_BUS DMA1 +#define SWO_DMA_CLK RCC_DMA1 +#define SWO_DMA_CHAN DMA_CHANNEL5 +#define SWO_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ +#define SWO_DMA_ISR(x) dma1_channel5_isr(x) #define SET_RUN_STATE(state) running_status = (state) #define SET_IDLE_STATE(state) gpio_set_val(LED_PORT, LED_IDLE_RUN, state) From 0337654a3e0773f1651231c4b9859e7ac5db1be3 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Sep 2024 18:55:49 +0100 Subject: [PATCH 20/48] common/stm32/swo_uart: Restructured the code to put the interaction control routines at the top --- src/platforms/common/stm32/swo_uart.c | 106 +++++++++++++------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 2cb504adbdf..a137d569fb5 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -67,6 +67,59 @@ static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; +static void swo_uart_set_baud(uint32_t baudrate); + +void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) +{ + /* Skip initial allocation on commands for mode change */ + if (trace_rx_buf == NULL) { + /* Alignment (bytes): 1 for UART DMA, 2-4 for memcpy in usb code, 8 provided by malloc. Not 64 */ + uint8_t *const newbuf = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); + if (!newbuf) { + DEBUG_ERROR("malloc: failed in %s\n", __func__); + return; + } + trace_rx_buf = newbuf; + } + + if (!baudrate) + baudrate = SWO_DEFAULT_BAUD; + + rcc_periph_clock_enable(SWO_UART_CLK); + rcc_periph_clock_enable(SWO_DMA_CLK); + +#if defined(STM32F1) + gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SWO_UART_RX_PIN); + /* Pull SWO pin high to keep open SWO line ind uart idle state! */ + gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); +#else + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SWO_UART_RX_PIN); + gpio_set_output_options(SWO_UART_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_100MHZ, SWO_UART_RX_PIN); + gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); +#endif + + nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); + nvic_enable_irq(SWO_DMA_IRQ); + swo_uart_set_baud(baudrate); + swo_itm_decode_set_mask(swo_chan_bitmask); + decoding = (swo_chan_bitmask != 0); +} + +void swo_uart_deinit(void) +{ + /* Stop peripherals servicing */ + nvic_disable_irq(SWO_DMA_IRQ); + dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); + usart_disable(SWO_UART); + /* Dump the buffered remains */ + swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); + /* Return this contiguous chunk of SRAM to unshrinkable heap */ + if (trace_rx_buf != NULL) { + free(trace_rx_buf); + trace_rx_buf = NULL; + } +} + void swo_send_buffer(usbd_device *dev, uint8_t ep) { static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; @@ -95,7 +148,7 @@ uint32_t swo_uart_get_baudrate(void) return usart_get_baudrate(SWO_UART); } -void traceswo_setspeed(uint32_t baudrate) +static void swo_uart_set_baud(const uint32_t baudrate) { dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_disable(SWO_UART); @@ -147,54 +200,3 @@ void SWO_DMA_ISR(void) write_index = (write_index + 1U) % NUM_SWO_PACKETS; swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); } - -void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) -{ - /* Skip initial allocation on commands for mode change */ - if (trace_rx_buf == NULL) { - /* Alignment (bytes): 1 for UART DMA, 2-4 for memcpy in usb code, 8 provided by malloc. Not 64 */ - uint8_t *const newbuf = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); - if (!newbuf) { - DEBUG_ERROR("malloc: failed in %s\n", __func__); - return; - } - trace_rx_buf = newbuf; - } - - if (!baudrate) - baudrate = SWO_DEFAULT_BAUD; - - rcc_periph_clock_enable(SWO_UART_CLK); - rcc_periph_clock_enable(SWO_DMA_CLK); - -#if defined(STM32F1) - gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SWO_UART_RX_PIN); - /* Pull SWO pin high to keep open SWO line ind uart idle state! */ - gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); -#else - gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SWO_UART_RX_PIN); - gpio_set_output_options(SWO_UART_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_100MHZ, SWO_UART_RX_PIN); - gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); -#endif - - nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); - nvic_enable_irq(SWO_DMA_IRQ); - traceswo_setspeed(baudrate); - swo_itm_decode_set_mask(swo_chan_bitmask); - decoding = (swo_chan_bitmask != 0); -} - -void swo_uart_deinit(void) -{ - /* Stop peripherals servicing */ - nvic_disable_irq(SWO_DMA_IRQ); - dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); - usart_disable(SWO_UART); - /* Dump the buffered remains */ - swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); - /* Return this contiguous chunk of SRAM to unshrinkable heap */ - if (trace_rx_buf != NULL) { - free(trace_rx_buf); - trace_rx_buf = NULL; - } -} From 5e1bc4013391573e75b91472bb8b0ee42b462f43 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 10 Sep 2024 04:04:30 +0100 Subject: [PATCH 21/48] native/platform: Implemented a mechanism for dispatching to the appropriate hwversion-dependant handler for DMA completion on DMA1's Channel 5 --- src/platforms/native/platform.c | 10 ++++++++++ src/platforms/native/platform.h | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index e6fb8b96dff..078e456b72d 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -570,3 +570,13 @@ static void setup_vbus_irq(void) exti15_10_isr(); } + +void dma1_channel5_isr(void) +{ + if (hwversion < 6) + usart1_rx_dma_isr(); +#if TRACE_PROTOCOL != 1 + else + swo_dma_isr(); +#endif +} diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 3af7c4dd35f..38c488a0523 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -285,7 +285,7 @@ extern int hwversion; #define USBUSART1_DMA_TX_ISR(x) dma1_channel4_isr(x) #define USBUSART1_DMA_RX_CHAN DMA_CHANNEL5 #define USBUSART1_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ -#define USBUSART1_DMA_RX_ISR(x) dma1_channel5_isr(x) +#define USBUSART1_DMA_RX_ISR(x) usart1_rx_dma_isr(x) #define USBUSART2 USART2 #define USBUSART2_IRQ NVIC_USART2_IRQ @@ -326,12 +326,20 @@ extern int hwversion; #define SWO_DMA_CLK RCC_DMA1 #define SWO_DMA_CHAN DMA_CHANNEL5 #define SWO_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ -#define SWO_DMA_ISR(x) dma1_channel5_isr(x) +#define SWO_DMA_ISR(x) swo_dma_isr(x) #define SET_RUN_STATE(state) running_status = (state) #define SET_IDLE_STATE(state) gpio_set_val(LED_PORT, LED_IDLE_RUN, state) #define SET_ERROR_STATE(state) gpio_set_val(LED_PORT, LED_ERROR, state) +/* + * These are bounce declarations for the ISR handlers competing for dma1_channel5_isr(). + * The actual handler is defined in platform.c, the USART1 RX handler in aux_serial.c, + * and the SWO DMA handler in swo_uart.c. + */ +void usart1_rx_dma_isr(void); +void swo_dma_isr(void); + /* Frequency constants (in Hz) for the bitbanging routines */ #define BITBANG_CALIBRATED_FREQS /* From 44cb5cef76fa24b6a7efd062722ee103e3f021b0 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 10 Sep 2024 04:09:23 +0100 Subject: [PATCH 22/48] native: Enabled building UART instead of Manchester mode for SWO in the firmware --- src/platforms/native/meson.build | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platforms/native/meson.build b/src/platforms/native/meson.build index 9ab3f90d0c0..50a1e9c51f9 100644 --- a/src/platforms/native/meson.build +++ b/src/platforms/native/meson.build @@ -41,10 +41,11 @@ probe_native_args = [ trace_protocol = get_option('trace_protocol') if trace_protocol in ['1', '3'] - probe_native_args += [f'-DTRACESWO_PROTOCOL=1'] + probe_native_args += ['-DTRACESWO_PROTOCOL=1'] probe_native_dependencies = platform_stm32_swo_manchester else - error('Unsupported SWO mode requested') + probe_native_args += ['-DTRACESWO_PROTOCOL=2'] + probe_native_dependencies = platform_stm32_swo_uart endif probe_native_common_link_args = [ From 640b904019af15b14c58fd20340ef47d99afc6d2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 10 Sep 2024 04:27:41 +0100 Subject: [PATCH 23/48] common: Bought the nomenclature for the SWO encoding definition into harmony with the rest of the naming for the SWO implementation --- src/command.c | 8 ++++---- src/platforms/common/blackpill-f4/Makefile.inc | 2 +- src/platforms/common/blackpill-f4/blackpill-f4.h | 6 +++--- src/platforms/common/blackpill-f4/meson.build | 2 +- src/platforms/common/swo.h | 11 ++++++----- src/platforms/ctxlink/Makefile.inc | 2 +- src/platforms/ctxlink/meson.build | 2 +- src/platforms/ctxlink/platform.h | 6 +++--- src/platforms/native/Makefile.inc | 2 +- src/platforms/native/meson.build | 4 ++-- src/platforms/native/platform.c | 2 +- src/platforms/stlink/Makefile.inc | 2 +- src/platforms/stlink/meson.build | 6 +++--- src/platforms/stlink/platform.h | 8 ++++---- src/platforms/stlinkv3/Makefile.inc | 2 +- src/platforms/stlinkv3/meson.build | 2 +- src/platforms/swlink/Makefile.inc | 2 +- src/platforms/swlink/meson.build | 2 +- src/platforms/swlink/platform.h | 8 ++++---- 19 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/command.c b/src/command.c index 8df082677e6..8fc9a65ed07 100644 --- a/src/command.c +++ b/src/command.c @@ -109,7 +109,7 @@ const command_s cmd_list[] = { "MAXERR]]"}, #endif #ifdef PLATFORM_HAS_TRACESWO -#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2 +#if defined SWO_ENCODING && SWO_ENCODING == 2 {"swo", cmd_swo, "Start SWO capture, UART mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, #else {"swo", cmd_swo, "Start SWO capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, @@ -612,7 +612,7 @@ static bool cmd_swo_enable(int argc, const char **argv) */ uint32_t itm_stream_mask = 0U; uint8_t decode_arg = 1U; -#if TRACESWO_PROTOCOL == 2 +#if SWO_ENCODING == 2 uint32_t baudrate = SWO_DEFAULT_BAUD; /* Handle the optional baud rate argument if present */ if (argc > 1 && argv[1][0] >= '0' && argv[1][0] <= '9') { @@ -640,7 +640,7 @@ static bool cmd_swo_enable(int argc, const char **argv) } /* Now enable SWO data recovery */ -#if TRACESWO_PROTOCOL == 2 +#if SWO_ENCODING == 2 swo_uart_init(baudrate, itm_stream_mask); gdb_outf("Baudrate: %lu ", swo_uart_get_baudrate()); #else @@ -660,7 +660,7 @@ static bool cmd_swo_enable(int argc, const char **argv) static bool cmd_swo_disable(void) { -#if TRACESWO_PROTOCOL == 1 +#if SWO_ENCODING == 1 swo_manchester_deinit(); #else swo_uart_deinit(); diff --git a/src/platforms/common/blackpill-f4/Makefile.inc b/src/platforms/common/blackpill-f4/Makefile.inc index 34bdbcfb389..086e1b21608 100644 --- a/src/platforms/common/blackpill-f4/Makefile.inc +++ b/src/platforms/common/blackpill-f4/Makefile.inc @@ -80,7 +80,7 @@ else ifeq ($(SWO_ENCODING), 3) else # If we got some other value, that's an error so report it $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif -CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) +CFLAGS += -DSWO_ENCODING=$(SWO_ENCODING) ifneq ($(BMD_BOOTLOADER), 1) all: blackmagic.bin diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index 4154b1511a8..bcc71a00426 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -290,7 +290,7 @@ extern bool debug_bmp; #define PLATFORM_HAS_TRACESWO #define NUM_SWO_PACKETS 256U /* 16K buffer */ -#if TRACESWO_PROTOCOL == 1 +#if SWO_ENCODING == 1 /* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, triggered on rising edge */ #define SWO_TIM TIM4 @@ -309,7 +309,7 @@ extern bool debug_bmp; #define SWO_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) #define SWO_TIM_PIN_AF GPIO_AF2 -#elif TRACESWO_PROTOCOL == 2 +#elif SWO_ENCODING == 2 /* On F411 use USART1_RX mapped on PB7 for async capture */ #define SWO_UART USBUSART1 @@ -327,7 +327,7 @@ extern bool debug_bmp; #define SWO_DMA_ISR(x) USBUSART1_DMA_RX_ISRx(x) #define SWO_DMA_TRG DMA_SxCR_CHSEL_4 -#endif /* TRACESWO_PROTOCOL */ +#endif /* SWO_ENCODING */ #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/common/blackpill-f4/meson.build b/src/platforms/common/blackpill-f4/meson.build index 154e9811b1d..56ea8072724 100644 --- a/src/platforms/common/blackpill-f4/meson.build +++ b/src/platforms/common/blackpill-f4/meson.build @@ -70,7 +70,7 @@ trace_protocol = get_option('trace_protocol') if trace_protocol == '3' trace_protocol = '2' endif -probe_blackpill_args += [f'-DTRACESWO_PROTOCOL=@trace_protocol@'] +probe_blackpill_args += [f'-DSWO_ENCODING=@trace_protocol@'] if trace_protocol == '1' probe_blackpill_dependencies = platform_stm32_swo_manchester else diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 34e780e7d54..82483470a85 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -25,19 +25,20 @@ #include -#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2 /* Default line rate, used as default for a request without baudrate */ #define SWO_DEFAULT_BAUD 2250000U + +/* Initialisation and deinitialisation functions (ties into command.c) */ +void swo_manchester_init(uint32_t itm_stream_bitmask); void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask); +void swo_manchester_deinit(void); void swo_uart_deinit(void); +/* UART mode baudate functions */ uint32_t swo_uart_get_baudrate(void); void bmd_usart_set_baudrate(uint32_t usart, uint32_t baud_rate); -#else -void swo_manchester_init(uint32_t itm_stream_bitmask); -void swo_manchester_deinit(void); -#endif +/* USB callback for the raw data endpoint to ask for a new buffer of data */ void swo_send_buffer(usbd_device *dev, uint8_t ep); /* Set a bitmask of SWO ITM streams to be decoded */ diff --git a/src/platforms/ctxlink/Makefile.inc b/src/platforms/ctxlink/Makefile.inc index efec7905b65..053beb32881 100644 --- a/src/platforms/ctxlink/Makefile.inc +++ b/src/platforms/ctxlink/Makefile.inc @@ -41,7 +41,7 @@ else ifeq ($(SWO_ENCODING), 3) else # If we got some other value, that's an error so report it $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif -CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) +CFLAGS += -DSWO_ENCODING=$(SWO_ENCODING) all: blackmagic.bin diff --git a/src/platforms/ctxlink/meson.build b/src/platforms/ctxlink/meson.build index 46f3e2b4506..a97647695a3 100644 --- a/src/platforms/ctxlink/meson.build +++ b/src/platforms/ctxlink/meson.build @@ -40,7 +40,7 @@ trace_protocol = get_option('trace_protocol') if trace_protocol == '3' trace_protocol = '2' endif -probe_ctxlink_args += [f'-DTRACESWO_PROTOCOL=@trace_protocol@'] +probe_ctxlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] if trace_protocol == '1' probe_ctxlink_dependencies = platform_stm32_swo_manchester else diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index a2123d86f6c..108be6cae3a 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -186,7 +186,7 @@ #define PLATFORM_HAS_TRACESWO #define NUM_SWO_PACKETS 256U /* 16K buffer */ -#if TRACESWO_PROTOCOL == 1 +#if SWO_ENCODING == 1 /* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ #define SWO_TIM TIM3 @@ -205,7 +205,7 @@ #define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 #define SWO_TIM_PIN_AF GPIO_AF2 -#elif TRACESWO_PROTOCOL == 2 +#elif SWO_ENCODING == 2 /* On ctxLink use USART6_RX mapped on PC7 for async capture */ #define SWO_UART USART6 @@ -223,7 +223,7 @@ #define SWO_DMA_ISR dma2_stream1_isr #define SWO_DMA_TRG DMA_SxCR_CHSEL_5 -#endif /* TRACESWO_PROTOCOL */ +#endif /* SWO_ENCODING */ #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 8555a56325c..064d0bb141b 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -4,7 +4,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DBLACKMAGIC -I../deps/libopencm3/include \ - -Iplatforms/common/stm32 -DDFU_SERIAL_LENGTH=9 -DTRACESWO_PROTOCOL=1 + -Iplatforms/common/stm32 -DDFU_SERIAL_LENGTH=9 -DSWO_ENCODING=1 LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Lplatforms/native \ -Tnative.ld --specs=nano.specs -nostartfiles -lc \ diff --git a/src/platforms/native/meson.build b/src/platforms/native/meson.build index 50a1e9c51f9..0dceaaa673d 100644 --- a/src/platforms/native/meson.build +++ b/src/platforms/native/meson.build @@ -41,10 +41,10 @@ probe_native_args = [ trace_protocol = get_option('trace_protocol') if trace_protocol in ['1', '3'] - probe_native_args += ['-DTRACESWO_PROTOCOL=1'] + probe_native_args += ['-DSWO_ENCODING=1'] probe_native_dependencies = platform_stm32_swo_manchester else - probe_native_args += ['-DTRACESWO_PROTOCOL=2'] + probe_native_args += ['-DSWO_ENCODING=2'] probe_native_dependencies = platform_stm32_swo_uart endif diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 078e456b72d..e90d05c4be7 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -575,7 +575,7 @@ void dma1_channel5_isr(void) { if (hwversion < 6) usart1_rx_dma_isr(); -#if TRACE_PROTOCOL != 1 +#if SWO_ENCODING != 1 else swo_dma_isr(); #endif diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 7d0baa843df..91df677ce6e 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -50,7 +50,7 @@ else else # If we got some other value, that's an error so report it $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif - CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) + CFLAGS += -DSWO_ENCODING=$(SWO_ENCODING) endif ifeq ($(BLUEPILL), 1) diff --git a/src/platforms/stlink/meson.build b/src/platforms/stlink/meson.build index a70936f06ed..d4490103718 100644 --- a/src/platforms/stlink/meson.build +++ b/src/platforms/stlink/meson.build @@ -76,13 +76,13 @@ endif if probe == 'stlink' and stlink_swim_nrst_as_uart probe_stlink_args += ['-DSWIM_NRST_AS_UART=1'] probe_stlink_dependencies += platform_stm32_swo_manchester - probe_stlink_args += ['-DTRACESWO_PROTOCOL=1'] + probe_stlink_args += ['-DSWO_ENCODING=1'] elif trace_protocol == '1' probe_stlink_dependencies += platform_stm32_swo_manchester - probe_stlink_args += ['-DTRACESWO_PROTOCOL=1'] + probe_stlink_args += ['-DSWO_ENCODING=1'] elif trace_protocol == '2' probe_stlink_dependencies += platform_stm32_swo_uart - probe_stlink_args += ['-DTRACESWO_PROTOCOL=2'] + probe_stlink_args += ['-DSWO_ENCODING=2'] else error('Unsupported SWO mode requested') endif diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 5339a30f0e4..fe0cf1b6c55 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -173,9 +173,9 @@ extern bool debug_bmp; #define PLATFORM_HAS_TRACESWO 1 #endif #define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ -//#define TRACESWO_PROTOCOL 2U /* 1 = Manchester, 2 = NRZ / async */ +//#define SWO_ENCODING 2U /* 1 = Manchester, 2 = NRZ / async */ -#if TRACESWO_PROTOCOL == 1 +#if SWO_ENCODING == 1 /* Use TIM3 Input 1 (from PA6/TDO) */ #define SWO_TIM TIM3 @@ -193,7 +193,7 @@ extern bool debug_bmp; #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 -#elif TRACESWO_PROTOCOL == 2 +#elif SWO_ENCODING == 2 /* On F103, only USART1 is on AHB2 and can reach 4.5MBaud at 72 MHz. */ #define SWO_UART USART1 @@ -209,7 +209,7 @@ extern bool debug_bmp; #define SWO_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ #define SWO_DMA_ISR(x) dma1_channel5_isr(x) -#endif /* TRACESWO_PROTOCOL */ +#endif /* SWO_ENCODING */ extern uint16_t led_idle_run; #define LED_IDLE_RUN led_idle_run diff --git a/src/platforms/stlinkv3/Makefile.inc b/src/platforms/stlinkv3/Makefile.inc index 9256a6990a1..736b33eed19 100644 --- a/src/platforms/stlinkv3/Makefile.inc +++ b/src/platforms/stlinkv3/Makefile.inc @@ -5,7 +5,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy OPT_FLAGS = -Og -g CFLAGS += -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard \ -DSTM32F7 -DDFU_SERIAL_LENGTH=25 -I../deps/libopencm3/include \ - -I platforms/common/stm32 -DTRACESWO_PROTOCOL=2 + -I platforms/common/stm32 -DSWO_ENCODING=2 LDFLAGS_BOOT := $(LDFLAGS) -mfpu=fpv5-sp-d16 -mfloat-abi=hard \ --specs=nano.specs -lopencm3_stm32f7 -Lplatforms/stlinkv3 \ -Tstlinkv3.ld -nostartfiles -lc \ diff --git a/src/platforms/stlinkv3/meson.build b/src/platforms/stlinkv3/meson.build index a26db5b04cf..d9039389d7c 100644 --- a/src/platforms/stlinkv3/meson.build +++ b/src/platforms/stlinkv3/meson.build @@ -64,7 +64,7 @@ if trace_protocol == '3' endif if trace_protocol == '2' probe_stlinkv3_dependencies = platform_stm32f7_swo_uart - probe_stlinkv3_args += ['-DTRACESWO_PROTOCOL=2'] + probe_stlinkv3_args += ['-DSWO_ENCODING=2'] else error('Unsupported SWO protocol requested') endif diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index e85bf9ee1b7..21c7b437875 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -45,7 +45,7 @@ else ifeq ($(SWO_ENCODING), 3) else # If we got some other value, that's an error so report it $(error Invalid value for SWO encoding, must be one of 1, 2, or 3) endif -CFLAGS += -DTRACESWO_PROTOCOL=$(SWO_ENCODING) +CFLAGS += -DSWO_ENCODING=$(SWO_ENCODING) all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/swlink/meson.build b/src/platforms/swlink/meson.build index 46a8661e7d0..cb0bc117983 100644 --- a/src/platforms/swlink/meson.build +++ b/src/platforms/swlink/meson.build @@ -58,7 +58,7 @@ if trace_protocol == '3' trace_protocol = '2' endif if trace_protocol == '2' - probe_swlink_args += '-DTRACESWO_PROTOCOL=2' + probe_swlink_args += '-DSWO_ENCODING=2' else error('Unsupported SWO protocol requested') endif diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index e32ab9be5e5..11cc2e87670 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -123,9 +123,9 @@ extern bool debug_bmp; #define PLATFORM_HAS_TRACESWO 1 #define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ -//#define TRACESWO_PROTOCOL 2U /* 1 = Manchester, 2 = NRZ / async */ +//#define SWO_ENCODING 2U /* 1 = Manchester, 2 = NRZ / async */ -#if TRACESWO_PROTOCOL == 1 +#if SWO_ENCODING == 1 /* Use TIM2 Input 2 (from PB3/TDO with Remap) */ #define SWO_TIM TIM2 @@ -143,7 +143,7 @@ extern bool debug_bmp; #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 -#elif TRACESWO_PROTOCOL == 2 +#elif SWO_ENCODING == 2 /* * On F103, only USART1 is on AHB2 and can reach 4.5MBaud at 72 MHz. @@ -163,7 +163,7 @@ extern bool debug_bmp; #define SWO_DMA_IRQ NVIC_DMA1_CHANNEL6_IRQ #define SWO_DMA_ISR(x) dma1_channel6_isr(x) -#endif /* TRACESWO_PROTOCOL */ +#endif /* SWO_ENCODING */ #define LED_PORT GPIOC #define LED_IDLE_RUN GPIO15 From 93069f732703a46a311bedbf7ed325d8286c456e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 12 Sep 2024 01:09:33 +0100 Subject: [PATCH 24/48] common/swo: Started building out a mechanism to allow the SWO implementations to be dynamically switched between --- src/command.c | 6 +- src/platforms/common/stm32/meson.build | 1 + src/platforms/common/stm32/swo.c | 62 +++++++++++++++++++++ src/platforms/common/stm32/swo_internal.h | 32 +++++++++++ src/platforms/common/stm32/swo_manchester.c | 3 +- src/platforms/common/stm32/swo_uart.c | 3 +- src/platforms/common/stm32/swo_uart_f723.c | 9 +-- src/platforms/common/swo.h | 11 +++- 8 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 src/platforms/common/stm32/swo.c create mode 100644 src/platforms/common/stm32/swo_internal.h diff --git a/src/command.c b/src/command.c index 8fc9a65ed07..b787de51e38 100644 --- a/src/command.c +++ b/src/command.c @@ -660,11 +660,7 @@ static bool cmd_swo_enable(int argc, const char **argv) static bool cmd_swo_disable(void) { -#if SWO_ENCODING == 1 - swo_manchester_deinit(); -#else - swo_uart_deinit(); -#endif + swo_deinit(); gdb_out("Trace disabled\n"); return true; } diff --git a/src/platforms/common/stm32/meson.build b/src/platforms/common/stm32/meson.build index e2f9ebb5515..85d9f58d1be 100644 --- a/src/platforms/common/stm32/meson.build +++ b/src/platforms/common/stm32/meson.build @@ -34,6 +34,7 @@ platform_stm32_sources = files( 'gdb_if.c', 'serialno.c', 'timing_stm32.c', + 'swo.c', 'swo_itm_decode.c', ) diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c new file mode 100644 index 00000000000..6019bfb12e5 --- /dev/null +++ b/src/platforms/common/stm32/swo.c @@ -0,0 +1,62 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2024 1BitSquared + * Modified by Rachel Mant + * + * 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 . + */ + +#include "swo.h" +#include "swo_internal.h" + +/* + * Management and muxing layer for the SWO implementations + * + * SWO_ENCODING takes 3 possible states guaranteed by the build system: + * 1: Manchester coded SWO only + * 2: UART/NRZ coded SWO only + * 3: Both enabled w/ the full switching mechanism provided + * + * It is an error for SWO_ENCODING to be undefined if PLATFORM_HAS_TRACESWO is + * defined by the platform. It is an error to include this file in the build + * under this circumstance as it requires SWO_ENCODING to be defined and valid. + */ + +swo_coding_e swo_current_coding; + +void swo_deinit(void) +{ +#if SWO_ENCODING == 1 || SWO_ENCODING == 3 + if (swo_current_coding == swo_manchester) + swo_manchester_deinit(); +#endif +#if SWO_ENCODING == 2 || SWO_ENCODING == 3 + if (swo_current_coding == swo_nrz_uart) + swo_uart_deinit(); +#endif + swo_current_coding = swo_none; +} + +void swo_send_buffer(usbd_device *const dev, const uint8_t ep) +{ +#if SWO_ENCODING == 1 || SWO_ENCODING == 3 + if (swo_current_coding == swo_manchester) + swo_manchester_send_buffer(dev, ep); +#endif +#if SWO_ENCODING == 2 || SWO_ENCODING == 3 + if (swo_current_coding == swo_nrz_uart) + swo_uart_send_buffer(dev, ep); +#endif +} diff --git a/src/platforms/common/stm32/swo_internal.h b/src/platforms/common/stm32/swo_internal.h new file mode 100644 index 00000000000..e5053cf1124 --- /dev/null +++ b/src/platforms/common/stm32/swo_internal.h @@ -0,0 +1,32 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2024 1BitSquared + * Written by Rachel Mant + * + * 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 . + */ + +#ifndef PLATFORMS_COMMON_STM32_SWO_INTERNAL_H +#define PLATFORMS_COMMON_STM32_SWO_INTERNAL_H + +/* Manchester-mode implementation functions */ +void swo_manchester_deinit(void); +void swo_manchester_send_buffer(usbd_device *dev, uint8_t ep); + +/* UART-mode implementation functions */ +void swo_uart_deinit(void); +void swo_uart_send_buffer(usbd_device *dev, uint8_t ep); + +#endif /* PLATFORMS_COMMON_STM32_SWO_INTERNAL_H */ diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 23cabafa7e1..d3adb6a1a92 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -44,6 +44,7 @@ #include "platform.h" #include "usb.h" #include "swo.h" +#include "swo_internal.h" #include #include @@ -158,7 +159,7 @@ void swo_buffer_data(void) swo_data_bit_index = 0U; } -void swo_send_buffer(usbd_device *dev, uint8_t ep) +void swo_manchester_send_buffer(usbd_device *const dev, const uint8_t ep) { if (!swo_transmit_buffer_index) return; diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index a137d569fb5..487a81341e5 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -32,6 +32,7 @@ #include "platform.h" #include "usb.h" #include "swo.h" +#include "swo_internal.h" #include #include @@ -120,7 +121,7 @@ void swo_uart_deinit(void) } } -void swo_send_buffer(usbd_device *dev, uint8_t ep) +void swo_uart_send_buffer(usbd_device *const dev, const uint8_t ep) { static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c index a059497c326..6989b743535 100644 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -34,6 +34,7 @@ #include "platform.h" #include "usb.h" #include "swo.h" +#include "swo_internal.h" #include #include @@ -51,7 +52,7 @@ static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; /* SWO decoding */ static bool decoding = false; -void swo_send_buffer(usbd_device *dev, uint8_t ep) +void swo_uart_send_buffer(usbd_device *dev, uint8_t ep) { static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; @@ -63,7 +64,7 @@ void swo_send_buffer(usbd_device *dev, uint8_t ep) uint16_t result; if (decoding) /* write decoded swo packets to the uart port */ - result = traceswo_decode( + result = swo_itm_decode( dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); else /* write raw swo packets to the trace port */ @@ -79,7 +80,7 @@ uint32_t swo_uart_get_baudrate(void) return usart_get_baudrate(SWO_UART); } -void traceswo_setspeed(uint32_t baudrate) +void swo_uart_set_baud(uint32_t baudrate) { dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); usart_disable(SWO_UART); @@ -141,7 +142,7 @@ void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); nvic_enable_irq(SWO_DMA_IRQ); - traceswo_setspeed(baudrate); + swo_uart_set_baud(baudrate); traceswo_setmask(swo_chan_bitmask); decoding = swo_chan_bitmask != 0; } diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 82483470a85..e618767d2d6 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -28,11 +28,18 @@ /* Default line rate, used as default for a request without baudrate */ #define SWO_DEFAULT_BAUD 2250000U +typedef enum swo_coding { + swo_none, + swo_manchester, + swo_nrz_uart, +} swo_coding_e; + +extern swo_coding_e swo_current_coding; + /* Initialisation and deinitialisation functions (ties into command.c) */ void swo_manchester_init(uint32_t itm_stream_bitmask); void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask); -void swo_manchester_deinit(void); -void swo_uart_deinit(void); +void swo_deinit(void); /* UART mode baudate functions */ uint32_t swo_uart_get_baudrate(void); From e306eff3020f768ec9a13ae791b37ea6e948bb31 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 12 Sep 2024 01:23:40 +0100 Subject: [PATCH 25/48] common/swo: Implemented switched initialisation for decoding --- src/command.c | 48 ++++++++++++++++------- src/platforms/common/stm32/swo.c | 38 +++++++++++++++--- src/platforms/common/stm32/swo_internal.h | 2 + src/platforms/common/swo.h | 5 +-- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/command.c b/src/command.c index b787de51e38..093c8d1e7a9 100644 --- a/src/command.c +++ b/src/command.c @@ -606,20 +606,45 @@ static bool cmd_rtt(target_s *t, int argc, const char **argv) #ifdef PLATFORM_HAS_TRACESWO static bool cmd_swo_enable(int argc, const char **argv) { + /* Set up which mode we're going to default to */ +#if SWO_ENCODING == 1 + const swo_coding_e capture_mode = swo_manchester; +#elif SWO_ENCODING == 2 + const swo_coding_e capture_mode = swo_nrz_uart; +#elif SWO_ENCODING == 3 + swo_coding_e capture_mode = swo_none; +#endif + /* Set up the presumed baudrate for the stream */ + uint32_t baudrate = SWO_DEFAULT_BAUD; /* * Before we can enable SWO data recovery, potentially with decoding, * start with the assumption ITM decoding is off */ uint32_t itm_stream_mask = 0U; uint8_t decode_arg = 1U; -#if SWO_ENCODING == 2 - uint32_t baudrate = SWO_DEFAULT_BAUD; +#if SWO_ENCODING == 3 + /* Next, determine which decoding mode to use */ + if (argc > decode_arg) { + const size_t arg_length = strlen(argv[decode_arg]); + if (!strncmp(argv[decode_arg], "manchester", arg_length)) + capture_mode = swo_manchester; + if (!strncmp(argv[decode_arg], "uart", arg_length)) + capture_mode = swo_nrz_uart; + } + /* If a mode was given, make sure the rest of the parser skips the mode verb */ + if (capture_mode != swo_none) + ++decode_arg; + /* Otherwise set a default mode up */ + else + capture_mode = swo_nrz_uart; +#endif +#if SWO_ENCODING == 2 || SWO_ENCODING == 3 /* Handle the optional baud rate argument if present */ - if (argc > 1 && argv[1][0] >= '0' && argv[1][0] <= '9') { - baudrate = strtoul(argv[1], NULL, 0); + if (capture_mode == swo_nrz_uart && argc > decode_arg && argv[decode_arg][0] >= '0' && argv[decode_arg][0] <= '9') { + baudrate = strtoul(argv[decode_arg], NULL, 0); if (baudrate == 0U) baudrate = SWO_DEFAULT_BAUD; - decode_arg = 2U; + ++decode_arg; } #endif /* Check if `decode` has been given and if it has, enable ITM decoding */ @@ -640,13 +665,8 @@ static bool cmd_swo_enable(int argc, const char **argv) } /* Now enable SWO data recovery */ -#if SWO_ENCODING == 2 - swo_uart_init(baudrate, itm_stream_mask); - gdb_outf("Baudrate: %lu ", swo_uart_get_baudrate()); -#else - swo_manchester_init(itm_stream_mask); -#endif - /* Now show the user what we've done - first the channel mask from MSb to LSb */ + swo_init(capture_mode, baudrate, itm_stream_mask); + /* And show the user what we've done - first the channel mask from MSb to LSb */ gdb_outf("Channel mask: "); for (size_t i = 0; i < 32U; ++i) { const char bit = '0' + ((itm_stream_mask >> (31U - i)) & 1U); @@ -724,8 +744,8 @@ static bool cmd_heapinfo(target_s *t, int argc, const char **argv) target_addr_t heap_limit = strtoul(argv[2], NULL, 16); target_addr_t stack_base = strtoul(argv[3], NULL, 16); target_addr_t stack_limit = strtoul(argv[4], NULL, 16); - gdb_outf("heap_base: %08" PRIx32 " heap_limit: %08" PRIx32 " stack_base: %08" PRIx32 " stack_limit: %08" PRIx32 - "\n", + gdb_outf("heap_base: %08" PRIx32 " heap_limit: %08" PRIx32 " stack_base: %08" PRIx32 " stack_limit: " + "%08" PRIx32 "\n", heap_base, heap_limit, stack_base, stack_limit); target_set_heapinfo(t, heap_base, heap_limit, stack_base, stack_limit); } else diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c index 6019bfb12e5..640ef3c5660 100644 --- a/src/platforms/common/stm32/swo.c +++ b/src/platforms/common/stm32/swo.c @@ -18,6 +18,8 @@ * along with this program. If not, see . */ +#include "general.h" +#include "gdb_packet.h" #include "swo.h" #include "swo_internal.h" @@ -34,29 +36,53 @@ * under this circumstance as it requires SWO_ENCODING to be defined and valid. */ -swo_coding_e swo_current_coding; +swo_coding_e swo_current_mode; + +void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32_t itm_stream_bitmask) +{ +#if SWO_ENCODING == 1 + (void)baudrate; +#endif + /* Make sure any existing SWO capture is first spun down */ + if (swo_current_mode != swo_none) + swo_deinit(); + + /* Now determine which mode to enable and initialise it */ +#if SWO_ENCODING == 1 || SWO_ENCODING == 3 + if (swo_mode == swo_manchester) + swo_manchester_init(itm_stream_bitmask); +#endif +#if SWO_ENCODING == 2 || SWO_ENCODING == 3 + if (swo_mode == swo_nrz_uart) { + swo_uart_init(baudrate, itm_stream_bitmask); + gdb_outf("Baudrate: %" PRIu32 " ", swo_uart_get_baudrate()); + } +#endif + /* Make a note of which mode we initialised into */ + swo_current_mode = swo_mode; +} void swo_deinit(void) { #if SWO_ENCODING == 1 || SWO_ENCODING == 3 - if (swo_current_coding == swo_manchester) + if (swo_current_mode == swo_manchester) swo_manchester_deinit(); #endif #if SWO_ENCODING == 2 || SWO_ENCODING == 3 - if (swo_current_coding == swo_nrz_uart) + if (swo_current_mode == swo_nrz_uart) swo_uart_deinit(); #endif - swo_current_coding = swo_none; + swo_current_mode = swo_none; } void swo_send_buffer(usbd_device *const dev, const uint8_t ep) { #if SWO_ENCODING == 1 || SWO_ENCODING == 3 - if (swo_current_coding == swo_manchester) + if (swo_current_mode == swo_manchester) swo_manchester_send_buffer(dev, ep); #endif #if SWO_ENCODING == 2 || SWO_ENCODING == 3 - if (swo_current_coding == swo_nrz_uart) + if (swo_current_mode == swo_nrz_uart) swo_uart_send_buffer(dev, ep); #endif } diff --git a/src/platforms/common/stm32/swo_internal.h b/src/platforms/common/stm32/swo_internal.h index e5053cf1124..68b22423cdd 100644 --- a/src/platforms/common/stm32/swo_internal.h +++ b/src/platforms/common/stm32/swo_internal.h @@ -22,10 +22,12 @@ #define PLATFORMS_COMMON_STM32_SWO_INTERNAL_H /* Manchester-mode implementation functions */ +void swo_manchester_init(uint32_t itm_stream_bitmask); void swo_manchester_deinit(void); void swo_manchester_send_buffer(usbd_device *dev, uint8_t ep); /* UART-mode implementation functions */ +void swo_uart_init(uint32_t baudrate, uint32_t itm_stream_bitmask); void swo_uart_deinit(void); void swo_uart_send_buffer(usbd_device *dev, uint8_t ep); diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index e618767d2d6..536a76e6172 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -34,11 +34,10 @@ typedef enum swo_coding { swo_nrz_uart, } swo_coding_e; -extern swo_coding_e swo_current_coding; +extern swo_coding_e swo_current_mode; /* Initialisation and deinitialisation functions (ties into command.c) */ -void swo_manchester_init(uint32_t itm_stream_bitmask); -void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask); +void swo_init(swo_coding_e swo_mode, uint32_t baudrate, uint32_t itm_stream_bitmask); void swo_deinit(void); /* UART mode baudate functions */ From ec41ce9ee980b0923138bc980f0ac686055a240e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 12 Sep 2024 01:24:33 +0100 Subject: [PATCH 26/48] native: Enabled both SWO decoders and the switchable SWO support --- src/platforms/native/meson.build | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/platforms/native/meson.build b/src/platforms/native/meson.build index 0dceaaa673d..0c38d544c4c 100644 --- a/src/platforms/native/meson.build +++ b/src/platforms/native/meson.build @@ -40,12 +40,13 @@ probe_native_args = [ ] trace_protocol = get_option('trace_protocol') +probe_native_args += [f'-DSWO_ENCODING=@trace_protocol@'] +probe_native_dependencies = [] if trace_protocol in ['1', '3'] - probe_native_args += ['-DSWO_ENCODING=1'] - probe_native_dependencies = platform_stm32_swo_manchester -else - probe_native_args += ['-DSWO_ENCODING=2'] - probe_native_dependencies = platform_stm32_swo_uart + probe_native_dependencies += platform_stm32_swo_manchester +endif +if trace_protocol in ['2', '3'] + probe_native_dependencies += platform_stm32_swo_uart endif probe_native_common_link_args = [ From 6c98aefe0effd2c6755e84956e5f03c49fdd2401 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 13 Sep 2024 02:32:20 +0100 Subject: [PATCH 27/48] common/swo: Started refactoring all the buffer and ITM decode logic out to reduce duplication --- src/platforms/common/stm32/swo.c | 19 ++++++- src/platforms/common/stm32/swo_internal.h | 14 ++++- src/platforms/common/stm32/swo_manchester.c | 49 ++++++++-------- src/platforms/common/stm32/swo_uart.c | 18 ++---- src/platforms/common/stm32/swo_uart_f723.c | 62 ++++++++++----------- 5 files changed, 86 insertions(+), 76 deletions(-) diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c index 640ef3c5660..81a9cdc9952 100644 --- a/src/platforms/common/stm32/swo.c +++ b/src/platforms/common/stm32/swo.c @@ -36,8 +36,17 @@ * under this circumstance as it requires SWO_ENCODING to be defined and valid. */ +/* Current SWO decoding mode being used */ swo_coding_e swo_current_mode; +/* Whether ITM decoding is engaged */ +bool swo_itm_decoding = false; + +/* Buffers, active buffer index and fill level for USB */ +uint8_t swo_transmit_buffers[2][SWO_ENDPOINT_SIZE]; +uint8_t swo_active_transmit_buffer = 0; +uint16_t swo_transmit_buffer_index = 0; + void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32_t itm_stream_bitmask) { #if SWO_ENCODING == 1 @@ -47,14 +56,18 @@ void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32 if (swo_current_mode != swo_none) swo_deinit(); - /* Now determine which mode to enable and initialise it */ + /* Configure the ITM decoder and state */ + swo_itm_decode_set_mask(itm_stream_bitmask); + swo_itm_decoding = itm_stream_bitmask != 0; + + /* Now determine which mode to enable and initialise it */ #if SWO_ENCODING == 1 || SWO_ENCODING == 3 if (swo_mode == swo_manchester) - swo_manchester_init(itm_stream_bitmask); + swo_manchester_init(); #endif #if SWO_ENCODING == 2 || SWO_ENCODING == 3 if (swo_mode == swo_nrz_uart) { - swo_uart_init(baudrate, itm_stream_bitmask); + swo_uart_init(baudrate); gdb_outf("Baudrate: %" PRIu32 " ", swo_uart_get_baudrate()); } #endif diff --git a/src/platforms/common/stm32/swo_internal.h b/src/platforms/common/stm32/swo_internal.h index 68b22423cdd..0c80308894a 100644 --- a/src/platforms/common/stm32/swo_internal.h +++ b/src/platforms/common/stm32/swo_internal.h @@ -21,13 +21,23 @@ #ifndef PLATFORMS_COMMON_STM32_SWO_INTERNAL_H #define PLATFORMS_COMMON_STM32_SWO_INTERNAL_H +#include "usb.h" + +/* Control variables shared between decoders */ +extern bool swo_itm_decoding; + +/* Buffers, active buffer index and fill level for USB */ +extern uint8_t swo_transmit_buffers[2][SWO_ENDPOINT_SIZE]; +extern uint8_t swo_active_transmit_buffer; +extern uint16_t swo_transmit_buffer_index; + /* Manchester-mode implementation functions */ -void swo_manchester_init(uint32_t itm_stream_bitmask); +void swo_manchester_init(void); void swo_manchester_deinit(void); void swo_manchester_send_buffer(usbd_device *dev, uint8_t ep); /* UART-mode implementation functions */ -void swo_uart_init(uint32_t baudrate, uint32_t itm_stream_bitmask); +void swo_uart_init(uint32_t baudrate); void swo_uart_deinit(void); void swo_uart_send_buffer(usbd_device *dev, uint8_t ep); diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index d3adb6a1a92..18a89ae5976 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -57,22 +57,13 @@ (TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF | TIM_SR_TIF | TIM_SR_CC1OF | \ TIM_SR_CC2OF | TIM_SR_CC3OF | TIM_SR_CC4OF) -/* SWO decoding */ -static bool decoding = false; - -#define SWO_BUFFER_SIZE 64U - -/* Buffer and fill level for USB */ -static uint8_t swo_transmit_buffer[SWO_BUFFER_SIZE]; -static uint8_t swo_transmit_buffer_index; - /* Manchester bit capture buffer and current bit index */ static uint8_t swo_data[16U]; static uint8_t swo_data_bit_index = 0; /* Number of timer clock cycles that describe half a bit period as detected */ static uint32_t swo_half_bit_period = 0U; -void swo_manchester_init(const uint32_t itm_stream_bitmask) +void swo_manchester_init(void) { /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ SWO_TIM_CLK_EN(); @@ -117,9 +108,7 @@ void swo_manchester_init(const uint32_t itm_stream_bitmask) /* Set the period to an improbable value */ timer_set_period(SWO_TIM, UINT32_MAX); - /* Configure the capture decoder and state, then enable the timer */ - swo_itm_decode_set_mask(itm_stream_bitmask); - decoding = itm_stream_bitmask != 0; + /* Now we've got everything configured and ready, enable the timer */ timer_enable_counter(SWO_TIM); } @@ -144,17 +133,23 @@ void swo_manchester_deinit(void) void swo_buffer_data(void) { const uint8_t byte_count = swo_data_bit_index >> 3U; - if (decoding) + if (swo_itm_decoding) swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, swo_data, byte_count); - else if (usbd_ep_write_packet(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, swo_data, byte_count) != byte_count) { - if (swo_transmit_buffer_index + byte_count > SWO_BUFFER_SIZE) { - /* Stall if upstream to too slow. */ - usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, 1U); - swo_transmit_buffer_index = 0; - return; + else { + /* First, see how much space we have in the current transmit buffer and move what we can */ + const uint16_t amount = MIN(byte_count, SWO_ENDPOINT_SIZE - swo_transmit_buffer_index); + memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data, amount); + swo_transmit_buffer_index += amount; + /* Now, if we just exhausted that buffer, send it */ + if (swo_transmit_buffer_index == SWO_ENDPOINT_SIZE) + swo_send_buffer(usbdev, SWO_ENDPOINT); + /* If we have anything left to move, now put that in the new buffer */ + if (amount != byte_count) { + const uint16_t remainder = byte_count - amount; + memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data + amount, + remainder); + swo_transmit_buffer_index += remainder; } - memcpy(swo_transmit_buffer + swo_transmit_buffer_index, swo_data, byte_count); - swo_transmit_buffer_index += byte_count; } swo_data_bit_index = 0U; } @@ -164,11 +159,13 @@ void swo_manchester_send_buffer(usbd_device *const dev, const uint8_t ep) if (!swo_transmit_buffer_index) return; - if (decoding) - swo_itm_decode(dev, CDCACM_UART_ENDPOINT, swo_transmit_buffer, swo_transmit_buffer_index); + if (swo_itm_decoding) + swo_itm_decode( + dev, CDCACM_UART_ENDPOINT, swo_transmit_buffers[swo_active_transmit_buffer], swo_transmit_buffer_index); else - usbd_ep_write_packet(dev, ep, swo_transmit_buffer, swo_transmit_buffer_index); - swo_transmit_buffer_index = 0; + usbd_ep_write_packet(dev, ep, swo_transmit_buffers[swo_active_transmit_buffer], swo_transmit_buffer_index); + swo_active_transmit_buffer ^= 1U; + swo_transmit_buffer_index = 0U; } void SWO_TIM_ISR(void) diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 487a81341e5..17a9fcf4443 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -63,14 +63,10 @@ static volatile uint32_t write_index; /* Packet currently received via UART */ static volatile uint32_t read_index; /* Packet currently waiting to transmit to USB */ /* Packets arrived from the SWO interface */ static uint8_t *trace_rx_buf = NULL; -/* Packet pingpong buffer used for receiving packets */ -static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; -/* SWO decoding */ -static bool decoding = false; static void swo_uart_set_baud(uint32_t baudrate); -void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) +void swo_uart_init(uint32_t baudrate) { /* Skip initial allocation on commands for mode change */ if (trace_rx_buf == NULL) { @@ -102,8 +98,6 @@ void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); nvic_enable_irq(SWO_DMA_IRQ); swo_uart_set_baud(baudrate); - swo_itm_decode_set_mask(swo_chan_bitmask); - decoding = (swo_chan_bitmask != 0); } void swo_uart_deinit(void) @@ -131,7 +125,7 @@ void swo_uart_send_buffer(usbd_device *const dev, const uint8_t ep) /* Attempt to write everything we buffered */ if (write_index != read_index) { uint16_t result; - if (decoding) + if (swo_itm_decoding) /* write decoded swo packets to the uart port */ result = swo_itm_decode( dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); @@ -162,7 +156,7 @@ static void swo_uart_set_baud(const uint32_t baudrate) /* Set up DMA channel */ dma_channel_reset(SWO_DMA_BUS, SWO_DMA_CHAN); - dma_set_peripheral_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uint32_t)&SWO_UART_DR); + dma_set_peripheral_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&SWO_UART_DR); #if defined(DMA_STREAM0) dma_set_transfer_mode(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_channel_select(SWO_DMA_BUS, SWO_DMA_CHAN, SWO_DMA_TRG); @@ -182,7 +176,7 @@ static void swo_uart_set_baud(const uint32_t baudrate) usart_enable(SWO_UART); nvic_enable_irq(SWO_DMA_IRQ); write_index = read_index = 0; - dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uint32_t)pingpong_buf); + dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&swo_transmit_buffers[0][0]); dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, 2 * SWO_ENDPOINT_SIZE); dma_enable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_enable_rx_dma(SWO_UART); @@ -192,11 +186,11 @@ void SWO_DMA_ISR(void) { if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF); - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], pingpong_buf, SWO_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[0U], SWO_ENDPOINT_SIZE); } if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF); - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], &pingpong_buf[SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); + memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[1U], SWO_ENDPOINT_SIZE); } write_index = (write_index + 1U) % NUM_SWO_PACKETS; swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c index 6989b743535..3b098c3ca2b 100644 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ b/src/platforms/common/stm32/swo_uart_f723.c @@ -49,8 +49,34 @@ static volatile uint32_t read_index; /* Packet currently waiting to transmit to static uint8_t trace_rx_buf[NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE]; /* Packet pingpong buffer used for receiving packets */ static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; -/* SWO decoding */ -static bool decoding = false; + +void swo_uart_init(uint32_t baudrate) +{ + if (!baudrate) + baudrate = SWO_DEFAULT_BAUD; + + rcc_periph_clock_enable(SWO_UART_CLK); + rcc_periph_clock_enable(SWO_DMA_CLK); + + rcc_periph_clock_enable(RCC_GPIOD); + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SWO_UART_RX_PIN); + gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); + /* Pull SWO pin high to keep open SWO line ind uart idle state!*/ + gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); + nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); + nvic_enable_irq(SWO_DMA_IRQ); + swo_uart_set_baud(baudrate); +} + +void swo_uart_deinit(void) +{ + /* Stop peripherals servicing */ + nvic_disable_irq(SWO_DMA_IRQ); + dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); + usart_disable(SWO_UART); + /* Dump the buffered remains */ + swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); +} void swo_uart_send_buffer(usbd_device *dev, uint8_t ep) { @@ -62,7 +88,7 @@ void swo_uart_send_buffer(usbd_device *dev, uint8_t ep) /* Attempt to write everything we buffered */ if (write_index != read_index) { uint16_t result; - if (decoding) + if (swo_itm_decoding) /* write decoded swo packets to the uart port */ result = swo_itm_decode( dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); @@ -126,33 +152,3 @@ void SWO_DMA_ISR(void) write_index = (write_index + 1) % NUM_SWO_PACKETS; swo_send_buffer(usbdev, SWO_ENDPOINT); } - -void swo_uart_init(uint32_t baudrate, uint32_t swo_chan_bitmask) -{ - if (!baudrate) - baudrate = SWO_DEFAULT_BAUD; - - rcc_periph_clock_enable(SWO_UART_CLK); - rcc_periph_clock_enable(SWO_DMA_CLK); - - rcc_periph_clock_enable(RCC_GPIOD); - gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SWO_UART_RX_PIN); - gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); - /* Pull SWO pin high to keep open SWO line ind uart idle state!*/ - gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); - nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); - nvic_enable_irq(SWO_DMA_IRQ); - swo_uart_set_baud(baudrate); - traceswo_setmask(swo_chan_bitmask); - decoding = swo_chan_bitmask != 0; -} - -void swo_uart_deinit(void) -{ - /* Stop peripherals servicing */ - nvic_disable_irq(SWO_DMA_IRQ); - dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); - usart_disable(SWO_UART); - /* Dump the buffered remains */ - swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); -} From d495779875fab93b5b8c0b62f4b2aa57024d9d12 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 13 Sep 2024 02:33:56 +0100 Subject: [PATCH 28/48] command: Provide for the multi-mode version of the SWO monitor command --- src/command.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/command.c b/src/command.c index 093c8d1e7a9..90c5904bac1 100644 --- a/src/command.c +++ b/src/command.c @@ -109,10 +109,12 @@ const command_s cmd_list[] = { "MAXERR]]"}, #endif #ifdef PLATFORM_HAS_TRACESWO -#if defined SWO_ENCODING && SWO_ENCODING == 2 - {"swo", cmd_swo, "Start SWO capture, UART mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, -#else +#if SWO_ENCODING == 1 {"swo", cmd_swo, "Start SWO capture, Manchester mode: [decode [CHANNEL_NR ...]]"}, +#elif SWO_ENCODING == 2 + {"swo", cmd_swo, "Start SWO capture, UART mode: [BAUDRATE] [decode [CHANNEL_NR ...]]"}, +#elif SWO_ENCODING == 3 + {"swo", cmd_swo, "Start SWO capture: [manchester|uart] [BAUDRATE] [decode [CHANNEL_NR ...]]"}, #endif {"traceswo", cmd_swo, "Deprecated: use swo instead"}, #endif From 95aa24dbd118477af284eac6faa712ac66a85745 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Sep 2024 12:17:35 +0100 Subject: [PATCH 29/48] swo_manchester: Reworked some of the buffering logic to pull decoding logic out from where it shouldn't be, and fix the deinit behaviour --- src/platforms/common/stm32/swo_manchester.c | 25 ++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 18a89ae5976..4ebbdf9ef3f 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -118,6 +118,9 @@ void swo_manchester_deinit(void) timer_disable_counter(SWO_TIM); timer_slave_set_mode(SWO_TIM, TIM_SMCR_SMS_OFF); + /* Flush any pending data */ + swo_send_buffer(usbdev, SWO_ENDPOINT); + /* Reset state so that when init is called we wind up in a fresh capture state */ swo_data_bit_index = 0U; swo_half_bit_period = 0U; @@ -133,22 +136,18 @@ void swo_manchester_deinit(void) void swo_buffer_data(void) { const uint8_t byte_count = swo_data_bit_index >> 3U; - if (swo_itm_decoding) - swo_itm_decode(usbdev, CDCACM_UART_ENDPOINT, swo_data, byte_count); - else { - /* First, see how much space we have in the current transmit buffer and move what we can */ - const uint16_t amount = MIN(byte_count, SWO_ENDPOINT_SIZE - swo_transmit_buffer_index); - memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data, amount); - swo_transmit_buffer_index += amount; - /* Now, if we just exhausted that buffer, send it */ - if (swo_transmit_buffer_index == SWO_ENDPOINT_SIZE) - swo_send_buffer(usbdev, SWO_ENDPOINT); + /* First, see how much space we have in the current transmit buffer and move what we can */ + const uint16_t amount = MIN(byte_count, SWO_ENDPOINT_SIZE - swo_transmit_buffer_index); + memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data, amount); + swo_transmit_buffer_index += amount; + /* Now, if we just exhausted that buffer, send it */ + if (swo_transmit_buffer_index == SWO_ENDPOINT_SIZE) { + swo_send_buffer(usbdev, SWO_ENDPOINT); /* If we have anything left to move, now put that in the new buffer */ if (amount != byte_count) { const uint16_t remainder = byte_count - amount; - memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data + amount, - remainder); - swo_transmit_buffer_index += remainder; + memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][0U], swo_data + amount, remainder); + swo_transmit_buffer_index = remainder; } } swo_data_bit_index = 0U; From ced2e4c7ec8a7d7a03a8d23dffbbb36ca840d4e2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Sep 2024 13:46:47 +0100 Subject: [PATCH 30/48] common/stm32/swo: De-duplicated the UART-encoded SWO implementations so there's less to be dragged around --- src/platforms/common/stm32/meson.build | 1 - src/platforms/common/stm32/swo_uart.c | 6 +- src/platforms/common/stm32/swo_uart_f723.c | 154 --------------------- src/platforms/native/platform.c | 2 +- src/platforms/stlinkv3/meson.build | 2 +- src/platforms/stlinkv3/platform.c | 5 +- src/platforms/stlinkv3/platform.h | 4 +- 7 files changed, 10 insertions(+), 164 deletions(-) delete mode 100644 src/platforms/common/stm32/swo_uart_f723.c diff --git a/src/platforms/common/stm32/meson.build b/src/platforms/common/stm32/meson.build index 85d9f58d1be..ebf4bfbb97e 100644 --- a/src/platforms/common/stm32/meson.build +++ b/src/platforms/common/stm32/meson.build @@ -42,7 +42,6 @@ platform_stm32_sources = files( # This is a temporary hack to allow selecting swo_manchester vs swo_uart implementation platform_stm32_swo_manchester = declare_dependency(sources: files('swo_manchester.c')) platform_stm32_swo_uart = declare_dependency(sources: files('swo_uart.c')) -platform_stm32f7_swo_uart = declare_dependency(sources: files('swo_uart_f723.c')) # RTT support handling if get_option('rtt_support') diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 17a9fcf4443..6e3885dc56b 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -107,7 +107,7 @@ void swo_uart_deinit(void) dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_disable(SWO_UART); /* Dump the buffered remains */ - swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, SWO_ENDPOINT); /* Return this contiguous chunk of SRAM to unshrinkable heap */ if (trace_rx_buf != NULL) { free(trace_rx_buf); @@ -148,7 +148,7 @@ static void swo_uart_set_baud(const uint32_t baudrate) dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); usart_disable(SWO_UART); bmd_usart_set_baudrate(SWO_UART, baudrate); - usart_set_databits(SWO_UART, 8); + usart_set_databits(SWO_UART, 8U); usart_set_stopbits(SWO_UART, USART_STOPBITS_1); usart_set_mode(SWO_UART, USART_MODE_RX); usart_set_parity(SWO_UART, USART_PARITY_NONE); @@ -193,5 +193,5 @@ void SWO_DMA_ISR(void) memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[1U], SWO_ENDPOINT_SIZE); } write_index = (write_index + 1U) % NUM_SWO_PACKETS; - swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); + swo_send_buffer(usbdev, SWO_ENDPOINT); } diff --git a/src/platforms/common/stm32/swo_uart_f723.c b/src/platforms/common/stm32/swo_uart_f723.c deleted file mode 100644 index 3b098c3ca2b..00000000000 --- a/src/platforms/common/stm32/swo_uart_f723.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Based on work that is Copyright (C) 2017 Black Sphere Technologies Ltd. - * Copyright (C) 2017 Dave Marples - * Portions (C) 2020-2021 Stoyan Shopov - * - * 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 . - */ - -/* This file implements capture of the TRACESWO output using ASYNC signalling. - * - * ARM DDI 0403D - ARMv7M Architecture Reference Manual - * ARM DDI 0337I - Cortex-M3 Technical Reference Manual - * ARM DDI 0314H - CoreSight Components Technical Reference Manual - */ - -/* TDO/TRACESWO signal comes into the SWOUSART RX pin. - */ - -#include -#include "general.h" -#include "platform.h" -#include "usb.h" -#include "swo.h" -#include "swo_internal.h" - -#include -#include -#include -#include -#include -#include - -static volatile uint32_t write_index; /* Packet currently received via UART */ -static volatile uint32_t read_index; /* Packet currently waiting to transmit to USB */ -/* Packets arrived from the SWO interface */ -static uint8_t trace_rx_buf[NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE]; -/* Packet pingpong buffer used for receiving packets */ -static uint8_t pingpong_buf[2 * SWO_ENDPOINT_SIZE]; - -void swo_uart_init(uint32_t baudrate) -{ - if (!baudrate) - baudrate = SWO_DEFAULT_BAUD; - - rcc_periph_clock_enable(SWO_UART_CLK); - rcc_periph_clock_enable(SWO_DMA_CLK); - - rcc_periph_clock_enable(RCC_GPIOD); - gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SWO_UART_RX_PIN); - gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); - /* Pull SWO pin high to keep open SWO line ind uart idle state!*/ - gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); - nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); - nvic_enable_irq(SWO_DMA_IRQ); - swo_uart_set_baud(baudrate); -} - -void swo_uart_deinit(void) -{ - /* Stop peripherals servicing */ - nvic_disable_irq(SWO_DMA_IRQ); - dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); - usart_disable(SWO_UART); - /* Dump the buffered remains */ - swo_send_buffer(usbdev, SWO_ENDPOINT | USB_REQ_TYPE_IN); -} - -void swo_uart_send_buffer(usbd_device *dev, uint8_t ep) -{ - static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; - - /* If we are already in this routine then we don't need to come in again */ - if (atomic_flag_test_and_set_explicit(&reentry_flag, memory_order_relaxed)) - return; - /* Attempt to write everything we buffered */ - if (write_index != read_index) { - uint16_t result; - if (swo_itm_decoding) - /* write decoded swo packets to the uart port */ - result = swo_itm_decode( - dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); - else - /* write raw swo packets to the trace port */ - result = usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); - if (result) - read_index = (read_index + 1U) % NUM_SWO_PACKETS; - } - atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); -} - -uint32_t swo_uart_get_baudrate(void) -{ - return usart_get_baudrate(SWO_UART); -} - -void swo_uart_set_baud(uint32_t baudrate) -{ - dma_disable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); - usart_disable(SWO_UART); - bmd_usart_set_baudrate(SWO_UART, baudrate); - usart_set_databits(SWO_UART, 8); - usart_set_stopbits(SWO_UART, USART_STOPBITS_1); - usart_set_mode(SWO_UART, USART_MODE_RX); - usart_set_parity(SWO_UART, USART_PARITY_NONE); - usart_set_flow_control(SWO_UART, USART_FLOWCONTROL_NONE); - - /* Set up DMA channel*/ - dma_stream_reset(SWO_DMA_BUS, SWO_DMA_STREAM); - dma_set_peripheral_address(SWO_DMA_BUS, SWO_DMA_STREAM, (uint32_t)&SWO_UART_DR); - dma_set_transfer_mode(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); - dma_enable_memory_increment_mode(SWO_DMA_BUS, SWO_DMA_STREAM); - dma_set_peripheral_size(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_PSIZE_8BIT); - dma_set_memory_size(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_MSIZE_8BIT); - dma_set_priority(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_PL_VERY_HIGH); - dma_enable_transfer_complete_interrupt(SWO_DMA_BUS, SWO_DMA_STREAM); - dma_enable_half_transfer_interrupt(SWO_DMA_BUS, SWO_DMA_STREAM); - dma_enable_circular_mode(SWO_DMA_BUS, SWO_DMA_STREAM); - - usart_enable(SWO_UART); - nvic_enable_irq(SWO_DMA_IRQ); - write_index = read_index = 0; - dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_STREAM, (uint32_t)pingpong_buf); - dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_STREAM, 2 * SWO_ENDPOINT_SIZE); - dma_channel_select(SWO_DMA_BUS, SWO_DMA_STREAM, DMA_SxCR_CHSEL_4); - dma_enable_stream(SWO_DMA_BUS, SWO_DMA_STREAM); - usart_enable_rx_dma(SWO_UART); -} - -void SWO_DMA_ISR(void) -{ - if (DMA_LISR(SWO_DMA_BUS) & DMA_LISR_HTIF0) { - DMA_LIFCR(SWO_DMA_BUS) |= DMA_LISR_HTIF0; - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], pingpong_buf, SWO_ENDPOINT_SIZE); - } - if (DMA_LISR(SWO_DMA_BUS) & DMA_LISR_TCIF0) { - DMA_LIFCR(SWO_DMA_BUS) |= DMA_LISR_TCIF0; - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], &pingpong_buf[SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); - } - write_index = (write_index + 1) % NUM_SWO_PACKETS; - swo_send_buffer(usbdev, SWO_ENDPOINT); -} diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index e90d05c4be7..e889527e872 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -265,7 +265,7 @@ void platform_init(void) gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); } /* Set up the NVIC vector table for the firmware */ - SCB_VTOR = (uint32_t)&vector_table; // NOLINT(clang-diagnostic-pointer-to-int-cast) + SCB_VTOR = (uintptr_t)&vector_table; // NOLINT(clang-diagnostic-pointer-to-int-cast, performance-no-int-to-ptr) platform_timing_init(); blackmagic_usb_init(); diff --git a/src/platforms/stlinkv3/meson.build b/src/platforms/stlinkv3/meson.build index d9039389d7c..7962cabe20e 100644 --- a/src/platforms/stlinkv3/meson.build +++ b/src/platforms/stlinkv3/meson.build @@ -63,7 +63,7 @@ if trace_protocol == '3' trace_protocol = '2' endif if trace_protocol == '2' - probe_stlinkv3_dependencies = platform_stm32f7_swo_uart + probe_stlinkv3_dependencies = platform_stm32_swo_uart probe_stlinkv3_args += ['-DSWO_ENCODING=2'] else error('Unsupported SWO protocol requested') diff --git a/src/platforms/stlinkv3/platform.c b/src/platforms/stlinkv3/platform.c index fd67914822f..6e603b1c953 100644 --- a/src/platforms/stlinkv3/platform.c +++ b/src/platforms/stlinkv3/platform.c @@ -244,12 +244,13 @@ void platform_init(void) regval |= (usart6_clksel & RCC_DCKCFGR2_UARTxSEL_MASK) << RCC_DCKCFGR2_USART6SEL_SHIFT; RCC_DCKCFGR2 = regval; - /* Relocate interrupt vector table here */ - SCB_VTOR = (uintptr_t)&vector_table; + /* Set up the NVIC vector table for the firmware */ + SCB_VTOR = (uintptr_t)&vector_table; // NOLINT(clang-diagnostic-pointer-to-int-cast, performance-no-int-to-ptr) platform_timing_init(); blackmagic_usb_init(); aux_serial_init(); + /* By default, do not drive the swd bus too fast. */ platform_max_frequency_set(6000000); } diff --git a/src/platforms/stlinkv3/platform.h b/src/platforms/stlinkv3/platform.h index eee2eb7d75e..98cb2deb974 100644 --- a/src/platforms/stlinkv3/platform.h +++ b/src/platforms/stlinkv3/platform.h @@ -185,8 +185,8 @@ extern const struct _usbd_driver stm32f723_usb_driver; /* This DMA channel is set by the USART in use */ #define SWO_DMA_BUS DMA1 #define SWO_DMA_CLK RCC_DMA1 -#define SWO_DMA_CHAN DMA_CHANNEL4 -#define SWO_DMA_STREAM DMA_STREAM0 +#define SWO_DMA_CHAN DMA_STREAM0 +#define SWO_DMA_TRG DMA_SxCR_CHSEL_4 #define SWO_DMA_IRQ NVIC_DMA1_STREAM0_IRQ #define SWO_DMA_ISR(x) dma1_stream0_isr(x) From c497b6ee16616cc066b42f56963aaf5a797ce2a9 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Sep 2024 16:05:35 +0100 Subject: [PATCH 31/48] common/stm32/swo: Fixed a couple of comments that were misworded --- src/platforms/common/stm32/swo_internal.h | 2 +- src/platforms/common/stm32/swo_manchester.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/common/stm32/swo_internal.h b/src/platforms/common/stm32/swo_internal.h index 0c80308894a..c32ef0ebf99 100644 --- a/src/platforms/common/stm32/swo_internal.h +++ b/src/platforms/common/stm32/swo_internal.h @@ -26,7 +26,7 @@ /* Control variables shared between decoders */ extern bool swo_itm_decoding; -/* Buffers, active buffer index and fill level for USB */ +/* Data buffers, active buffer index and fill level for USB */ extern uint8_t swo_transmit_buffers[2][SWO_ENDPOINT_SIZE]; extern uint8_t swo_active_transmit_buffer; extern uint16_t swo_transmit_buffer_index; diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 4ebbdf9ef3f..6282a4854ed 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -128,7 +128,7 @@ void swo_manchester_deinit(void) #if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); #else - /* Put the GPIO back into normal service as TDO */ + /* Put the GPIO back into normal service as a GPIO */ gpio_set_mode(SWO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_PIN); #endif } From bff3c161c4a02c55a8e611eb3509d1725886e2f2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Sep 2024 16:06:48 +0100 Subject: [PATCH 32/48] common/stm32/swo_uart: Nomenclature corrections for the USB bounce buffer --- src/platforms/common/stm32/swo_uart.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 6e3885dc56b..cc30e6f716b 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -62,21 +62,21 @@ static volatile uint32_t write_index; /* Packet currently received via UART */ static volatile uint32_t read_index; /* Packet currently waiting to transmit to USB */ /* Packets arrived from the SWO interface */ -static uint8_t *trace_rx_buf = NULL; +static uint8_t *swo_data_buffer = NULL; static void swo_uart_set_baud(uint32_t baudrate); void swo_uart_init(uint32_t baudrate) { /* Skip initial allocation on commands for mode change */ - if (trace_rx_buf == NULL) { + if (swo_data_buffer == NULL) { /* Alignment (bytes): 1 for UART DMA, 2-4 for memcpy in usb code, 8 provided by malloc. Not 64 */ - uint8_t *const newbuf = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); - if (!newbuf) { + uint8_t *const swo_data_buffer = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); + /* Check for allocation failure and abort initialisation if we see it failed */ + if (!swo_data_buffer) { DEBUG_ERROR("malloc: failed in %s\n", __func__); return; } - trace_rx_buf = newbuf; } if (!baudrate) @@ -109,9 +109,9 @@ void swo_uart_deinit(void) /* Dump the buffered remains */ swo_send_buffer(usbdev, SWO_ENDPOINT); /* Return this contiguous chunk of SRAM to unshrinkable heap */ - if (trace_rx_buf != NULL) { - free(trace_rx_buf); - trace_rx_buf = NULL; + if (swo_data_buffer != NULL) { + free(swo_data_buffer); + swo_data_buffer = NULL; } } @@ -128,10 +128,10 @@ void swo_uart_send_buffer(usbd_device *const dev, const uint8_t ep) if (swo_itm_decoding) /* write decoded swo packets to the uart port */ result = swo_itm_decode( - dev, CDCACM_UART_ENDPOINT, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); + dev, CDCACM_UART_ENDPOINT, &swo_data_buffer[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); else /* write raw swo packets to the trace port */ - result = usbd_ep_write_packet(dev, ep, &trace_rx_buf[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); + result = usbd_ep_write_packet(dev, ep, &swo_data_buffer[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); if (result) read_index = (read_index + 1U) % NUM_SWO_PACKETS; } @@ -186,11 +186,11 @@ void SWO_DMA_ISR(void) { if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF); - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[0U], SWO_ENDPOINT_SIZE); + memcpy(&swo_data_buffer[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[0U], SWO_ENDPOINT_SIZE); } if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF); - memcpy(&trace_rx_buf[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[1U], SWO_ENDPOINT_SIZE); + memcpy(&swo_data_buffer[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[1U], SWO_ENDPOINT_SIZE); } write_index = (write_index + 1U) % NUM_SWO_PACKETS; swo_send_buffer(usbdev, SWO_ENDPOINT); From 42ba11f0029952a9ed46fd517d17c221f8aa3856 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Sep 2024 16:09:49 +0100 Subject: [PATCH 33/48] common/stm32/swo_uart: Fixed an issue with deinitialisation leaving the pin configured, which is wrong for platforms that share their SWO pin with TDO --- src/platforms/common/stm32/swo_uart.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index cc30e6f716b..6368bdaa2fc 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -113,6 +113,13 @@ void swo_uart_deinit(void) free(swo_data_buffer); swo_data_buffer = NULL; } + + /* Put the GPIO back into normal service as a GPIO */ +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); +#else + gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_UART_RX_PIN); +#endif } void swo_uart_send_buffer(usbd_device *const dev, const uint8_t ep) @@ -156,6 +163,7 @@ static void swo_uart_set_baud(const uint32_t baudrate) /* Set up DMA channel */ dma_channel_reset(SWO_DMA_BUS, SWO_DMA_CHAN); + // NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast,performance-no-int-to-ptr) dma_set_peripheral_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&SWO_UART_DR); #if defined(DMA_STREAM0) dma_set_transfer_mode(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); @@ -176,6 +184,7 @@ static void swo_uart_set_baud(const uint32_t baudrate) usart_enable(SWO_UART); nvic_enable_irq(SWO_DMA_IRQ); write_index = read_index = 0; + // NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast) dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&swo_transmit_buffers[0][0]); dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, 2 * SWO_ENDPOINT_SIZE); dma_enable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); From e65b7622edc74709c169f175280251d892152e0b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 16 Sep 2024 16:33:24 +0100 Subject: [PATCH 34/48] common/stm32/swo: Rebuilt the buffering system using one single unified buffer to handle the data with DMA direct to that surge buffer, and no intermediary buffers --- src/command.c | 2 +- src/platforms/common/stm32/swo.c | 96 +++++++++++-- src/platforms/common/stm32/swo_internal.h | 17 ++- src/platforms/common/stm32/swo_manchester.c | 38 ++---- src/platforms/common/stm32/swo_uart.c | 143 +++++++------------- src/platforms/common/swo.h | 2 +- src/platforms/common/usb.h | 10 +- 7 files changed, 164 insertions(+), 144 deletions(-) diff --git a/src/command.c b/src/command.c index 90c5904bac1..4d731f53997 100644 --- a/src/command.c +++ b/src/command.c @@ -682,7 +682,7 @@ static bool cmd_swo_enable(int argc, const char **argv) static bool cmd_swo_disable(void) { - swo_deinit(); + swo_deinit(true); gdb_out("Trace disabled\n"); return true; } diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c index 81a9cdc9952..1c3e0b7c8ea 100644 --- a/src/platforms/common/stm32/swo.c +++ b/src/platforms/common/stm32/swo.c @@ -23,6 +23,10 @@ #include "swo.h" #include "swo_internal.h" +#include +#include +#include + /* * Management and muxing layer for the SWO implementations * @@ -42,10 +46,18 @@ swo_coding_e swo_current_mode; /* Whether ITM decoding is engaged */ bool swo_itm_decoding = false; -/* Buffers, active buffer index and fill level for USB */ -uint8_t swo_transmit_buffers[2][SWO_ENDPOINT_SIZE]; -uint8_t swo_active_transmit_buffer = 0; -uint16_t swo_transmit_buffer_index = 0; +/* + * Dynamically-allocated data buffer, current read index, current write index, + * current fill level, and total available buffer size. We initialise to 0 just + * to get a consistent starting point, but the indexes do not matter once up and + * running. It only matters the post-condition of swo_deinit() that no bytes + * are available and the indicies are equal to each other are kept for entry + * into swo_init() and the successful execution of it all. + */ +uint8_t *swo_buffer; +uint16_t swo_buffer_read_index = 0U; +uint16_t swo_buffer_write_index = 0U; +_Atomic uint16_t swo_buffer_bytes_available = 0U; void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32_t itm_stream_bitmask) { @@ -54,7 +66,21 @@ void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32 #endif /* Make sure any existing SWO capture is first spun down */ if (swo_current_mode != swo_none) - swo_deinit(); + swo_deinit(false); + /* If we're spinning this up fresh, allocate a buffer for the data */ + else { + /* + * This needs to be at least 2 endpoint buffers large, more is better to a point but + * it has diminishing returns. Aim for no more than 8KiB of buffer as after that, larger + * is entirely pointless. + */ + swo_buffer = malloc(SWO_BUFFER_SIZE); + /* Check for allocation failure and abort initialisation if we see it failed */ + if (!swo_buffer) { + DEBUG_ERROR("malloc: failed in %s\n", __func__); + return; + } + } /* Configure the ITM decoder and state */ swo_itm_decode_set_mask(itm_stream_bitmask); @@ -75,7 +101,7 @@ void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32 swo_current_mode = swo_mode; } -void swo_deinit(void) +void swo_deinit(const bool deallocate) { #if SWO_ENCODING == 1 || SWO_ENCODING == 3 if (swo_current_mode == swo_manchester) @@ -85,17 +111,59 @@ void swo_deinit(void) if (swo_current_mode == swo_nrz_uart) swo_uart_deinit(); #endif + + /* Spin waiting for all data to finish being transmitted */ + while (swo_buffer_bytes_available) { + swo_send_buffer(usbdev, SWO_ENDPOINT); + __WFI(); + } + + /* If we're being asked to give the SWO buffer back, then free it */ + if (deallocate) + free(swo_buffer); swo_current_mode = swo_none; } void swo_send_buffer(usbd_device *const dev, const uint8_t ep) { -#if SWO_ENCODING == 1 || SWO_ENCODING == 3 - if (swo_current_mode == swo_manchester) - swo_manchester_send_buffer(dev, ep); -#endif -#if SWO_ENCODING == 2 || SWO_ENCODING == 3 - if (swo_current_mode == swo_nrz_uart) - swo_uart_send_buffer(dev, ep); -#endif + /* NOTLINTNEXTLINE(clang-diagnostic-error) */ + static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; + + /* If we are already in this routine then we don't need to come in again */ + if (atomic_flag_test_and_set_explicit(&reentry_flag, memory_order_relaxed)) + return; + + const uint16_t bytes_available = swo_buffer_bytes_available; + /* + * If there is somthing to move, move the next up-to SWO_ENDPOINT_SIZE bytes chunk of it (USB) + * or the whole lot (ITM decoding) as appropriate + */ + if (bytes_available) { + uint16_t result; + /* If we're doing decoding, hand the data to the ITM decoder */ + if (swo_itm_decoding) { + /* If we're in UART mode, hand as much as we can all at once */ + if (swo_current_mode == swo_nrz_uart) + result = swo_itm_decode(dev, CDCACM_UART_ENDPOINT, swo_buffer + swo_buffer_read_index, + MIN(bytes_available, SWO_BUFFER_SIZE - swo_buffer_read_index)); + /* Otherwise, if we're in Manchester mode, manage the amount moved the same as we do USB */ + else + result = swo_itm_decode(dev, CDCACM_UART_ENDPOINT, swo_buffer + swo_buffer_read_index, + MIN(bytes_available, SWO_ENDPOINT_SIZE)); + } else + /* Otherwise, queue the new data to the SWO data endpoint */ + result = usbd_ep_write_packet( + dev, ep, swo_buffer + swo_buffer_read_index, MIN(bytes_available, SWO_ENDPOINT_SIZE)); + + /* If we actually queued/processed some data, update indicies etc */ + if (result) { + /* + * Update the amount read and consumed */ + swo_buffer_read_index += result; + swo_buffer_read_index &= SWO_BUFFER_SIZE - 1U; + swo_buffer_bytes_available -= result; + } + } + + atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); } diff --git a/src/platforms/common/stm32/swo_internal.h b/src/platforms/common/stm32/swo_internal.h index c32ef0ebf99..dc9fda16239 100644 --- a/src/platforms/common/stm32/swo_internal.h +++ b/src/platforms/common/stm32/swo_internal.h @@ -23,22 +23,27 @@ #include "usb.h" +/* + * Total buffer size for the dynamic buffer + * NB: This *must* result in a value that is a power of two. + */ +#define SWO_BUFFER_SIZE (NUM_SWO_USB_PACKETS * SWO_ENDPOINT_SIZE) + /* Control variables shared between decoders */ extern bool swo_itm_decoding; -/* Data buffers, active buffer index and fill level for USB */ -extern uint8_t swo_transmit_buffers[2][SWO_ENDPOINT_SIZE]; -extern uint8_t swo_active_transmit_buffer; -extern uint16_t swo_transmit_buffer_index; +/* Dynamically-allocated data buffer, current read index, current write index, and current fill level */ +extern uint8_t *swo_buffer; +extern uint16_t swo_buffer_read_index; +extern uint16_t swo_buffer_write_index; +extern _Atomic uint16_t swo_buffer_bytes_available; /* Manchester-mode implementation functions */ void swo_manchester_init(void); void swo_manchester_deinit(void); -void swo_manchester_send_buffer(usbd_device *dev, uint8_t ep); /* UART-mode implementation functions */ void swo_uart_init(uint32_t baudrate); void swo_uart_deinit(void); -void swo_uart_send_buffer(usbd_device *dev, uint8_t ep); #endif /* PLATFORMS_COMMON_STM32_SWO_INTERNAL_H */ diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 6282a4854ed..1bebc820aea 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -118,9 +118,6 @@ void swo_manchester_deinit(void) timer_disable_counter(SWO_TIM); timer_slave_set_mode(SWO_TIM, TIM_SMCR_SMS_OFF); - /* Flush any pending data */ - swo_send_buffer(usbdev, SWO_ENDPOINT); - /* Reset state so that when init is called we wind up in a fresh capture state */ swo_data_bit_index = 0U; swo_half_bit_period = 0U; @@ -136,37 +133,26 @@ void swo_manchester_deinit(void) void swo_buffer_data(void) { const uint8_t byte_count = swo_data_bit_index >> 3U; - /* First, see how much space we have in the current transmit buffer and move what we can */ - const uint16_t amount = MIN(byte_count, SWO_ENDPOINT_SIZE - swo_transmit_buffer_index); - memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][swo_transmit_buffer_index], swo_data, amount); - swo_transmit_buffer_index += amount; - /* Now, if we just exhausted that buffer, send it */ - if (swo_transmit_buffer_index == SWO_ENDPOINT_SIZE) { + /* First, see how much space we have in the buffer and move what we can */ + const uint16_t amount = MIN(byte_count, SWO_BUFFER_SIZE - swo_buffer_write_index); + memcpy(swo_buffer + swo_buffer_write_index, swo_data, amount); + swo_buffer_write_index += amount; + swo_buffer_write_index &= SWO_BUFFER_SIZE - 1U; + swo_buffer_bytes_available += amount; + /* Make sure we're sending the data if we've got more than an endpoint buffer's worth */ + if (swo_buffer_bytes_available >= SWO_ENDPOINT_SIZE) { swo_send_buffer(usbdev, SWO_ENDPOINT); - /* If we have anything left to move, now put that in the new buffer */ + /* If we have anything left to move, put that at the start of the buffer */ if (amount != byte_count) { const uint16_t remainder = byte_count - amount; - memcpy(&swo_transmit_buffers[swo_active_transmit_buffer][0U], swo_data + amount, remainder); - swo_transmit_buffer_index = remainder; + memcpy(swo_buffer, swo_data + amount, remainder); + swo_buffer_write_index = remainder; + swo_buffer_bytes_available += remainder; } } swo_data_bit_index = 0U; } -void swo_manchester_send_buffer(usbd_device *const dev, const uint8_t ep) -{ - if (!swo_transmit_buffer_index) - return; - - if (swo_itm_decoding) - swo_itm_decode( - dev, CDCACM_UART_ENDPOINT, swo_transmit_buffers[swo_active_transmit_buffer], swo_transmit_buffer_index); - else - usbd_ep_write_packet(dev, ep, swo_transmit_buffers[swo_active_transmit_buffer], swo_transmit_buffer_index); - swo_active_transmit_buffer ^= 1U; - swo_transmit_buffer_index = 0U; -} - void SWO_TIM_ISR(void) { static uint8_t bit_value; diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 6368bdaa2fc..81d54eebfd3 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -34,10 +34,6 @@ #include "swo.h" #include "swo_internal.h" -#include -#include -#include - #include #include #include @@ -59,32 +55,18 @@ #define DMA_PL_HIGH DMA_CCR_PL_HIGH #endif -static volatile uint32_t write_index; /* Packet currently received via UART */ -static volatile uint32_t read_index; /* Packet currently waiting to transmit to USB */ -/* Packets arrived from the SWO interface */ -static uint8_t *swo_data_buffer = NULL; - -static void swo_uart_set_baud(uint32_t baudrate); - void swo_uart_init(uint32_t baudrate) { - /* Skip initial allocation on commands for mode change */ - if (swo_data_buffer == NULL) { - /* Alignment (bytes): 1 for UART DMA, 2-4 for memcpy in usb code, 8 provided by malloc. Not 64 */ - uint8_t *const swo_data_buffer = malloc(NUM_SWO_PACKETS * SWO_ENDPOINT_SIZE); - /* Check for allocation failure and abort initialisation if we see it failed */ - if (!swo_data_buffer) { - DEBUG_ERROR("malloc: failed in %s\n", __func__); - return; - } - } - + /* First, make sure the baud rate is something sensible */ if (!baudrate) baudrate = SWO_DEFAULT_BAUD; + /* Ensure required peripherals are spun up */ + /* TODO: Move this into platform_init()! */ rcc_periph_clock_enable(SWO_UART_CLK); rcc_periph_clock_enable(SWO_DMA_CLK); + /* Reconfigure the GPIO over to UART mode */ #if defined(STM32F1) gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SWO_UART_RX_PIN); /* Pull SWO pin high to keep open SWO line ind uart idle state! */ @@ -95,65 +77,7 @@ void swo_uart_init(uint32_t baudrate) gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); #endif - nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); - nvic_enable_irq(SWO_DMA_IRQ); - swo_uart_set_baud(baudrate); -} - -void swo_uart_deinit(void) -{ - /* Stop peripherals servicing */ - nvic_disable_irq(SWO_DMA_IRQ); - dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); - usart_disable(SWO_UART); - /* Dump the buffered remains */ - swo_send_buffer(usbdev, SWO_ENDPOINT); - /* Return this contiguous chunk of SRAM to unshrinkable heap */ - if (swo_data_buffer != NULL) { - free(swo_data_buffer); - swo_data_buffer = NULL; - } - - /* Put the GPIO back into normal service as a GPIO */ -#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) - gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); -#else - gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_UART_RX_PIN); -#endif -} - -void swo_uart_send_buffer(usbd_device *const dev, const uint8_t ep) -{ - static atomic_flag reentry_flag = ATOMIC_FLAG_INIT; - - /* If we are already in this routine then we don't need to come in again */ - if (atomic_flag_test_and_set_explicit(&reentry_flag, memory_order_relaxed)) - return; - /* Attempt to write everything we buffered */ - if (write_index != read_index) { - uint16_t result; - if (swo_itm_decoding) - /* write decoded swo packets to the uart port */ - result = swo_itm_decode( - dev, CDCACM_UART_ENDPOINT, &swo_data_buffer[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); - else - /* write raw swo packets to the trace port */ - result = usbd_ep_write_packet(dev, ep, &swo_data_buffer[read_index * SWO_ENDPOINT_SIZE], SWO_ENDPOINT_SIZE); - if (result) - read_index = (read_index + 1U) % NUM_SWO_PACKETS; - } - atomic_flag_clear_explicit(&reentry_flag, memory_order_relaxed); -} - -uint32_t swo_uart_get_baudrate(void) -{ - return usart_get_baudrate(SWO_UART); -} - -static void swo_uart_set_baud(const uint32_t baudrate) -{ - dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); - usart_disable(SWO_UART); + /* Set up the UART for 8N1 at the requested baud rate in RX only */ bmd_usart_set_baudrate(SWO_UART, baudrate); usart_set_databits(SWO_UART, 8U); usart_set_stopbits(SWO_UART, USART_STOPBITS_1); @@ -161,10 +85,14 @@ static void swo_uart_set_baud(const uint32_t baudrate) usart_set_parity(SWO_UART, USART_PARITY_NONE); usart_set_flow_control(SWO_UART, USART_FLOWCONTROL_NONE); - /* Set up DMA channel */ + /* Set up DMA channel and tell the DMA subsystem where to put the data received from the UART */ dma_channel_reset(SWO_DMA_BUS, SWO_DMA_CHAN); // NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast,performance-no-int-to-ptr) dma_set_peripheral_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&SWO_UART_DR); + // NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast) + dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)swo_buffer); + /* Define the buffer length and configure this as a peripheral -> memory transfer */ + dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, SWO_BUFFER_SIZE); #if defined(DMA_STREAM0) dma_set_transfer_mode(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_channel_select(SWO_DMA_BUS, SWO_DMA_CHAN, SWO_DMA_TRG); @@ -174,33 +102,64 @@ static void swo_uart_set_baud(const uint32_t baudrate) dma_set_read_from_peripheral(SWO_DMA_BUS, SWO_DMA_CHAN); #endif dma_enable_memory_increment_mode(SWO_DMA_BUS, SWO_DMA_CHAN); + /* Define it as being bytewise into a circular buffer with high priority */ dma_set_peripheral_size(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_PSIZE_8BIT); dma_set_memory_size(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_MSIZE_8BIT); dma_set_priority(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_PL_HIGH); + dma_enable_circular_mode(SWO_DMA_BUS, SWO_DMA_CHAN); + /* Enable the 50% and 100% interrupts so we can update the buffer counters to initiate the USB half of the picture */ dma_enable_transfer_complete_interrupt(SWO_DMA_BUS, SWO_DMA_CHAN); dma_enable_half_transfer_interrupt(SWO_DMA_BUS, SWO_DMA_CHAN); - dma_enable_circular_mode(SWO_DMA_BUS, SWO_DMA_CHAN); + /* Enable DMA trigger on receive for the UART */ + usart_enable_rx_dma(SWO_UART); - usart_enable(SWO_UART); + /* Enable the interrupts */ + nvic_set_priority(SWO_DMA_IRQ, IRQ_PRI_SWO_DMA); nvic_enable_irq(SWO_DMA_IRQ); - write_index = read_index = 0; - // NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast) - dma_set_memory_address(SWO_DMA_BUS, SWO_DMA_CHAN, (uintptr_t)&swo_transmit_buffers[0][0]); - dma_set_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN, 2 * SWO_ENDPOINT_SIZE); + + /* Reset the read and write indicies */ + swo_buffer_read_index = 0U; + swo_buffer_write_index = 0U; + + /* Now everything has been configured, enable the UART and its associated DMA channel */ dma_enable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); - usart_enable_rx_dma(SWO_UART); + usart_enable(SWO_UART); +} + +void swo_uart_deinit(void) +{ + /* Disable the UART and halt DMA for it, grabbing the number of bytes left in the buffer as we do */ + usart_disable(SWO_UART); + const uint16_t space_remaining = dma_get_number_of_data(SWO_DMA_BUS, SWO_DMA_CHAN); + dma_disable_channel(SWO_DMA_BUS, SWO_DMA_CHAN); + + /* Convert the counter into an amount captured and add that to the write index and amount available */ + const uint16_t amount = (SWO_BUFFER_SIZE - space_remaining) & ((SWO_BUFFER_SIZE / 2U) - 1U); + swo_buffer_write_index += amount; + swo_buffer_bytes_available += amount; + + /* Put the GPIO back into normal service as a GPIO */ +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); +#else + gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_UART_RX_PIN); +#endif +} + +uint32_t swo_uart_get_baudrate(void) +{ + return usart_get_baudrate(SWO_UART); } void SWO_DMA_ISR(void) { if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_HTIF); - memcpy(&swo_data_buffer[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[0U], SWO_ENDPOINT_SIZE); + swo_buffer_bytes_available += SWO_BUFFER_SIZE / 2U; } if (dma_get_interrupt_flag(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF)) { dma_clear_interrupt_flags(SWO_DMA_BUS, SWO_DMA_CHAN, DMA_TCIF); - memcpy(&swo_data_buffer[write_index * SWO_ENDPOINT_SIZE], swo_transmit_buffers[1U], SWO_ENDPOINT_SIZE); + swo_buffer_bytes_available += SWO_BUFFER_SIZE / 2U; } - write_index = (write_index + 1U) % NUM_SWO_PACKETS; swo_send_buffer(usbdev, SWO_ENDPOINT); } diff --git a/src/platforms/common/swo.h b/src/platforms/common/swo.h index 536a76e6172..0e6830d85aa 100644 --- a/src/platforms/common/swo.h +++ b/src/platforms/common/swo.h @@ -38,7 +38,7 @@ extern swo_coding_e swo_current_mode; /* Initialisation and deinitialisation functions (ties into command.c) */ void swo_init(swo_coding_e swo_mode, uint32_t baudrate, uint32_t itm_stream_bitmask); -void swo_deinit(void); +void swo_deinit(bool deallocate); /* UART mode baudate functions */ uint32_t swo_uart_get_baudrate(void); diff --git a/src/platforms/common/usb.h b/src/platforms/common/usb.h index e07815b8932..19611dc5384 100644 --- a/src/platforms/common/usb.h +++ b/src/platforms/common/usb.h @@ -28,11 +28,13 @@ extern usbd_device *usbdev; extern uint16_t usb_config; #if defined(USB_HS) -#define CDCACM_PACKET_SIZE 512U -#define SWO_ENDPOINT_SIZE 512U +#define CDCACM_PACKET_SIZE 512U +#define SWO_ENDPOINT_SIZE 512U +#define NUM_SWO_USB_PACKETS 16U /* 8KiB of data buffer */ #else -#define CDCACM_PACKET_SIZE 64U -#define SWO_ENDPOINT_SIZE 64U +#define CDCACM_PACKET_SIZE 64U +#define SWO_ENDPOINT_SIZE 64U +#define NUM_SWO_USB_PACKETS 4U /* 512B of data buffer */ #endif #if !defined(USB_MAX_INTERVAL) From 50253203bbf838371e451180e3bd699eae9e62c5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 11:50:15 +0100 Subject: [PATCH 35/48] platforms: Cleaned up defunct SWO definitions --- src/platforms/common/blackpill-f4/blackpill-f4.h | 5 ++--- src/platforms/ctxlink/platform.h | 3 --- src/platforms/native/platform.h | 2 -- src/platforms/stlink/platform.h | 10 ++++------ src/platforms/stlinkv3/platform.h | 2 -- src/platforms/swlink/platform.h | 5 +---- 6 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index bcc71a00426..7305ba1a34e 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -32,6 +32,8 @@ #include "timing.h" #include "timing_stm32.h" +#define PLATFORM_HAS_TRACESWO + #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG extern bool debug_bmp; @@ -287,9 +289,6 @@ extern bool debug_bmp; #define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#define PLATFORM_HAS_TRACESWO -#define NUM_SWO_PACKETS 256U /* 16K buffer */ - #if SWO_ENCODING == 1 /* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, triggered on rising edge */ diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index 108be6cae3a..ebae4f9a152 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -183,9 +183,6 @@ #define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#define PLATFORM_HAS_TRACESWO -#define NUM_SWO_PACKETS 256U /* 16K buffer */ - #if SWO_ENCODING == 1 /* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 38c488a0523..e2c393c7a33 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -297,8 +297,6 @@ extern int hwversion; #define USBUSART2_DMA_RX_IRQ NVIC_DMA1_CHANNEL6_IRQ #define USBUSART2_DMA_RX_ISR(x) dma1_channel6_isr(x) -#define NUM_SWO_PACKETS 8U /* 512B buffer */ - /* Use TIM3 Input 1 (from PA6/TDO) for Manchester data recovery */ #define SWO_TIM TIM3 #define SWO_TIM_CLK_EN() diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index fe0cf1b6c55..f1d0d6c0387 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -31,6 +31,10 @@ #include #include +#ifndef SWIM_AS_UART +#define PLATFORM_HAS_TRACESWO +#endif + #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG extern bool debug_bmp; @@ -169,12 +173,6 @@ extern bool debug_bmp; #define USBUSART_DMA_BUS DMA1 #define USBUSART_DMA_CLK RCC_DMA1 -#ifndef SWIM_AS_UART -#define PLATFORM_HAS_TRACESWO 1 -#endif -#define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ -//#define SWO_ENCODING 2U /* 1 = Manchester, 2 = NRZ / async */ - #if SWO_ENCODING == 1 /* Use TIM3 Input 1 (from PA6/TDO) */ diff --git a/src/platforms/stlinkv3/platform.h b/src/platforms/stlinkv3/platform.h index 98cb2deb974..93360f501df 100644 --- a/src/platforms/stlinkv3/platform.h +++ b/src/platforms/stlinkv3/platform.h @@ -84,8 +84,6 @@ extern bool debug_bmp; #define MCO1_PIN GPIO8 #define MCO1_AF 0 -#define NUM_SWO_PACKETS 16U - #define SWDIO_MODE_REG GPIO_MODER(TMS_PORT) #define SWDIO_MODE_REG_MULT (1U << (9U << 1U)) diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 11cc2e87670..7b823308e03 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -28,6 +28,7 @@ #include "timing.h" #include "timing_stm32.h" +#define PLATFORM_HAS_TRACESWO #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG extern bool debug_bmp; @@ -121,10 +122,6 @@ extern bool debug_bmp; #define USBUSART_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ #define USBUSART_DMA_RX_ISR(x) dma1_channel5_isr(x) -#define PLATFORM_HAS_TRACESWO 1 -#define NUM_SWO_PACKETS 128U /* This is an 8K buffer */ -//#define SWO_ENCODING 2U /* 1 = Manchester, 2 = NRZ / async */ - #if SWO_ENCODING == 1 /* Use TIM2 Input 2 (from PB3/TDO with Remap) */ From 7b11f5037f2a33ae37e3fafd48448cb7a49fe9f5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 11:56:19 +0100 Subject: [PATCH 36/48] ctxlink: Enabled switchable SWO on the platform --- src/platforms/ctxlink/meson.build | 13 ++++++------- src/platforms/ctxlink/platform.h | 20 +++++++------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/platforms/ctxlink/meson.build b/src/platforms/ctxlink/meson.build index a97647695a3..808f177052f 100644 --- a/src/platforms/ctxlink/meson.build +++ b/src/platforms/ctxlink/meson.build @@ -37,14 +37,13 @@ probe_ctxlink_args = [ ] trace_protocol = get_option('trace_protocol') -if trace_protocol == '3' - trace_protocol = '2' -endif probe_ctxlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] -if trace_protocol == '1' - probe_ctxlink_dependencies = platform_stm32_swo_manchester -else - probe_ctxlink_dependencies = platform_stm32_swo_uart +probe_ctxlink_dependencies = [] +if trace_protocol in ['1', '3'] + probe_ctxlink_dependencies += platform_stm32_swo_manchester +endif +if trace_protocol in ['2', '3'] + probe_ctxlink_dependencies += platform_stm32_swo_uart endif probe_ctxlink_commonn_link_args = [ diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index ebae4f9a152..bfdd489ab80 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -183,8 +183,6 @@ #define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#if SWO_ENCODING == 1 - /* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ #define SWO_TIM TIM3 #define SWO_TIM_CLK_EN() @@ -202,9 +200,7 @@ #define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 #define SWO_TIM_PIN_AF GPIO_AF2 -#elif SWO_ENCODING == 2 - -/* On ctxLink use USART6_RX mapped on PC7 for async capture */ +/* On ctxLink use USART6 RX mapped on PC7 for async capture */ #define SWO_UART USART6 #define SWO_UART_CLK RCC_USART6 #define SWO_UART_DR USART6_DR @@ -213,14 +209,12 @@ #define SWO_UART_PIN_AF GPIO_AF8 /* Bind to the same DMA Rx channel */ -#define SWO_DMA_BUS DMA2 -#define SWO_DMA_CLK RCC_DMA2 -#define SWO_DMA_CHAN DMA_STREAM1 -#define SWO_DMA_IRQ NVIC_DMA2_STREAM1_IRQ -#define SWO_DMA_ISR dma2_stream1_isr -#define SWO_DMA_TRG DMA_SxCR_CHSEL_5 - -#endif /* SWO_ENCODING */ +#define SWO_DMA_BUS DMA2 +#define SWO_DMA_CLK RCC_DMA2 +#define SWO_DMA_CHAN DMA_STREAM1 +#define SWO_DMA_IRQ NVIC_DMA2_STREAM1_IRQ +#define SWO_DMA_ISR dma2_stream1_isr +#define SWO_DMA_TRG DMA_SxCR_CHSEL_5 #define SET_RUN_STATE(state) \ { \ From 312194c223fbfee1a0421701e9d8449fc39ec7e1 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 11:58:50 +0100 Subject: [PATCH 37/48] swlink: Enabled switchable SWO on the platform --- src/platforms/swlink/meson.build | 14 +++++++------- src/platforms/swlink/platform.h | 21 ++++++++------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/platforms/swlink/meson.build b/src/platforms/swlink/meson.build index cb0bc117983..8778e395d61 100644 --- a/src/platforms/swlink/meson.build +++ b/src/platforms/swlink/meson.build @@ -54,13 +54,13 @@ probe_swlink_link_args = [ ] trace_protocol = get_option('trace_protocol') -if trace_protocol == '3' - trace_protocol = '2' +probe_swlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] +probe_swlink_dependencies = [] +if trace_protocol in ['1', '3'] + probe_swlink_dependencies += platform_stm32_swo_manchester endif -if trace_protocol == '2' - probe_swlink_args += '-DSWO_ENCODING=2' -else - error('Unsupported SWO protocol requested') +if trace_protocol in ['2', '3'] + probe_swlink_dependencies += platform_stm32_swo_uart endif probe_host = declare_dependency( @@ -68,7 +68,7 @@ probe_host = declare_dependency( sources: probe_swlink_sources, compile_args: probe_swlink_args, link_args: probe_swlink_common_link_args + probe_swlink_link_args, - dependencies: [platform_common, platform_stm32f1, platform_stm32_swo_uart], + dependencies: [platform_common, platform_stm32f1, probe_swlink_dependencies], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 7b823308e03..65d774b74a6 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -29,6 +29,7 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO + #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG extern bool debug_bmp; @@ -122,8 +123,6 @@ extern bool debug_bmp; #define USBUSART_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ #define USBUSART_DMA_RX_ISR(x) dma1_channel5_isr(x) -#if SWO_ENCODING == 1 - /* Use TIM2 Input 2 (from PB3/TDO with Remap) */ #define SWO_TIM TIM2 #define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) @@ -131,17 +130,15 @@ extern bool debug_bmp; #define SWO_TIM_ISR(x) tim2_isr(x) #define SWO_IC_IN TIM_IC_IN_TI2 #define SWO_IC_RISING TIM_IC1 -#define SWO_CC_RISING TIM3_CCR1 +#define SWO_CC_RISING TIM2_CCR1 #define SWO_ITR_RISING TIM_DIER_CC1IE #define SWO_STATUS_RISING TIM_SR_CC1IF #define SWO_IC_FALLING TIM_IC2 -#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_CC_FALLING TIM2_CCR2 #define SWO_STATUS_FALLING TIM_SR_CC2IF #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 -#elif SWO_ENCODING == 2 - /* * On F103, only USART1 is on AHB2 and can reach 4.5MBaud at 72 MHz. * Unfortunately, USART1 is already used, so the maximum speed @@ -154,13 +151,11 @@ extern bool debug_bmp; #define SWO_UART_RX_PIN GPIO3 /* This DMA channel is set by the USART in use */ -#define SWO_DMA_BUS DMA1 -#define SWO_DMA_CLK RCC_DMA1 -#define SWO_DMA_CHAN DMA_CHANNEL6 -#define SWO_DMA_IRQ NVIC_DMA1_CHANNEL6_IRQ -#define SWO_DMA_ISR(x) dma1_channel6_isr(x) - -#endif /* SWO_ENCODING */ +#define SWO_DMA_BUS DMA1 +#define SWO_DMA_CLK RCC_DMA1 +#define SWO_DMA_CHAN DMA_CHANNEL6 +#define SWO_DMA_IRQ NVIC_DMA1_CHANNEL6_IRQ +#define SWO_DMA_ISR(x) dma1_channel6_isr(x) #define LED_PORT GPIOC #define LED_IDLE_RUN GPIO15 From c261082ded8c50b6285b911529fef05fba32d354 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 12:00:55 +0100 Subject: [PATCH 38/48] stlink: Enabled switchable SWO on the platform --- src/platforms/stlink/meson.build | 17 +++++++---------- src/platforms/stlink/platform.h | 16 +++++----------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/platforms/stlink/meson.build b/src/platforms/stlink/meson.build index d4490103718..c353e000dd1 100644 --- a/src/platforms/stlink/meson.build +++ b/src/platforms/stlink/meson.build @@ -70,21 +70,18 @@ probe_stlink_dependencies = [platform_common, platform_stm32f1] stlink_swim_nrst_as_uart = get_option('stlink_swim_nrst_as_uart') trace_protocol = get_option('trace_protocol') -if trace_protocol == '3' - trace_protocol = '2' -endif if probe == 'stlink' and stlink_swim_nrst_as_uart probe_stlink_args += ['-DSWIM_NRST_AS_UART=1'] probe_stlink_dependencies += platform_stm32_swo_manchester probe_stlink_args += ['-DSWO_ENCODING=1'] -elif trace_protocol == '1' - probe_stlink_dependencies += platform_stm32_swo_manchester - probe_stlink_args += ['-DSWO_ENCODING=1'] -elif trace_protocol == '2' - probe_stlink_dependencies += platform_stm32_swo_uart - probe_stlink_args += ['-DSWO_ENCODING=2'] else - error('Unsupported SWO mode requested') + probe_stlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] + if trace_protocol in ['1', '3'] + probe_stlink_dependencies += platform_stm32_swo_manchester + endif + if trace_protocol in ['2', '3'] + probe_stlink_dependencies += platform_stm32_swo_uart + endif endif probe_host = declare_dependency( diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index f1d0d6c0387..8068c717d2a 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -173,8 +173,6 @@ extern bool debug_bmp; #define USBUSART_DMA_BUS DMA1 #define USBUSART_DMA_CLK RCC_DMA1 -#if SWO_ENCODING == 1 - /* Use TIM3 Input 1 (from PA6/TDO) */ #define SWO_TIM TIM3 #define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) @@ -191,8 +189,6 @@ extern bool debug_bmp; #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI1FP1 -#elif SWO_ENCODING == 2 - /* On F103, only USART1 is on AHB2 and can reach 4.5MBaud at 72 MHz. */ #define SWO_UART USART1 #define SWO_UART_DR USART1_DR @@ -201,13 +197,11 @@ extern bool debug_bmp; #define SWO_UART_RX_PIN GPIO10 /* This DMA channel is set by the USART in use */ -#define SWO_DMA_BUS DMA1 -#define SWO_DMA_CLK RCC_DMA1 -#define SWO_DMA_CHAN DMA_CHANNEL5 -#define SWO_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ -#define SWO_DMA_ISR(x) dma1_channel5_isr(x) - -#endif /* SWO_ENCODING */ +#define SWO_DMA_BUS DMA1 +#define SWO_DMA_CLK RCC_DMA1 +#define SWO_DMA_CHAN DMA_CHANNEL5 +#define SWO_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ +#define SWO_DMA_ISR(x) dma1_channel5_isr(x) extern uint16_t led_idle_run; #define LED_IDLE_RUN led_idle_run From 2ea0787604511c5b6c114054fa4766f60ae1959e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 12:03:21 +0100 Subject: [PATCH 39/48] common/blackpill-f4: Enabled switchable SWO on the platform --- .../common/blackpill-f4/blackpill-f4.h | 22 +++++++------------ src/platforms/common/blackpill-f4/meson.build | 13 +++++------ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index 7305ba1a34e..a03265d8dea 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -289,8 +289,6 @@ extern bool debug_bmp; #define IRQ_PRI_SWO_TIM (0U << 4U) #define IRQ_PRI_SWO_DMA (0U << 4U) -#if SWO_ENCODING == 1 - /* Use TIM4 Input 2 (from PB7/TDO) or Input 1 (from PB6/TDO), AF2, triggered on rising edge */ #define SWO_TIM TIM4 #define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) @@ -298,18 +296,16 @@ extern bool debug_bmp; #define SWO_TIM_ISR(x) tim4_isr(x) #define SWO_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) #define SWO_IC_RISING TIM_IC1 -#define SWO_CC_RISING TIM3_CCR1 +#define SWO_CC_RISING TIM4_CCR1 #define SWO_ITR_RISING TIM_DIER_CC1IE #define SWO_STATUS_RISING TIM_SR_CC1IF #define SWO_IC_FALLING TIM_IC2 -#define SWO_CC_FALLING TIM3_CCR2 +#define SWO_CC_FALLING TIM4_CCR2 #define SWO_STATUS_FALLING TIM_SR_CC2IF #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) #define SWO_TIM_PIN_AF GPIO_AF2 -#elif SWO_ENCODING == 2 - /* On F411 use USART1_RX mapped on PB7 for async capture */ #define SWO_UART USBUSART1 #define SWO_UART_CLK USBUSART1_CLK @@ -319,14 +315,12 @@ extern bool debug_bmp; #define SWO_UART_PIN_AF GPIO_AF7 /* Bind to the same DMA Rx channel */ -#define SWO_DMA_BUS USBUSART1_DMA_BUS -#define SWO_DMA_CLK USBUSART1_DMA_CLK -#define SWO_DMA_CHAN USBUSART1_DMA_RX_CHAN -#define SWO_DMA_IRQ USBUSART1_DMA_RX_IRQ -#define SWO_DMA_ISR(x) USBUSART1_DMA_RX_ISRx(x) -#define SWO_DMA_TRG DMA_SxCR_CHSEL_4 - -#endif /* SWO_ENCODING */ +#define SWO_DMA_BUS USBUSART1_DMA_BUS +#define SWO_DMA_CLK USBUSART1_DMA_CLK +#define SWO_DMA_CHAN USBUSART1_DMA_RX_CHAN +#define SWO_DMA_IRQ USBUSART1_DMA_RX_IRQ +#define SWO_DMA_ISR(x) USBUSART1_DMA_RX_ISRx(x) +#define SWO_DMA_TRG DMA_SxCR_CHSEL_4 #define SET_RUN_STATE(state) \ { \ diff --git a/src/platforms/common/blackpill-f4/meson.build b/src/platforms/common/blackpill-f4/meson.build index 56ea8072724..3cd777c3188 100644 --- a/src/platforms/common/blackpill-f4/meson.build +++ b/src/platforms/common/blackpill-f4/meson.build @@ -67,14 +67,13 @@ if on_carrier_board endif trace_protocol = get_option('trace_protocol') -if trace_protocol == '3' - trace_protocol = '2' -endif probe_blackpill_args += [f'-DSWO_ENCODING=@trace_protocol@'] -if trace_protocol == '1' - probe_blackpill_dependencies = platform_stm32_swo_manchester -else - probe_blackpill_dependencies = platform_stm32_swo_uart +probe_blackpill_dependencies = [] +if trace_protocol in ['1', '3'] + probe_blackpill_dependencies += platform_stm32_swo_manchester +endif +if trace_protocol in ['2', '3'] + probe_blackpill_dependencies += platform_stm32_swo_uart endif if bmd_bootloader From 891261e47b32c7b3ebc2016e85bf83c70656cb30 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 12:32:14 +0100 Subject: [PATCH 40/48] platforms: Added missing definitions for the SWO support across various platforms --- src/platforms/common/stm32/swo.c | 1 + src/platforms/ctxlink/platform.h | 4 ++-- src/platforms/f072/platform.h | 1 + src/platforms/f3/platform.h | 1 + src/platforms/f4discovery/platform.h | 2 ++ src/platforms/hydrabus/platform.h | 2 ++ src/platforms/launchpad-icdi/platform.h | 9 +++++---- src/platforms/stlinkv3/Makefile.inc | 2 +- src/platforms/stlinkv3/meson.build | 1 - src/platforms/stlinkv3/platform.h | 1 + 10 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c index 1c3e0b7c8ea..7b5c071b4f8 100644 --- a/src/platforms/common/stm32/swo.c +++ b/src/platforms/common/stm32/swo.c @@ -19,6 +19,7 @@ */ #include "general.h" +#include "platform.h" #include "gdb_packet.h" #include "swo.h" #include "swo_internal.h" diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index bfdd489ab80..6ae7d6e92a4 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -184,8 +184,8 @@ #define IRQ_PRI_SWO_DMA (0U << 4U) /* Use TIM3 Input 2 from PC7/TDO, AF2, trigger on rising edge */ -#define SWO_TIM TIM3 -#define SWO_TIM_CLK_EN() +#define SWO_TIM TIM3 +#define SWO_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) #define SWO_TIM_IRQ NVIC_TIM3_IRQ #define SWO_TIM_ISR(x) tim3_isr(x) #define SWO_IC_IN TIM_IC_IN_TI2 diff --git a/src/platforms/f072/platform.h b/src/platforms/f072/platform.h index ab8453642d5..8cde924da40 100644 --- a/src/platforms/f072/platform.h +++ b/src/platforms/f072/platform.h @@ -27,6 +27,7 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 1 /* Use only Manchester mode SWO recovery */ #define PLATFORM_IDENT "(F072-IF) " diff --git a/src/platforms/f3/platform.h b/src/platforms/f3/platform.h index 2915e55e72a..e9d63f447b7 100644 --- a/src/platforms/f3/platform.h +++ b/src/platforms/f3/platform.h @@ -27,6 +27,7 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 1 /* Use only Manchester mode SWO recovery */ #define PLATFORM_IDENT "(F3-IF) " diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 8f71a710612..dcf081c8054 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -28,6 +28,8 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 1 /* Use only Manchester mode SWO recovery */ + #define PLATFORM_IDENT "(F4Discovery) " /* diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index 5e505299f56..5375c5115e4 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -29,6 +29,8 @@ #include "timing_stm32.h" #define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 1 /* Use only Manchester mode SWO recovery */ + #define PLATFORM_IDENT "(HydraBus) " /* diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 846f504c065..ff26f8d1530 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -23,6 +23,9 @@ #include "timing.h" +#define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 2 /* Use only UART mode SWO recovery */ + #define PLATFORM_IDENT "(Launchpad ICDI) " extern uint8_t running_status; @@ -103,16 +106,14 @@ extern uint8_t running_status; } #define SET_ERROR_STATE(state) SET_IDLE_STATE(state) -#define PLATFORM_HAS_TRACESWO - inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { - gpio_write(port, pin, val == 0 ? 0 : 0xff); + gpio_write(port, pin, val == 0U ? 0U : 0xffU); } inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { - return !(gpio_read(port, pin) == 0); + return gpio_read(port, pin) != 0U; } #define disconnect_usb() \ diff --git a/src/platforms/stlinkv3/Makefile.inc b/src/platforms/stlinkv3/Makefile.inc index 736b33eed19..3df3a5536d0 100644 --- a/src/platforms/stlinkv3/Makefile.inc +++ b/src/platforms/stlinkv3/Makefile.inc @@ -5,7 +5,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy OPT_FLAGS = -Og -g CFLAGS += -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard \ -DSTM32F7 -DDFU_SERIAL_LENGTH=25 -I../deps/libopencm3/include \ - -I platforms/common/stm32 -DSWO_ENCODING=2 + -I platforms/common/stm32 LDFLAGS_BOOT := $(LDFLAGS) -mfpu=fpv5-sp-d16 -mfloat-abi=hard \ --specs=nano.specs -lopencm3_stm32f7 -Lplatforms/stlinkv3 \ -Tstlinkv3.ld -nostartfiles -lc \ diff --git a/src/platforms/stlinkv3/meson.build b/src/platforms/stlinkv3/meson.build index 7962cabe20e..dde0834a6bb 100644 --- a/src/platforms/stlinkv3/meson.build +++ b/src/platforms/stlinkv3/meson.build @@ -64,7 +64,6 @@ if trace_protocol == '3' endif if trace_protocol == '2' probe_stlinkv3_dependencies = platform_stm32_swo_uart - probe_stlinkv3_args += ['-DSWO_ENCODING=2'] else error('Unsupported SWO protocol requested') endif diff --git a/src/platforms/stlinkv3/platform.h b/src/platforms/stlinkv3/platform.h index 93360f501df..78643bd4fba 100644 --- a/src/platforms/stlinkv3/platform.h +++ b/src/platforms/stlinkv3/platform.h @@ -33,6 +33,7 @@ #include #define PLATFORM_HAS_TRACESWO +#define SWO_ENCODING 2 /* Use only UART mode SWO recovery */ #if ENABLE_DEBUG == 1 #define PLATFORM_HAS_DEBUG From 72b89dae5f858970c1a06536398dde3aad6a6720 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 12:59:18 +0100 Subject: [PATCH 41/48] common/stm32/swo: Deal with the STM32F7 platforms properly in the pin control blocks --- src/platforms/common/stm32/swo_manchester.c | 4 ++-- src/platforms/common/stm32/swo_uart.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index 1bebc820aea..aaebee4fe79 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -68,7 +68,7 @@ void swo_manchester_init(void) /* Make sure the timer block is clocked on platforms that don't do this in their `platform_init()` */ SWO_TIM_CLK_EN(); -#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) || defined(STM32F7) /* Set any required pin alt-function configuration - TIM3/TIM4/TIM5 are AF2 */ gpio_mode_setup(SWO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SWO_PIN); gpio_set_af(SWO_PORT, SWO_TIM_PIN_AF, SWO_PIN); @@ -122,7 +122,7 @@ void swo_manchester_deinit(void) swo_data_bit_index = 0U; swo_half_bit_period = 0U; -#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) || defined(STM32F7) gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); #else /* Put the GPIO back into normal service as a GPIO */ diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 81d54eebfd3..586d01a2851 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -67,14 +67,14 @@ void swo_uart_init(uint32_t baudrate) rcc_periph_clock_enable(SWO_DMA_CLK); /* Reconfigure the GPIO over to UART mode */ -#if defined(STM32F1) - gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SWO_UART_RX_PIN); - /* Pull SWO pin high to keep open SWO line ind uart idle state! */ - gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); -#else +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) || defined(STM32F7) gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SWO_UART_RX_PIN); gpio_set_output_options(SWO_UART_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_100MHZ, SWO_UART_RX_PIN); gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); +#else + gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SWO_UART_RX_PIN); + /* Pull SWO pin high to keep open SWO line ind uart idle state! */ + gpio_set(SWO_UART_PORT, SWO_UART_RX_PIN); #endif /* Set up the UART for 8N1 at the requested baud rate in RX only */ @@ -139,7 +139,7 @@ void swo_uart_deinit(void) swo_buffer_bytes_available += amount; /* Put the GPIO back into normal service as a GPIO */ -#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) +#if defined(STM32F4) || defined(STM32F0) || defined(STM32F3) || defined(STM32F7) gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); #else gpio_set_mode(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SWO_UART_RX_PIN); From 48577509419681c8d9f7a5c8f68e26a53874cc98 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 14:55:02 +0100 Subject: [PATCH 42/48] platforms: Fixed the build system including the base SWO and ITM decoder support even on platforms where it should not --- src/platforms/common/blackpill-f4/meson.build | 2 +- src/platforms/common/stm32/meson.build | 8 ++++---- src/platforms/ctxlink/meson.build | 2 +- src/platforms/f072/meson.build | 2 +- src/platforms/f3/meson.build | 2 +- src/platforms/f4discovery/meson.build | 2 +- src/platforms/hydrabus/meson.build | 2 +- src/platforms/native/meson.build | 2 +- src/platforms/stlink/meson.build | 2 +- src/platforms/stlinkv3/meson.build | 2 +- src/platforms/swlink/meson.build | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/platforms/common/blackpill-f4/meson.build b/src/platforms/common/blackpill-f4/meson.build index 3cd777c3188..2d399facc76 100644 --- a/src/platforms/common/blackpill-f4/meson.build +++ b/src/platforms/common/blackpill-f4/meson.build @@ -68,7 +68,7 @@ endif trace_protocol = get_option('trace_protocol') probe_blackpill_args += [f'-DSWO_ENCODING=@trace_protocol@'] -probe_blackpill_dependencies = [] +probe_blackpill_dependencies = [platform_stm32_swo] if trace_protocol in ['1', '3'] probe_blackpill_dependencies += platform_stm32_swo_manchester endif diff --git a/src/platforms/common/stm32/meson.build b/src/platforms/common/stm32/meson.build index ebf4bfbb97e..dec705b59c6 100644 --- a/src/platforms/common/stm32/meson.build +++ b/src/platforms/common/stm32/meson.build @@ -34,12 +34,12 @@ platform_stm32_sources = files( 'gdb_if.c', 'serialno.c', 'timing_stm32.c', - 'swo.c', - 'swo_itm_decode.c', ) -# TODO: add proper traceswoasync support -# This is a temporary hack to allow selecting swo_manchester vs swo_uart implementation +platform_stm32_swo = declare_dependency(sources: files( + 'swo.c', + 'swo_itm_decode.c', +)) platform_stm32_swo_manchester = declare_dependency(sources: files('swo_manchester.c')) platform_stm32_swo_uart = declare_dependency(sources: files('swo_uart.c')) diff --git a/src/platforms/ctxlink/meson.build b/src/platforms/ctxlink/meson.build index 808f177052f..49bdeba87f0 100644 --- a/src/platforms/ctxlink/meson.build +++ b/src/platforms/ctxlink/meson.build @@ -38,7 +38,7 @@ probe_ctxlink_args = [ trace_protocol = get_option('trace_protocol') probe_ctxlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] -probe_ctxlink_dependencies = [] +probe_ctxlink_dependencies = [platform_stm32_swo] if trace_protocol in ['1', '3'] probe_ctxlink_dependencies += platform_stm32_swo_manchester endif diff --git a/src/platforms/f072/meson.build b/src/platforms/f072/meson.build index 8678cdc56b3..1e4669b8c46 100644 --- a/src/platforms/f072/meson.build +++ b/src/platforms/f072/meson.build @@ -46,7 +46,7 @@ probe_host = declare_dependency( sources: probe_f072_sources, compile_args: probe_f072_args, link_args: probe_f072_link_args, - dependencies: [platform_common, platform_stm32f0, platform_stm32_swo_manchester], + dependencies: [platform_common, platform_stm32f0, platform_stm32_swo, platform_stm32_swo_manchester], ) summary( diff --git a/src/platforms/f3/meson.build b/src/platforms/f3/meson.build index aa230a53a59..fec311c4c55 100644 --- a/src/platforms/f3/meson.build +++ b/src/platforms/f3/meson.build @@ -46,7 +46,7 @@ probe_host = declare_dependency( sources: probe_f3_sources, compile_args: probe_f3_args, link_args: probe_f3_link_args, - dependencies: [platform_common, platform_stm32f3, platform_stm32_swo_manchester], + dependencies: [platform_common, platform_stm32f3, platform_stm32_swo, platform_stm32_swo_manchester], ) summary( diff --git a/src/platforms/f4discovery/meson.build b/src/platforms/f4discovery/meson.build index 302ebd3f644..8a5a124e59a 100644 --- a/src/platforms/f4discovery/meson.build +++ b/src/platforms/f4discovery/meson.build @@ -57,7 +57,7 @@ probe_host = declare_dependency( sources: probe_f4discovery_sources, compile_args: probe_f4discovery_args, link_args: probe_f4discovery_commonn_link_args + probe_f4discovery_link_args, - dependencies: [platform_common, platform_stm32f4, platform_stm32_swo_manchester], + dependencies: [platform_common, platform_stm32f4, platform_stm32_swo, platform_stm32_swo_manchester], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/hydrabus/meson.build b/src/platforms/hydrabus/meson.build index d80924d33ae..da2f0a27330 100644 --- a/src/platforms/hydrabus/meson.build +++ b/src/platforms/hydrabus/meson.build @@ -48,7 +48,7 @@ probe_host = declare_dependency( sources: probe_hydrabus_sources, compile_args: probe_hydrabus_args, link_args: probe_hydrabus_link_args, - dependencies: [platform_common, platform_stm32f4, platform_stm32_swo_manchester], + dependencies: [platform_common, platform_stm32f4, platform_stm32_swo, platform_stm32_swo_manchester], ) probe_bootloader = declare_dependency( diff --git a/src/platforms/native/meson.build b/src/platforms/native/meson.build index 0c38d544c4c..473ba65d4dd 100644 --- a/src/platforms/native/meson.build +++ b/src/platforms/native/meson.build @@ -41,7 +41,7 @@ probe_native_args = [ trace_protocol = get_option('trace_protocol') probe_native_args += [f'-DSWO_ENCODING=@trace_protocol@'] -probe_native_dependencies = [] +probe_native_dependencies = [platform_stm32_swo] if trace_protocol in ['1', '3'] probe_native_dependencies += platform_stm32_swo_manchester endif diff --git a/src/platforms/stlink/meson.build b/src/platforms/stlink/meson.build index c353e000dd1..ab8b3529796 100644 --- a/src/platforms/stlink/meson.build +++ b/src/platforms/stlink/meson.build @@ -65,7 +65,7 @@ if probe == 'bluepill' probe_stlink_args += ['-DBLUEPILL=1'] endif -probe_stlink_dependencies = [platform_common, platform_stm32f1] +probe_stlink_dependencies = [platform_common, platform_stm32f1, platform_stm32_swo] stlink_swim_nrst_as_uart = get_option('stlink_swim_nrst_as_uart') diff --git a/src/platforms/stlinkv3/meson.build b/src/platforms/stlinkv3/meson.build index dde0834a6bb..d5b4a09da57 100644 --- a/src/platforms/stlinkv3/meson.build +++ b/src/platforms/stlinkv3/meson.build @@ -63,7 +63,7 @@ if trace_protocol == '3' trace_protocol = '2' endif if trace_protocol == '2' - probe_stlinkv3_dependencies = platform_stm32_swo_uart + probe_stlinkv3_dependencies = [platform_stm32_swo, platform_stm32_swo_uart] else error('Unsupported SWO protocol requested') endif diff --git a/src/platforms/swlink/meson.build b/src/platforms/swlink/meson.build index 8778e395d61..19dff6f0e5b 100644 --- a/src/platforms/swlink/meson.build +++ b/src/platforms/swlink/meson.build @@ -55,7 +55,7 @@ probe_swlink_link_args = [ trace_protocol = get_option('trace_protocol') probe_swlink_args += [f'-DSWO_ENCODING=@trace_protocol@'] -probe_swlink_dependencies = [] +probe_swlink_dependencies = [platform_stm32_swo] if trace_protocol in ['1', '3'] probe_swlink_dependencies += platform_stm32_swo_manchester endif From 97529a27215bf3661847b0cc3efd1c6ba4edb089 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 15:20:51 +0100 Subject: [PATCH 43/48] f072: Handle the missing atomics needed for SWO via `libatomic` --- src/platforms/f072/Makefile.inc | 1 + src/platforms/f072/atomic.c | 166 ++++++++++++++++++++++++++++++++ src/platforms/f072/meson.build | 14 ++- 3 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 src/platforms/f072/atomic.c diff --git a/src/platforms/f072/Makefile.inc b/src/platforms/f072/Makefile.inc index 846d1fc6998..9878e486559 100644 --- a/src/platforms/f072/Makefile.inc +++ b/src/platforms/f072/Makefile.inc @@ -15,6 +15,7 @@ VPATH += platforms/common/stm32 SRC += \ platform.c \ + atomic.c \ serialno.c \ timing.c \ timing_stm32.c \ diff --git a/src/platforms/f072/atomic.c b/src/platforms/f072/atomic.c new file mode 100644 index 00000000000..4b5e7621918 --- /dev/null +++ b/src/platforms/f072/atomic.c @@ -0,0 +1,166 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2024 1BitSquared + * Written by Rachel Mant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements the libatomic special functions that are otherwise missing + * for this platform. libatomic itself is not included in most compiler distributions + * for arm-none-eabi, so we implement our own for sanity. + */ + +#include +#include +#include + +#include + +/* Use a sequential consistency barrier on Cortex-M0 (no special-case for relaxed or aquire-release */ +__attribute__((always_inline, artificial)) static inline void pre_barrier(int model) +{ + (void)model; + __atomic_thread_fence(__ATOMIC_SEQ_CST); +} + +__attribute__((always_inline, artificial)) static inline void post_barrier(int model) +{ + (void)model; + __atomic_thread_fence(__ATOMIC_SEQ_CST); +} + +/* Sequence barriers only issue a fence in sequential consistency mode */ +__attribute__((always_inline, artificial)) static inline void pre_seq_barrier(int model) +{ + if (model == __ATOMIC_SEQ_CST) + __atomic_thread_fence(model); +} + +__attribute__((always_inline, artificial)) static inline void post_seq_barrier(int model) +{ + if (model == __ATOMIC_SEQ_CST) + __atomic_thread_fence(model); +} + +/* Begin a protected block (disables interrupts) */ +__attribute__((always_inline, artificial)) static inline uint32_t protect_begin(const void *const ptr) +{ + (void)ptr; + const uint32_t primask = cm_is_masked_interrupts() ? 1U : 0U; + cm_disable_interrupts(); + return primask; +} + +/* End a protected block (re-enables interrupts if they were enabled at the start of the critical section */ +__attribute__((always_inline, artificial)) static inline void protect_end(const void *const ptr, uint32_t primask) +{ + (void)ptr; + if (primask == 0U) + cm_enable_interrupts(); +} + +uint16_t atomic_fetch_add_2(uint16_t *const atomic_value, const uint16_t add_value, const int model) +{ + /* Create a model-appropriate sync barrier to start */ + pre_barrier(model); + /* Now grab the current value of the atomic to be modified */ + uint16_t new_value; + uint16_t current_value = *atomic_value; + /* Try, in a loop, doing the addition to the value */ + do { + new_value = current_value + add_value; + /* + * Try to replace the value store by the atomic by the updated value computed here - if this fails + * then we get the new value returned in current_value and can try again. + */ + } while (!atomic_compare_exchange_weak_explicit( + atomic_value, ¤t_value, new_value, memory_order_relaxed, memory_order_relaxed)); + /* Create a model-appropriate sync barrier to finish */ + post_barrier(model); + /* Finally, return the value that was in the atomic to complete the operation's contract */ + return current_value; +} + +uint16_t atomic_fetch_sub_2(uint16_t *const atomic_value, const uint16_t sub_value, const int model) +{ + /* Create a model-appropriate sync barrier to start */ + pre_barrier(model); + /* Now grab the current value of the atomic to be modified */ + uint16_t new_value; + uint16_t current_value = *atomic_value; + /* Try, in a loop, doing the addition to the value */ + do { + new_value = current_value - sub_value; + /* + * Try to replace the value store by the atomic by the updated value computed here - if this fails + * then we get the new value returned in current_value and can try again. + */ + } while (!atomic_compare_exchange_weak_explicit( + atomic_value, ¤t_value, new_value, memory_order_relaxed, memory_order_relaxed)); + /* Create a model-appropriate sync barrier to finish */ + post_barrier(model); + /* Finally, return the value that was in the atomic to complete the operation's contract */ + return current_value; +} + +bool atomic_compare_exchange_2(uint16_t *const atomic_value, uint16_t *const expected_value, const uint16_t new_value, + const bool weak, const int success_model, const int failure_model) +{ + (void)weak; + (void)failure_model; + /* Create a model-appropriate sequence barrier to start, and begin a protected block */ + pre_seq_barrier(success_model); + const uint32_t protect_state = protect_begin(atomic_value); + + /* Read out the current value of the atomic, compare it to the expected */ + const uint16_t old_value = *atomic_value; + const bool result = old_value == *expected_value; + /* If it's the expected value, write the new value to complete the RMW cycle */ + if (result) + *atomic_value = new_value; + /* Otherwise, uphold the contract required and write the current value to the expected value pointer */ + else + *expected_value = old_value; + + /* Finish up with a model-appropriate sequence barrier having ended the protected block */ + protect_end(atomic_value, protect_state); + post_seq_barrier(success_model); + return result; +} + +/* Alias the functions defined to their special names to satisfy the compiler */ +/* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) */ +uint16_t __atomic_fetch_add_2(volatile void *atomic_value, uint16_t add_value, int swap_model) + __attribute__((alias("atomic_fetch_add_2"))); +uint16_t __atomic_fetch_sub_2(volatile void *atomic_value, uint16_t add_value, int swap_model) + __attribute__((alias("atomic_fetch_sub_2"))); +bool __atomic_compare_exchange_2(volatile void *atomic_value, void *expected_value, uint16_t new_value, bool weak, + int success_model, int failure_model) __attribute__((alias("atomic_compare_exchange_2"))); +/* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) */ diff --git a/src/platforms/f072/meson.build b/src/platforms/f072/meson.build index 1e4669b8c46..8a534255c5e 100644 --- a/src/platforms/f072/meson.build +++ b/src/platforms/f072/meson.build @@ -30,7 +30,10 @@ probe_f072_includes = include_directories('.') -probe_f072_sources = files('platform.c') +probe_f072_sources = files( + 'platform.c', + 'atomic.c', +) probe_f072_args = [ '-DDFU_SERIAL_LENGTH=13', @@ -41,12 +44,19 @@ probe_f072_link_args = [ '-T@0@'.format('stm32f07xzb.ld'), ] +probe_f072_dependencies = [ + platform_common, + platform_stm32f0, + platform_stm32_swo, + platform_stm32_swo_manchester, +] + probe_host = declare_dependency( include_directories: probe_f072_includes, sources: probe_f072_sources, compile_args: probe_f072_args, link_args: probe_f072_link_args, - dependencies: [platform_common, platform_stm32f0, platform_stm32_swo, platform_stm32_swo_manchester], + dependencies: probe_f072_dependencies, ) summary( From 25258af0403786039d73e5eaee0b697036c8ade2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 18:54:22 +0100 Subject: [PATCH 44/48] common/stm32/swo_uart: Moved the baudrate checking and sanity code into `swo_init()` --- src/platforms/common/stm32/swo.c | 3 ++- src/platforms/common/stm32/swo_uart.c | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/platforms/common/stm32/swo.c b/src/platforms/common/stm32/swo.c index 7b5c071b4f8..8b32a52f510 100644 --- a/src/platforms/common/stm32/swo.c +++ b/src/platforms/common/stm32/swo.c @@ -94,7 +94,8 @@ void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32 #endif #if SWO_ENCODING == 2 || SWO_ENCODING == 3 if (swo_mode == swo_nrz_uart) { - swo_uart_init(baudrate); + /* Ensure the baud rate is something sensible */ + swo_uart_init(baudrate ? baudrate : SWO_DEFAULT_BAUD); gdb_outf("Baudrate: %" PRIu32 " ", swo_uart_get_baudrate()); } #endif diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 586d01a2851..7230418536c 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -55,12 +55,8 @@ #define DMA_PL_HIGH DMA_CCR_PL_HIGH #endif -void swo_uart_init(uint32_t baudrate) +void swo_uart_init(const uint32_t baudrate) { - /* First, make sure the baud rate is something sensible */ - if (!baudrate) - baudrate = SWO_DEFAULT_BAUD; - /* Ensure required peripherals are spun up */ /* TODO: Move this into platform_init()! */ rcc_periph_clock_enable(SWO_UART_CLK); From 4088295cba927e17fbd327ff56903fb0ecbf3bd8 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 17 Sep 2024 20:58:37 +0100 Subject: [PATCH 45/48] common/tm4c/swo_uart: Sorted out the initialisation and deinitialisation logic --- src/platforms/common/tm4c/swo_uart.c | 58 +++++++++++++++---------- src/platforms/launchpad-icdi/platform.h | 26 ++++++----- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/platforms/common/tm4c/swo_uart.c b/src/platforms/common/tm4c/swo_uart.c index a19be476e91..1fe72b6a962 100644 --- a/src/platforms/common/tm4c/swo_uart.c +++ b/src/platforms/common/tm4c/swo_uart.c @@ -20,7 +20,8 @@ * along with this program. If not, see . */ -/* This file implements capture of the TRACESWO output. +/* + * This file implements capture of the Trace/SWO output using async signalling. * * ARM DDI 0403D - ARMv7M Architecture Reference Manual * ARM DDI 0337I - Cortex-M3 Technical Reference Manual @@ -30,61 +31,70 @@ #include "general.h" #include "platform.h" #include "usb.h" +#include "swo.h" #include #include #include #include -#include -void swo_uart_init(void) +void swo_init(const swo_coding_e swo_mode, const uint32_t baudrate, const uint32_t itm_stream_bitmask) { + /* Neither mode switching nor ITM decoding is implemented on this platform (yet) */ + (void)swo_mode; + (void)itm_stream_bitmask; + + /* Ensure required peripherals are spun up */ + /* TODO: Move this into platform_init()! */ periph_clock_enable(RCC_GPIOD); periph_clock_enable(SWO_UART_CLK); __asm__("nop"); __asm__("nop"); __asm__("nop"); - gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); - gpio_set_af(SWO_PORT, 1, SWO_PIN); /* U2RX */ - - uart_disable(SWO_UART); + /* Reconfigure the GPIO over to UART mode */ + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); + gpio_set_af(SWO_UART_PORT, SWO_UART_PIN_AF, SWO_UART_RX_PIN); - /* Setup UART parameters. */ + /* Set up the UART for 8N1 at the requested baud rate */ uart_clock_from_sysclk(SWO_UART); - uart_set_baudrate(SWO_UART, 800000); - uart_set_databits(SWO_UART, 8); - uart_set_stopbits(SWO_UART, 1); + uart_set_baudrate(SWO_UART, baudrate); + uart_set_databits(SWO_UART, 8U); + uart_set_stopbits(SWO_UART, 1U); uart_set_parity(SWO_UART, UART_PARITY_NONE); - // Enable FIFO + /* Make use of the hardware FIFO for some additional buffering (up to 8 bytes) */ uart_enable_fifo(SWO_UART); - // Set FIFO interrupt trigger levels to 4/8 full for RX buffer and - // 7/8 empty (1/8 full) for TX buffer + /* Configure the FIFO interrupts for ½ full (RX) and ⅞ empty (TX) */ uart_set_fifo_trigger_levels(SWO_UART, UART_FIFO_RX_TRIG_1_2, UART_FIFO_TX_TRIG_7_8); + /* Clear and enable the RX and RX timeout interrupts */ uart_clear_interrupt_flag(SWO_UART, UART_INT_RX | UART_INT_RT); - - /* Enable interrupts */ uart_enable_interrupts(SWO_UART, UART_INT_RX | UART_INT_RT); - /* Finally enable the USART. */ - uart_enable(SWO_UART); - - nvic_set_priority(SWO_UART_IRQ, 0); + /* Actually enable the interrupts */ + nvic_set_priority(SWO_UART_IRQ, IRQ_PRI_SWO_UART); nvic_enable_irq(SWO_UART_IRQ); /* Un-stall USB endpoint */ - usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, 0); + usbd_ep_stall_set(usbdev, USB_REQ_TYPE_IN | SWO_ENDPOINT, 0U); + + /* Finally enable the USART. */ + uart_enable(SWO_UART); + /* XXX: What is this even reconfiguring?! */ gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3); } -void traceswo_baud(unsigned int baud) +void swo_deinit(const bool deallocate) { - uart_set_baudrate(SWO_UART, baud); - uart_set_databits(SWO_UART, 8); + (void)deallocate; + /* Disable the UART */ + uart_disable(SWO_UART); + /* Put the GPIO back into normal service as a GPIO */ + gpio_mode_setup(SWO_UART_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_UART_RX_PIN); + gpio_set_af(SWO_UART_PORT, 0U, SWO_UART_RX_PIN); } uint32_t swo_uart_get_baudrate(void) diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index ff26f8d1530..84fb1d73b91 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -30,19 +30,19 @@ extern uint8_t running_status; -#define TMS_PORT GPIOA_BASE +#define TMS_PORT GPIOA #define TMS_PIN GPIO3 -#define TCK_PORT GPIOA_BASE +#define TCK_PORT GPIOA #define TCK_PIN GPIO2 -#define TDI_PORT GPIOA_BASE +#define TDI_PORT GPIOA #define TDI_PIN GPIO5 -#define TDO_PORT GPIOA_BASE +#define TDO_PORT GPIOA #define TDO_PIN GPIO4 -#define SWO_PORT GPIOD_BASE +#define SWO_PORT GPIOD #define SWO_PIN GPIO6 #define SWDIO_PORT TMS_PORT @@ -51,7 +51,7 @@ extern uint8_t running_status; #define SWCLK_PORT TCK_PORT #define SWCLK_PIN TCK_PIN -#define NRST_PORT GPIOA_BASE +#define NRST_PORT GPIOA #define NRST_PIN GPIO6 #define TMS_SET_MODE() \ @@ -75,7 +75,8 @@ extern uint8_t running_status; #define USB_IRQ NVIC_USB0_IRQ #define USB_ISR usb0_isr -#define IRQ_PRI_USB (2 << 4) +#define IRQ_PRI_USB (2U << 4U) +#define IRQ_PRI_SWO_UART (0U << 4U) #define USBUART UART0 #define USBUART_CLK RCC_UART0 @@ -92,10 +93,13 @@ extern uint8_t running_status; gpio_mode_setup(GPIOA_BASE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); \ } while (0) -#define SWO_UART UART2 -#define SWO_UART_CLK RCC_UART2 -#define SWO_UART_IRQ NVIC_UART2_IRQ -#define SWO_UART_ISR uart2_isr +#define SWO_UART UART2 +#define SWO_UART_CLK RCC_UART2 +#define SWO_UART_PORT GPIOD +#define SWO_UART_RX_PIN GPIO6 +#define SWO_UART_PIN_AF 1U +#define SWO_UART_IRQ NVIC_UART2_IRQ +#define SWO_UART_ISR(x) uart2_isr(x) #define SET_RUN_STATE(state) \ { \ From f3b75494d9bdef3149bd90871a764855a67b76e4 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 22 Sep 2024 02:37:02 +0100 Subject: [PATCH 46/48] common/blackpill-f4: The CCR's become swapped when the input is on channel 2, adjust for that --- src/platforms/common/blackpill-f4/blackpill-f4.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.h b/src/platforms/common/blackpill-f4/blackpill-f4.h index a03265d8dea..9745755981d 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.h +++ b/src/platforms/common/blackpill-f4/blackpill-f4.h @@ -295,13 +295,13 @@ extern bool debug_bmp; #define SWO_TIM_IRQ NVIC_TIM4_IRQ #define SWO_TIM_ISR(x) tim4_isr(x) #define SWO_IC_IN PINOUT_SWITCH(TIM_IC_IN_TI2, TIM_IC_IN_TI1) -#define SWO_IC_RISING TIM_IC1 -#define SWO_CC_RISING TIM4_CCR1 -#define SWO_ITR_RISING TIM_DIER_CC1IE -#define SWO_STATUS_RISING TIM_SR_CC1IF -#define SWO_IC_FALLING TIM_IC2 -#define SWO_CC_FALLING TIM4_CCR2 -#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_IC_RISING PINOUT_SWITCH(TIM_IC2, TIM_IC1) +#define SWO_CC_RISING PINOUT_SWITCH(TIM4_CCR2, TIM4_CCR1) +#define SWO_ITR_RISING PINOUT_SWITCH(TIM_DIER_CC2IE, TIM_DIER_CC1IE) +#define SWO_STATUS_RISING PINOUT_SWITCH(TIM_SR_CC2IF, TIM_SR_CC1IF) +#define SWO_IC_FALLING PINOUT_SWITCH(TIM_IC1, TIM_IC2) +#define SWO_CC_FALLING PINOUT_SWITCH(TIM4_CCR1, TIM4_CCR2) +#define SWO_STATUS_FALLING PINOUT_SWITCH(TIM_SR_CC1IF, TIM_SR_CC2IF) #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN PINOUT_SWITCH(TIM_SMCR_TS_TI2FP2, TIM_SMCR_TS_TI1FP1) #define SWO_TIM_PIN_AF GPIO_AF2 From 4c6bd0c6092a001d01dd6cb2e31ef52cae7b9c6d Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 22 Sep 2024 02:37:58 +0100 Subject: [PATCH 47/48] ctxlink/platform: The CCR's become swapped when the input is on channel 2, adjust for that --- src/platforms/ctxlink/platform.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platforms/ctxlink/platform.h b/src/platforms/ctxlink/platform.h index 6ae7d6e92a4..c689f75e3c1 100644 --- a/src/platforms/ctxlink/platform.h +++ b/src/platforms/ctxlink/platform.h @@ -189,13 +189,13 @@ #define SWO_TIM_IRQ NVIC_TIM3_IRQ #define SWO_TIM_ISR(x) tim3_isr(x) #define SWO_IC_IN TIM_IC_IN_TI2 -#define SWO_IC_RISING TIM_IC1 -#define SWO_CC_RISING TIM3_CCR1 -#define SWO_ITR_RISING TIM_DIER_CC1IE -#define SWO_STATUS_RISING TIM_SR_CC1IF -#define SWO_IC_FALLING TIM_IC2 -#define SWO_CC_FALLING TIM3_CCR2 -#define SWO_STATUS_FALLING TIM_SR_CC2IF +#define SWO_IC_RISING TIM_IC2 +#define SWO_CC_RISING TIM3_CCR2 +#define SWO_ITR_RISING TIM_DIER_CC2IE +#define SWO_STATUS_RISING TIM_SR_CC2IF +#define SWO_IC_FALLING TIM_IC1 +#define SWO_CC_FALLING TIM3_CCR1 +#define SWO_STATUS_FALLING TIM_SR_CC1IF #define SWO_STATUS_OVERFLOW (TIM_SR_CC1OF | TIM_SR_CC2OF) #define SWO_TRIG_IN TIM_SMCR_TS_TI2FP2 #define SWO_TIM_PIN_AF GPIO_AF2 From 7ce749ebb0ab003efead750ff4b67f72d9539ddc Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 22 Sep 2024 02:41:07 +0100 Subject: [PATCH 48/48] common/stm32/swo_uart: Cleaned up the copyright notice and corrected the top of file comments, including the docs references --- src/platforms/common/stm32/swo_manchester.c | 2 +- src/platforms/common/stm32/swo_uart.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/platforms/common/stm32/swo_manchester.c b/src/platforms/common/stm32/swo_manchester.c index aaebee4fe79..61c71f8a1f8 100644 --- a/src/platforms/common/stm32/swo_manchester.c +++ b/src/platforms/common/stm32/swo_manchester.c @@ -22,7 +22,7 @@ */ /* - * This file implements capture of Machester SWO trace output + * This file implements recovery and capture of Machester encoded SWO trace output * * References: * DDI0403 - ARMv7-M Architecture Reference Manual, version E.e diff --git a/src/platforms/common/stm32/swo_uart.c b/src/platforms/common/stm32/swo_uart.c index 7230418536c..44c64743267 100644 --- a/src/platforms/common/stm32/swo_uart.c +++ b/src/platforms/common/stm32/swo_uart.c @@ -3,6 +3,8 @@ * * Based on work that is Copyright (C) 2017 Black Sphere Technologies Ltd. * Copyright (C) 2017 Dave Marples + * Copyright (C) 2024 1BitSquared + * Modified by Rachel Mant * * 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 @@ -19,15 +21,17 @@ */ /* - * This file implements capture of the Trace/SWO output using async signalling. + * This file implements recovery and capture of UART/NRZ encoded SWO trace output * - * ARM DDI 0403D - ARMv7M Architecture Reference Manual - * ARM DDI 0337I - Cortex-M3 Technical Reference Manual - * ARM DDI 0314H - CoreSight Components Technical Reference Manual + * References: + * DDI0403 - ARMv7-M Architecture Reference Manual, version E.e + * - https://developer.arm.com/documentation/ddi0403/latest/ + * DDI0314 - CoreSight Components Technical Reference Manual, version 1.0, rev. H + * - https://developer.arm.com/documentation/ddi0314/latest/ + * + * We use a hardware UART to capture and recover the data, and DMA to buffer it. */ -/* TDO/TRACESWO signal comes into the SWOUSART RX pin. */ - #include "general.h" #include "platform.h" #include "usb.h"