Skip to content

Commit 634791a

Browse files
authored
Merge pull request #1647 from tannewt/swd_pin_reuse
Fix custom pin in use logic for SWD
2 parents 74083da + ff7e729 commit 634791a

File tree

1 file changed

+35
-11
lines changed
  • ports/atmel-samd/common-hal/microcontroller

1 file changed

+35
-11
lines changed

ports/atmel-samd/common-hal/microcontroller/Pin.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,25 @@ bool speaker_enable_in_use;
4545

4646
#define PORT_COUNT (PORT_BITS / 32 + 1)
4747

48+
#ifdef SAMD51
49+
#define SWD_MUX GPIO_PIN_FUNCTION_H
50+
#endif
51+
#ifdef SAMD21
52+
#define SWD_MUX GPIO_PIN_FUNCTION_G
53+
#endif
54+
4855
STATIC uint32_t never_reset_pins[PORT_COUNT];
4956

5057
void reset_all_pins(void) {
5158
uint32_t pin_mask[PORT_COUNT] = PORT_OUT_IMPLEMENTED;
5259

53-
// Do not full reset USB or SWD lines.
54-
pin_mask[0] &= ~(PORT_PA24 | PORT_PA25 | PORT_PA30 | PORT_PA31);
60+
// Do not full reset USB lines.
61+
pin_mask[0] &= ~(PORT_PA24 | PORT_PA25);
62+
63+
// Do not reset SWD when a debugger is present.
64+
if (DSU->STATUSB.bit.DBGPRES == 1) {
65+
pin_mask[0] &= ~(PORT_PA30 | PORT_PA31);
66+
}
5567

5668
for (uint32_t i = 0; i < PORT_COUNT; i++) {
5769
pin_mask[i] &= ~never_reset_pins[i];
@@ -66,16 +78,14 @@ void reset_all_pins(void) {
6678
gpio_set_port_direction(GPIO_PORTD, pin_mask[3] & ~MICROPY_PORT_D, GPIO_DIRECTION_OFF);
6779
#endif
6880

69-
// Configure SWD
81+
// Configure SWD. SWDIO will be automatically switched on PA31 when a signal is input on
82+
// SWCLK.
7083
#ifdef SAMD51
7184
gpio_set_pin_function(PIN_PA30, MUX_PA30H_CM4_SWCLK);
72-
// SWDIO will be automatically switched on PA31 when a signal is input on
73-
// SWCLK.
7485
#endif
7586
#ifdef SAMD21
76-
//gpio_set_pin_function(PIN_PA30, GPIO_PIN_FUNCTION_G);
77-
//gpio_set_pin_direction(PIN_PA31, GPIO_DIRECTION_OUT);
78-
//gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G);
87+
gpio_set_pin_function(PIN_PA30, GPIO_PIN_FUNCTION_G);
88+
gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G);
7989
#endif
8090

8191
#ifdef MICROPY_HW_NEOPIXEL
@@ -128,12 +138,11 @@ void reset_pin_number(uint8_t pin_number) {
128138
if (pin_number == PIN_PA30
129139
#ifdef SAMD51
130140
) {
131-
gpio_set_pin_function(pin_number, GPIO_PIN_FUNCTION_H);
132141
#endif
133142
#ifdef SAMD21
134143
|| pin_number == PIN_PA31) {
135-
gpio_set_pin_function(pin_number, GPIO_PIN_FUNCTION_G);
136144
#endif
145+
gpio_set_pin_function(pin_number, SWD_MUX);
137146
} else {
138147
gpio_set_pin_direction(pin_number, GPIO_DIRECTION_OFF);
139148
gpio_set_pin_function(pin_number, GPIO_PIN_FUNCTION_OFF);
@@ -178,7 +187,18 @@ bool pin_number_is_free(uint8_t pin_number) {
178187
volatile PORT_PMUX_Type *pmux = &port->PMUX[pin_index / 2];
179188

180189
if (pin_number == PIN_PA30 || pin_number == PIN_PA31) {
181-
return state->bit.PMUXEN == 1 && ((pmux->reg >> (4 * pin_index % 2)) & 0xf) == 0x6;
190+
if (DSU->STATUSB.bit.DBGPRES == 1) {
191+
return false;
192+
}
193+
if (pin_number == PIN_PA30
194+
#ifdef SAMD51
195+
) {
196+
#endif
197+
#ifdef SAMD21
198+
|| pin_number == PIN_PA31) {
199+
#endif) {
200+
return state->bit.PMUXEN == 1 && ((pmux->reg >> (4 * pin_index % 2)) & 0xf) == SWD_MUX;
201+
}
182202
}
183203

184204
return state->bit.PMUXEN == 0 && state->bit.INEN == 0 &&
@@ -188,6 +208,10 @@ bool pin_number_is_free(uint8_t pin_number) {
188208
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) {
189209
#ifdef MICROPY_HW_NEOPIXEL
190210
if (pin == MICROPY_HW_NEOPIXEL) {
211+
// Special case for Metro M0 where the NeoPixel is also SWCLK
212+
if (MICROPY_HW_NEOPIXEL == &pin_PA30 && DSU->STATUSB.bit.DBGPRES == 1) {
213+
return false;
214+
}
191215
return !neopixel_in_use;
192216
}
193217
#endif

0 commit comments

Comments
 (0)