Skip to content

Commit 7ea76e0

Browse files
committed
atmel-samd: Pin reset improvements.
* Reset SWD lines to SWD rather than GPIO. This makes OpenOCD happier. * Default speaker enable lines to False for CircuitPlayground to prevent the speaker from buzzing when no sound is playing. Fixes #126
1 parent 6984425 commit 7ea76e0

File tree

4 files changed

+84
-13
lines changed

4 files changed

+84
-13
lines changed

atmel-samd/boards/circuitplayground_express/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25)
3131
#define MICROPY_PORT_B (PORT_PB22)
3232

33+
#define SPEAKER_ENABLE_PIN (&pin_PA30)
34+
3335
#define AUTORESET_DELAY_MS 500
3436

3537
#include "spi_flash.h"

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

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
#include "shared-bindings/microcontroller/Pin.h"
2828

29+
#include "asf/sam0/drivers/port/port.h"
30+
2931
#include "rgb_led_status.h"
3032
#include "samd21_pins.h"
3133

@@ -36,6 +38,47 @@ bool neopixel_in_use;
3638
bool apa102_sck_in_use;
3739
bool apa102_mosi_in_use;
3840
#endif
41+
#ifdef SPEAKER_ENABLE_PIN
42+
bool speaker_enable_in_use;
43+
#endif
44+
45+
void reset_all_pins(void) {
46+
struct system_pinmux_config config;
47+
system_pinmux_get_config_defaults(&config);
48+
config.powersave = true;
49+
50+
uint32_t pin_mask[2] = PORT_OUT_IMPLEMENTED;
51+
52+
// Do not full reset USB or SWD lines.
53+
pin_mask[0] &= ~(PIN_PA24 | PIN_PA25 | PIN_PA30 | PIN_PA31);
54+
55+
system_pinmux_group_set_config(&(PORT->Group[0]), pin_mask[0] & ~MICROPY_PORT_A, &config);
56+
system_pinmux_group_set_config(&(PORT->Group[1]), pin_mask[1] & ~MICROPY_PORT_B, &config);
57+
58+
// Configure SWD
59+
system_pinmux_get_config_defaults(&config);
60+
config.mux_position = 0x6;
61+
system_pinmux_group_set_config(&(PORT->Group[0]), PIN_PA30 | PIN_PA31, &config);
62+
63+
#ifdef MICROPY_HW_NEOPIXEL
64+
neopixel_in_use = false;
65+
#endif
66+
#ifdef MICROPY_HW_APA102_MOSI
67+
apa102_sck_in_use = false;
68+
apa102_mosi_in_use = false;
69+
#endif
70+
71+
// After configuring SWD because it may be shared.
72+
#ifdef SPEAKER_ENABLE_PIN
73+
speaker_enable_in_use = false;
74+
struct port_config pin_conf;
75+
port_get_config_defaults(&pin_conf);
76+
77+
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
78+
port_pin_set_config(SPEAKER_ENABLE_PIN->pin, &pin_conf);
79+
port_pin_set_output_level(SPEAKER_ENABLE_PIN->pin, false);
80+
#endif
81+
}
3982

4083
void reset_pin(uint8_t pin) {
4184
if (pin >= PORT_BITS) {
@@ -63,8 +106,24 @@ void reset_pin(uint8_t pin) {
63106

64107
struct system_pinmux_config config;
65108
system_pinmux_get_config_defaults(&config);
66-
config.powersave = true;
109+
if (pin == PIN_PA30 || pin == PIN_PA31) {
110+
config.mux_position = 0x6;
111+
} else {
112+
config.powersave = true;
113+
}
67114
system_pinmux_pin_set_config(pin, &config);
115+
116+
#ifdef SPEAKER_ENABLE_PIN
117+
if (pin == SPEAKER_ENABLE_PIN->pin) {
118+
speaker_enable_in_use = false;
119+
struct port_config pin_conf;
120+
port_get_config_defaults(&pin_conf);
121+
122+
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
123+
port_pin_set_config(SPEAKER_ENABLE_PIN->pin, &pin_conf);
124+
port_pin_set_output_level(SPEAKER_ENABLE_PIN->pin, false);
125+
}
126+
#endif
68127
}
69128

70129
void claim_pin(const mcu_pin_obj_t* pin) {
@@ -81,6 +140,12 @@ void claim_pin(const mcu_pin_obj_t* pin) {
81140
apa102_sck_in_use = true;
82141
}
83142
#endif
143+
144+
#ifdef SPEAKER_ENABLE_PIN
145+
if (pin == SPEAKER_ENABLE_PIN) {
146+
speaker_enable_in_use = true;
147+
}
148+
#endif
84149
}
85150

86151
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) {
@@ -98,10 +163,21 @@ bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) {
98163
}
99164
#endif
100165

166+
#ifdef SPEAKER_ENABLE_PIN
167+
if (pin == SPEAKER_ENABLE_PIN) {
168+
return !speaker_enable_in_use;
169+
}
170+
#endif
171+
101172
PortGroup *const port = system_pinmux_get_group_from_gpio_pin(pin->pin);
102173
uint32_t pin_index = (pin->pin);
103-
PORT_PINCFG_Type state = port->PINCFG[pin_index];
174+
volatile PORT_PINCFG_Type *state = &port->PINCFG[pin_index];
175+
volatile PORT_PMUX_Type *pmux = &port->PMUX[pin_index / 2];
176+
177+
if (pin->pin == PIN_PA30 || pin->pin == PIN_PA31) {
178+
return state->bit.PMUXEN == 1 && ((pmux->reg >> (4 * pin_index % 2)) & 0xf) == 0x6;
179+
}
104180

105-
return state.bit.PMUXEN == 0 && state.bit.INEN == 0 &&
106-
state.bit.PULLEN == 0 && (port->DIR.reg & (1 << pin_index)) == 0;
181+
return state->bit.PMUXEN == 0 && state->bit.INEN == 0 &&
182+
state->bit.PULLEN == 0 && (port->DIR.reg & (1 << pin_index)) == 0;
107183
}

atmel-samd/common-hal/microcontroller/Pin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ extern bool apa102_sck_in_use;
7878
extern bool apa102_mosi_in_use;
7979
#endif
8080

81+
void reset_all_pins(void);
8182
// reset_pin takes the pin number instead of the pointer so that objects don't
8283
// need to store a full pointer.
8384
void reset_pin(uint8_t pin);

atmel-samd/main.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,7 @@ void reset_samd21(void) {
172172
while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {}
173173
DAC->CTRLA.reg |= DAC_CTRLA_SWRST;
174174

175-
// Reset pins
176-
struct system_pinmux_config config;
177-
system_pinmux_get_config_defaults(&config);
178-
config.powersave = true;
179-
180-
uint32_t pin_mask[2] = PORT_OUT_IMPLEMENTED;
181-
182-
system_pinmux_group_set_config(&(PORT->Group[0]), pin_mask[0] & ~MICROPY_PORT_A, &config);
183-
system_pinmux_group_set_config(&(PORT->Group[1]), pin_mask[1] & ~MICROPY_PORT_B, &config);
175+
reset_all_pins();
184176

185177
audioout_reset();
186178
pwmout_reset();

0 commit comments

Comments
 (0)