swd: use variables for pins (for later dynamic change)

This commit is contained in:
King Kévin 2021-03-10 14:24:52 +01:00
parent db5e22a5b3
commit f4bb7a7fd8
1 changed files with 25 additions and 19 deletions

View File

@ -28,8 +28,14 @@
/** @defgroup swd_gpio GPIO used for SWDIO and SWCLK
* @{
*/
#define SWD_SWCLK_PIN PB10 /**< GPIO pin for clock signal */
#define SWD_SWDIO_PIN PB2 /**< GPIO pin for data input/output signal */
#define SWD_SWCLK_PIN PB10 /**< default GPIO pin for clock signal */
#define SWD_SWDIO_PIN PB2 /**< default GPIO pin for data input/output signal */
static uint32_t swd_swclk_rcc = GPIO_RCC(SWD_SWCLK_PIN);
static uint32_t swd_swclk_port = GPIO_PORT(SWD_SWCLK_PIN);
static uint32_t swd_swclk_pin = GPIO_PIN(SWD_SWCLK_PIN);
static uint32_t swd_swdio_rcc = GPIO_RCC(SWD_SWDIO_PIN);
static uint32_t swd_swdio_port = GPIO_PORT(SWD_SWDIO_PIN);
static uint32_t swd_swdio_pin = GPIO_PIN(SWD_SWDIO_PIN);
/** @} */
/** @defgroup swd_timer timer used to generate a periodic clock
@ -47,14 +53,14 @@ static volatile uint8_t swd_bits_i = 0; /** transaction bit index */
void swd_setup(uint32_t freq)
{
// setup GPIO for clock and data signals
rcc_periph_clock_enable(GPIO_RCC(SWD_SWCLK_PIN)); // enable clock for GPIO peripheral for clock signal
gpio_set(GPIO_PORT(SWD_SWCLK_PIN), GPIO_PIN(SWD_SWCLK_PIN)); // inactive clock is high
gpio_mode_setup(GPIO_PORT(SWD_SWCLK_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(SWD_SWCLK_PIN)); // the host controls the clock
gpio_set_output_options(GPIO_PORT(SWD_SWCLK_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN(SWD_SWCLK_PIN)); // set SWCLK pin output as push-pull
rcc_periph_clock_enable(GPIO_RCC(SWD_SWDIO_PIN)); // enable clock for GPIO peripheral for data signal
gpio_set(GPIO_PORT(SWD_SWDIO_PIN), GPIO_PIN(SWD_SWDIO_PIN)); // inactive data is high (resetting the target when clock is active)
gpio_mode_setup(GPIO_PORT(SWD_SWDIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(SWD_SWDIO_PIN)); // the data signal is half duplex, with the host controlling who is driving the data signal when
gpio_set_output_options(GPIO_PORT(SWD_SWDIO_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN(SWD_SWDIO_PIN)); // set SWDIO pin output as push-pull
rcc_periph_clock_enable(swd_swclk_rcc); // enable clock for GPIO peripheral for clock signal
gpio_set(swd_swclk_port, swd_swclk_pin); // inactive clock is high
gpio_mode_setup(swd_swclk_port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, swd_swclk_pin); // the host controls the clock
gpio_set_output_options(swd_swclk_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, swd_swclk_pin); // set SWCLK pin output as push-pull
rcc_periph_clock_enable(swd_swdio_rcc); // enable clock for GPIO peripheral for data signal
gpio_set(swd_swdio_port, swd_swdio_pin); // inactive data is high (resetting the target when clock is active)
gpio_mode_setup(swd_swdio_port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, swd_swdio_pin); // the data signal is half duplex, with the host controlling who is driving the data signal when
gpio_set_output_options(swd_swdio_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, swd_swdio_pin); // set SWDIO pin output as push-pull
// setup timer to generate periodic clock
rcc_periph_clock_enable(RCC_TIM(SWD_TIMER)); // enable clock for timer peripheral
@ -86,8 +92,8 @@ void swd_release(void)
rcc_periph_clock_disable(RCC_TIM(SWD_TIMER)); // disable clock for timer peripheral
// release GPIO
gpio_mode_setup(GPIO_PORT(SWD_SWCLK_PIN), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(SWD_SWCLK_PIN)); // put clock signal pin back to input floating
gpio_mode_setup(GPIO_PORT(SWD_SWDIO_PIN), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(SWD_SWDIO_PIN)); // put data signal pin back to input floating
gpio_mode_setup(swd_swclk_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, swd_swclk_pin); // put clock signal pin back to input floating
gpio_mode_setup(swd_swdio_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, swd_swdio_pin); // put data signal pin back to input floating
}
/** perform SWD transaction (one sequence of bits read or write)
@ -104,10 +110,10 @@ uint64_t swd_transaction(uint64_t output, uint8_t bit_count, bool write)
}
// initialize read/write
if (write) {
gpio_mode_setup(GPIO_PORT(SWD_SWDIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(SWD_SWDIO_PIN)); // we drive the data signal to output data
gpio_mode_setup(swd_swdio_port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, swd_swdio_pin); // we drive the data signal to output data
swd_bits_out = output; // set data to output
} else {
gpio_mode_setup(GPIO_PORT(SWD_SWDIO_PIN), GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN(SWD_SWDIO_PIN)); // the target will drive the data signal, we just pull it up
gpio_mode_setup(swd_swdio_port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, swd_swdio_pin); // the target will drive the data signal, we just pull it up
swd_bits_out = ~0ULL; // set the value so we pull up
}
swd_bits_in = 0; // reset input buffer
@ -303,19 +309,19 @@ void TIM_ISR(SWD_TIMER)(void)
}
if (edge_falling) { // falling edge: we output data
if (swd_bits_out & (1ULL << swd_bits_i)) { // output data, LSb first
gpio_set(GPIO_PORT(SWD_SWDIO_PIN), GPIO_PIN(SWD_SWDIO_PIN)); // output high
gpio_set(swd_swdio_port, swd_swdio_pin); // output high
} else {
gpio_clear(GPIO_PORT(SWD_SWDIO_PIN), GPIO_PIN(SWD_SWDIO_PIN)); // output low
gpio_clear(swd_swdio_port, swd_swdio_pin); // output low
}
gpio_clear(GPIO_PORT(SWD_SWCLK_PIN), GPIO_PIN(SWD_SWCLK_PIN)); // output falling clock edge
gpio_clear(swd_swclk_port, swd_swclk_pin); // output falling clock edge
} else { // rising edge: read data
if (gpio_get(GPIO_PORT(SWD_SWDIO_PIN), GPIO_PIN(SWD_SWDIO_PIN))) { // read data
if (gpio_get(swd_swdio_port, swd_swdio_pin)) { // read data
swd_bits_out |= (1ULL << swd_bits_i); // set bit
} else {
swd_bits_out &= ~(1ULL << swd_bits_i); // clear bit
}
swd_bits_i++;
gpio_set(GPIO_PORT(SWD_SWCLK_PIN), GPIO_PIN(SWD_SWCLK_PIN)); // output rising clock edge
gpio_set(swd_swclk_port, swd_swclk_pin); // output rising clock edge
}
edge_falling = !edge_falling; // remember opposite upcoming edge
} else { // no other interrupt should occur