swd: provide function to set SWCLK/SWDIO pin
This commit is contained in:
parent
6b3b55839e
commit
0010c5e046
106
lib/swd.c
106
lib/swd.c
@ -52,16 +52,9 @@ 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(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 GPIO
|
||||
swd_set_pins(swd_swclk_port, swd_swclk_pin, swd_swdio_port, swd_swdio_pin);
|
||||
|
||||
// setup timer to generate periodic clock
|
||||
rcc_periph_clock_enable(RCC_TIM(SWD_TIMER)); // enable clock for timer peripheral
|
||||
rcc_periph_reset_pulse(RST_TIM(SWD_TIMER)); // reset timer state
|
||||
@ -84,6 +77,14 @@ void swd_setup(uint32_t freq)
|
||||
swd_bits_count = 0;
|
||||
}
|
||||
|
||||
/** release used pins */
|
||||
static void swd_release_pins(void)
|
||||
{
|
||||
// release GPIO
|
||||
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
|
||||
}
|
||||
|
||||
void swd_release(void)
|
||||
{
|
||||
// release timer
|
||||
@ -91,9 +92,88 @@ void swd_release(void)
|
||||
rcc_periph_reset_pulse(RST_TIM(SWD_TIMER)); // reset timer state
|
||||
rcc_periph_clock_disable(RCC_TIM(SWD_TIMER)); // disable clock for timer peripheral
|
||||
|
||||
// release GPIO
|
||||
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
|
||||
swd_release_pins(); // release GPIO
|
||||
}
|
||||
|
||||
bool swd_set_pins(uint32_t swclk_port, uint32_t swclk_pin, uint32_t swdio_port, uint32_t swdio_pin)
|
||||
{
|
||||
if (swclk_pin > (1 << 15) || swdio_pin > (1 << 15) || __builtin_popcount(swclk_pin) != 1 || __builtin_popcount(swdio_pin) != 1) { // check if pin exists and is unique
|
||||
return false;
|
||||
}
|
||||
uint32_t swclk_rcc = 0;
|
||||
switch (swclk_port) {
|
||||
case GPIOA:
|
||||
swclk_rcc = RCC_GPIOA;
|
||||
break;
|
||||
case GPIOB:
|
||||
swclk_rcc = RCC_GPIOB;
|
||||
break;
|
||||
case GPIOC:
|
||||
swclk_rcc = RCC_GPIOC;
|
||||
break;
|
||||
case GPIOD:
|
||||
swclk_rcc = RCC_GPIOD;
|
||||
break;
|
||||
case GPIOE:
|
||||
swclk_rcc = RCC_GPIOE;
|
||||
break;
|
||||
case GPIOF:
|
||||
swclk_rcc = RCC_GPIOF;
|
||||
break;
|
||||
case GPIOG:
|
||||
swclk_rcc = RCC_GPIOG;
|
||||
break;
|
||||
default: // unknown port
|
||||
return false;
|
||||
}
|
||||
uint32_t swdio_rcc = 0;
|
||||
switch (swdio_port) {
|
||||
case GPIOA:
|
||||
swdio_rcc = RCC_GPIOA;
|
||||
break;
|
||||
case GPIOB:
|
||||
swdio_rcc = RCC_GPIOB;
|
||||
break;
|
||||
case GPIOC:
|
||||
swdio_rcc = RCC_GPIOC;
|
||||
break;
|
||||
case GPIOD:
|
||||
swdio_rcc = RCC_GPIOD;
|
||||
break;
|
||||
case GPIOE:
|
||||
swdio_rcc = RCC_GPIOE;
|
||||
break;
|
||||
case GPIOF:
|
||||
swdio_rcc = RCC_GPIOF;
|
||||
break;
|
||||
case GPIOG:
|
||||
swdio_rcc = RCC_GPIOG;
|
||||
break;
|
||||
default: // unknown port
|
||||
return false;
|
||||
}
|
||||
|
||||
swd_release_pins(); // release already set pins (not a problem even if not already used
|
||||
|
||||
// remember pins
|
||||
swd_swclk_rcc = swclk_rcc;
|
||||
swd_swclk_port = swclk_port;
|
||||
swd_swclk_pin = swclk_pin;
|
||||
swd_swdio_rcc = swdio_rcc;
|
||||
swd_swdio_port = swdio_port;
|
||||
swd_swdio_pin = swdio_pin;
|
||||
|
||||
// setup GPIO for clock and data signals
|
||||
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
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** perform SWD transaction (one sequence of bits read or write)
|
||||
|
@ -90,6 +90,14 @@ void swd_setup(uint32_t freq);
|
||||
/** release 1-wire peripheral
|
||||
*/
|
||||
void swd_release(void);
|
||||
/** set SWCLK and SWDIO pins
|
||||
* @param[in] swclk_port port for SWCLK pin
|
||||
* @param[in] swclk_pin pin for SWCLK pin
|
||||
* @param[in] swclk_port port for SWDIO pin
|
||||
* @param[in] swclk_pin pin for SWDIO pin
|
||||
* @return true if operation succeeded, false if pin is unknown
|
||||
*/
|
||||
bool swd_set_pins(uint32_t swclk_port, uint32_t swclk_pin, uint32_t swdio_port, uint32_t swdio_pin);
|
||||
|
||||
/* DPv1/SWDv1 operations */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user