Skip to content

Commit 886d225

Browse files
authored
Merge pull request #9385 from Bruin-Spacecraft-Group/main
SAMD51 SPI Secondary Mode
2 parents e5e7c9e + 3b0b4d3 commit 886d225

File tree

34 files changed

+632
-47
lines changed

34 files changed

+632
-47
lines changed

docs/porting.rst

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ as a natural "TODO" list. An example minimal build list is shown below:
7272
CIRCUITPY_FRAMEBUFFERIO = 0
7373
CIRCUITPY_FREQUENCYIO = 0
7474
CIRCUITPY_I2CTARGET = 0
75+
CIRCUITPY_SPITARGET = 0
7576
# Requires SPI, PulseIO (stub ok):
7677
CIRCUITPY_DISPLAYIO = 0
7778

locale/circuitpython.pot

+12-4
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,10 @@ msgstr ""
594594
msgid "Array values should be single bytes."
595595
msgstr ""
596596

597+
#: ports/atmel-samd/common-hal/spitarget/SPITarget.c
598+
msgid "Async SPI transfer in progress on this bus, keep awaiting."
599+
msgstr ""
600+
597601
#: shared-module/memorymonitor/AllocationAlarm.c
598602
#, c-format
599603
msgid "Attempt to allocate %d blocks"
@@ -1725,6 +1729,10 @@ msgstr ""
17251729
msgid "PWM slice channel A already in use"
17261730
msgstr ""
17271731

1732+
#: shared-bindings/spitarget/SPITarget.c
1733+
msgid "Packet buffers for an SPI transfer must have the same length."
1734+
msgstr ""
1735+
17281736
#: shared-module/jpegio/JpegDecoder.c
17291737
msgid "Parameter error"
17301738
msgstr ""
@@ -2017,8 +2025,8 @@ msgstr ""
20172025
msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30"
20182026
msgstr ""
20192027

2020-
#: shared-module/audiodelays/Echo.c shared-module/audiofilters/Filter.c
2021-
#: shared-module/audiomixer/MixerVoice.c
2028+
#: shared-module/audiodelays/Echo.c shared-module/audiofilters/Distortion.c
2029+
#: shared-module/audiofilters/Filter.c shared-module/audiomixer/MixerVoice.c
20222030
msgid "The sample's %q does not match"
20232031
msgstr ""
20242032

@@ -2570,8 +2578,8 @@ msgstr ""
25702578
msgid "bits must be 32 or less"
25712579
msgstr ""
25722580

2573-
#: shared-bindings/audiodelays/Echo.c shared-bindings/audiofilters/Filter.c
2574-
#: shared-bindings/audiomixer/Mixer.c
2581+
#: shared-bindings/audiodelays/Echo.c shared-bindings/audiofilters/Distortion.c
2582+
#: shared-bindings/audiofilters/Filter.c shared-bindings/audiomixer/Mixer.c
25752583
msgid "bits_per_sample must be 8 or 16"
25762584
msgstr ""
25772585

ports/atmel-samd/audio_dma.c

+2-23
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ static audio_dma_t *audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
3030
// This cannot be in audio_dma_state because it's volatile.
3131
static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT];
3232

33-
static bool audio_dma_allocated[AUDIO_DMA_CHANNEL_COUNT];
34-
3533
uint8_t find_sync_event_channel_raise() {
3634
uint8_t event_channel = find_sync_event_channel();
3735
if (event_channel >= EVSYS_SYNCH_NUM) {
@@ -40,24 +38,6 @@ uint8_t find_sync_event_channel_raise() {
4038
return event_channel;
4139
}
4240

43-
uint8_t dma_allocate_channel(void) {
44-
uint8_t channel;
45-
for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) {
46-
if (!audio_dma_allocated[channel]) {
47-
audio_dma_allocated[channel] = true;
48-
return channel;
49-
}
50-
}
51-
return channel; // i.e., return failure
52-
}
53-
54-
void dma_free_channel(uint8_t channel) {
55-
assert(channel < AUDIO_DMA_CHANNEL_COUNT);
56-
assert(audio_dma_allocated[channel]);
57-
audio_dma_disable_channel(channel);
58-
audio_dma_allocated[channel] = false;
59-
}
60-
6141
void audio_dma_disable_channel(uint8_t channel) {
6242
if (channel >= AUDIO_DMA_CHANNEL_COUNT) {
6343
return;
@@ -191,7 +171,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma,
191171
bool output_signed,
192172
uint32_t output_register_address,
193173
uint8_t dma_trigger_source) {
194-
uint8_t dma_channel = dma_allocate_channel();
174+
uint8_t dma_channel = dma_allocate_channel(true);
195175
if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) {
196176
return AUDIO_DMA_DMA_BUSY;
197177
}
@@ -342,8 +322,7 @@ void audio_dma_reset(void) {
342322
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
343323
audio_dma_state[i] = NULL;
344324
audio_dma_pending[i] = false;
345-
audio_dma_allocated[i] = false;
346-
audio_dma_disable_channel(i);
325+
dma_free_channel(i);
347326
dma_descriptor(i)->BTCTRL.bit.VALID = false;
348327
MP_STATE_PORT(playing_audio)[i] = NULL;
349328
}

ports/atmel-samd/audio_dma.h

-3
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ typedef enum {
4444
void audio_dma_init(audio_dma_t *dma);
4545
void audio_dma_reset(void);
4646

47-
uint8_t dma_allocate_channel(void);
48-
void dma_free_channel(uint8_t channel);
49-
5047
// This sets everything up but doesn't start the timer.
5148
// Sample is the python object for the sample to play.
5249
// loop is true if we should loop the sample.

ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ LONGINT_IMPL = MPZ
1212

1313
CIRCUITPY_PS2IO = 1
1414
CIRCUITPY_JPEGIO = 0
15+
CIRCUITPY_SPITARGET = 0
1516
CIRCUITPY_SYNTHIO = 0

ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q16JVxQ, W25Q16JVxM"
1111
LONGINT_IMPL = MPZ
1212
CIRCUITPY_SYNTHIO = 0
1313
CIRCUITPY_JPEGIO = 0
14+
CIRCUITPY_SPITARGET = 0

ports/atmel-samd/boards/pybadge/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CIRCUITPY_I2CDISPLAYBUS = 0
1818
CIRCUITPY_JPEGIO = 0
1919
CIRCUITPY_KEYPAD = 1
2020
CIRCUITPY_PARALLELDISPLAYBUS= 0
21+
CIRCUITPY_SPITARGET = 0
2122
CIRCUITPY_STAGE = 1
2223

2324
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge

ports/atmel-samd/boards/pygamer/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CIRCUITPY_I2CDISPLAYBUS = 0
1818
CIRCUITPY_JPEGIO = 0
1919
CIRCUITPY_KEYPAD = 1
2020
CIRCUITPY_PARALLELDISPLAYBUS= 0
21+
CIRCUITPY_SPITARGET = 0
2122
CIRCUITPY_STAGE = 1
2223

2324
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pygamer

ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ EXTERNAL_FLASH_DEVICES = GD25Q16C
1111
LONGINT_IMPL = MPZ
1212

1313
CIRCUITPY_JPEGIO = 0
14+
CIRCUITPY_SPITARGET = 0
1415
CIRCUITPY_SYNTHIO = 0

ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk

+1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ CHIP_FAMILY = samd51
99
QSPI_FLASH_FILESYSTEM = 1
1010
EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ"
1111
LONGINT_IMPL = MPZ
12+
CIRCUITPY_SPITARGET = 0
1213
CIRCUITPY_SYNTHIO = 0
1314
CIRCUITPY_JPEGIO = 0

ports/atmel-samd/common-hal/audiobusio/PDMIn.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) {
364364
// output_buffer_length is the number of slots, not the number of bytes.
365365
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self,
366366
uint16_t *output_buffer, uint32_t output_buffer_length) {
367-
uint8_t dma_channel = dma_allocate_channel();
367+
uint8_t dma_channel = dma_allocate_channel(true);
368368
pdmin_event_channel = find_sync_event_channel_raise();
369369
pdmin_dma_block_done = false;
370370

ports/atmel-samd/common-hal/busio/SPI.c

+16-13
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717

1818
#include "hal/include/hal_gpio.h"
1919
#include "hal/include/hal_spi_m_sync.h"
20-
#include "hal/include/hpl_spi_m_sync.h"
2120

2221
#include "samd/dma.h"
2322
#include "samd/sercom.h"
2423

24+
void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux);
25+
2526
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
2627
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
2728
const mcu_pin_obj_t *miso, bool half_duplex) {
@@ -76,6 +77,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
7677
if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) {
7778
continue;
7879
}
80+
// find mosi_pad first, since it corresponds to dopo which takes limited values
7981
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
8082
if (!mosi_none) {
8183
if (sercom_index == mosi->sercom[j].index) {
@@ -125,6 +127,8 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
125127

126128
// Pads must be set after spi_m_sync_init(), which uses default values from
127129
// the prototypical SERCOM.
130+
131+
hri_sercomspi_write_CTRLA_MODE_bf(sercom, 3);
128132
hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo);
129133
hri_sercomspi_write_CTRLA_DIPO_bf(sercom, miso_pad);
130134

@@ -137,30 +141,21 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
137141
mp_raise_OSError(MP_EIO);
138142
}
139143

140-
gpio_set_pin_direction(clock->number, GPIO_DIRECTION_OUT);
141-
gpio_set_pin_pull_mode(clock->number, GPIO_PULL_OFF);
142-
gpio_set_pin_function(clock->number, clock_pinmux);
143-
claim_pin(clock);
144+
setup_pin(clock, clock_pinmux);
144145
self->clock_pin = clock->number;
145146

146147
if (mosi_none) {
147148
self->MOSI_pin = NO_PIN;
148149
} else {
149-
gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT);
150-
gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
151-
gpio_set_pin_function(mosi->number, mosi_pinmux);
150+
setup_pin(mosi, mosi_pinmux);
152151
self->MOSI_pin = mosi->number;
153-
claim_pin(mosi);
154152
}
155153

156154
if (miso_none) {
157155
self->MISO_pin = NO_PIN;
158156
} else {
159-
gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN);
160-
gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
161-
gpio_set_pin_function(miso->number, miso_pinmux);
157+
setup_pin(miso, miso_pinmux);
162158
self->MISO_pin = miso->number;
163-
claim_pin(miso);
164159
}
165160

166161
spi_m_sync_enable(&self->spi_desc);
@@ -322,3 +317,11 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) {
322317
void *hw = self->spi_desc.dev.prvt;
323318
return hri_sercomspi_get_CTRLA_CPOL_bit(hw);
324319
}
320+
321+
void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux) {
322+
gpio_set_pin_direction(pin->number, GPIO_DIRECTION_OUT);
323+
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_OFF);
324+
gpio_set_pin_function(pin->number, pinmux);
325+
claim_pin(pin);
326+
hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin->number), GPIO_PIN(pin->number));
327+
}

ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ void common_hal_imagecapture_parallelimagecapture_singleshot_capture(imagecaptur
135135
mp_buffer_info_t bufinfo;
136136
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_RW);
137137

138-
uint8_t dma_channel = dma_allocate_channel();
138+
uint8_t dma_channel = dma_allocate_channel(true);
139139

140140
uint32_t *dest = bufinfo.buf;
141141
size_t count = bufinfo.len / 4; // PCC receives 4 bytes (2 pixels) at a time

0 commit comments

Comments
 (0)