Skip to content

Commit 57133ee

Browse files
authored
Merge pull request #42 from dhalbert/atomic-spi-dma-startup
make SPI RX/TX dma startup be atomic
2 parents cd77c53 + 79bf4e8 commit 57133ee

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

samd/dma.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include <string.h>
2929

30+
#include "mphalport.h"
3031
#include "py/gc.h"
3132
#include "py/mpstate.h"
3233

@@ -66,6 +67,7 @@ void init_shared_dma(void) {
6667

6768
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN0;
6869

70+
// Non-audio channels will be configured on demand.
6971
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
7072
dma_configure(i, 0, true);
7173
}
@@ -155,15 +157,17 @@ static int32_t shared_dma_transfer(void* peripheral,
155157
SercomSpi *s = &((Sercom*) peripheral)->SPI;
156158
s->INTFLAG.reg = SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_DRE;
157159
}
158-
// Start the RX job first so we don't miss the first byte. The TX job clocks
159-
// the output.
160+
161+
// Start the RX job first so we don't miss the first byte. The TX job clocks the output.
162+
// Disable interrupts during startup to make sure both RX and TX start at just about the same time.
163+
mp_hal_disable_all_interrupts();
160164
if (rx_active) {
161165
dma_enable_channel(SHARED_RX_CHANNEL);
162166
}
163167
if (tx_active) {
164168
dma_enable_channel(SHARED_TX_CHANNEL);
165169
}
166-
170+
mp_hal_enable_all_interrupts();
167171

168172
if (!sercom) {
169173
if (rx_active) {
@@ -177,7 +181,7 @@ static int32_t shared_dma_transfer(void* peripheral,
177181
// legitimate state for a DMA channel to be in (apparently), so we can't use that alone as a check.
178182
// Instead, let's look at the ACTIVE flag. When DMA is hung, everything in ACTIVE is zeros.
179183
bool is_okay = false;
180-
for (int i=0; i<10 && !is_okay; i++) {
184+
for (int i = 0; i < 10 && !is_okay; i++) {
181185
bool complete = true;
182186
if (rx_active) {
183187
if (DMAC->Channel[SHARED_RX_CHANNEL].CHSTATUS.reg & 0x3)
@@ -190,7 +194,7 @@ static int32_t shared_dma_transfer(void* peripheral,
190194
is_okay = is_okay || (DMAC->ACTIVE.bit.ABUSY || complete);
191195
}
192196
if (!is_okay) {
193-
for (int i=0; i<AUDIO_DMA_CHANNEL_COUNT; i++) {
197+
for (int i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
194198
if(DMAC->Channel[i].CHCTRLA.bit.ENABLE) {
195199
DMAC->Channel[i].CHCTRLA.bit.ENABLE = 0;
196200
DMAC->Channel[i].CHCTRLA.bit.ENABLE = 1;

0 commit comments

Comments
 (0)