Skip to content

Commit dde5ade

Browse files
authored
Merge pull request adafruit#663 from tannewt/dma3
Use DMA for long SPI transactions including those to the SPI Flash.
2 parents f00d281 + e7fc0b6 commit dde5ade

File tree

10 files changed

+417
-222
lines changed

10 files changed

+417
-222
lines changed

ports/atmel-samd/Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,6 @@ endif
217217

218218
SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF))
219219

220-
# Skip this source for now.
221-
# shared_dma.c \
222-
223220
SRC_C = \
224221
background.c \
225222
fatfs_port.c \
@@ -229,6 +226,7 @@ SRC_C = \
229226
$(CHIP_FAMILY)_peripherals.c \
230227
peripherals.c \
231228
$(CHIP_FAMILY)_pins.c \
229+
shared_dma.c \
232230
tick.c \
233231
timers.c \
234232
usb.c \

ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#define MICROPY_HW_APA102_MOSI (&pin_PA01)
66
#define MICROPY_HW_APA102_SCK (&pin_PA00)
77

8-
// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
8+
// Saleae reads 12mhz which is the limit even though we set it to the safer 8mhz.
99
#define SPI_FLASH_BAUDRATE (8000000)
1010

1111
#define SPI_FLASH_MOSI_PIN PIN_PB22

ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#define MICROPY_HW_NEOPIXEL (&pin_PB17)
1313

14-
#define SPI_FLASH_BAUDRATE (8000000)
14+
#define SPI_FLASH_BAUDRATE (60000000)
1515

1616
// Rev B: single channel SPI
1717
// Rev C will be QSPI

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

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
#include "peripherals.h"
4040
#include "pins.h"
41-
//#include "shared_dma.h"
41+
#include "shared_dma.h"
4242

4343
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
4444
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
@@ -113,15 +113,15 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
113113

114114
// Set up SPI clocks on SERCOM.
115115
samd_peripherals_sercom_clock_init(sercom, sercom_index);
116-
116+
117117
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
118118
// if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out
119119
hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom);
120120
#endif
121121
if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
122122
mp_raise_OSError(MP_EIO);
123123
}
124-
124+
125125
// Pads must be set after spi_m_sync_init(), which uses default values from
126126
// the prototypical SERCOM.
127127
hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo);
@@ -135,7 +135,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
135135
// busy or not
136136
mp_raise_OSError(MP_EIO);
137137
}
138-
138+
139139
gpio_set_pin_direction(clock->pin, GPIO_DIRECTION_OUT);
140140
gpio_set_pin_pull_mode(clock->pin, GPIO_PULL_OFF);
141141
gpio_set_pin_function(clock->pin, clock_pinmux);
@@ -194,7 +194,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
194194
return true;
195195
}
196196

197-
// Disable, set values (most or all are enable-protected), and re-enable.
197+
// Disable, set values (most or all are enable-protected), and re-enable.
198198
spi_m_sync_disable(&self->spi_desc);
199199
hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_MASK);
200200

@@ -235,14 +235,14 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
235235
return true;
236236
}
237237
int32_t status;
238-
// if (len >= 16) {
239-
// status = shared_dma_write(self->spi_desc.dev.prvt, data, len);
240-
// } else {
238+
if (len >= 16) {
239+
status = sercom_dma_write(self->spi_desc.dev.prvt, data, len);
240+
} else {
241241
struct io_descriptor *spi_io;
242242
spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io);
243243
status = spi_io->write(spi_io, data, len);
244-
// }
245-
return status >= 0; // Status is number of chars read or an error code < 0.
244+
}
245+
return status >= 0; // Status is number of chars read or an error code < 0.
246246
}
247247

248248
bool common_hal_busio_spi_read(busio_spi_obj_t *self,
@@ -251,34 +251,34 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
251251
return true;
252252
}
253253
int32_t status;
254-
// if (len >= 16) {
255-
// status = shared_dma_read(self->spi_desc.dev.prvt, data, len, write_value);
256-
// } else {
254+
if (len >= 16) {
255+
status = sercom_dma_read(self->spi_desc.dev.prvt, data, len, write_value);
256+
} else {
257257
self->spi_desc.dev.dummy_byte = write_value;
258258

259259
struct io_descriptor *spi_io;
260260
spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io);
261261

262262
status = spi_io->read(spi_io, data, len);
263-
// }
264-
return status >= 0; // Status is number of chars read or an error code < 0.
263+
}
264+
return status >= 0; // Status is number of chars read or an error code < 0.
265265
}
266266

267267
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
268268
if (len == 0) {
269269
return true;
270270
}
271271
int32_t status;
272-
// if (len >= 16) {
273-
// status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/);
274-
// } else {
272+
if (len >= 16) {
273+
status = sercom_dma_transfer(self->spi_desc.dev.prvt, data_out, data_in, len);
274+
} else {
275275
struct spi_xfer xfer;
276276
xfer.txbuf = data_out;
277277
xfer.rxbuf = data_in;
278278
xfer.size = len;
279279
status = spi_m_sync_transfer(&self->spi_desc, &xfer);
280-
// }
281-
return status >= 0; // Status is number of chars read or an error code < 0.
280+
}
281+
return status >= 0; // Status is number of chars read or an error code < 0.
282282
}
283283

284284
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {

ports/atmel-samd/external_flash/external_flash.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ void external_flash_init(void) {
199199

200200
spi_flash_init();
201201

202-
203202
for (uint8_t i = 0; i < num_possible_devices; i++) {
204203
const external_flash_device* possible_device = &possible_devices[i];
205204
uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00};
@@ -213,7 +212,6 @@ void external_flash_init(void) {
213212
}
214213

215214
if (flash_device == NULL) {
216-
asm("bkpt");
217215
return;
218216
}
219217

ports/atmel-samd/external_flash/qspi_flash.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <string.h>
3131

3232
#include "external_flash/common_commands.h"
33+
#include "shared_dma.h"
3334

3435
#include "atmel_start_pins.h"
3536
#include "hal_gpio.h"
@@ -125,6 +126,8 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
125126
QSPI_INSTRFRAME_DATAEN;
126127

127128
memcpy(((uint8_t *) QSPI_AHB) + address, data, length);
129+
// TODO(tannewt): Fix DMA and enable it.
130+
// qspi_dma_write(address, data, length);
128131

129132
QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER;
130133

@@ -148,6 +151,8 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
148151
QSPI_INSTRFRAME_DUMMYLEN(8);
149152

150153
memcpy(data, ((uint8_t *) QSPI_AHB) + address, length);
154+
// TODO(tannewt): Fix DMA and enable it.
155+
// qspi_dma_read(address, data, length);
151156

152157
QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER;
153158

@@ -167,12 +172,15 @@ void spi_flash_init(void) {
167172
QSPI->CTRLA.reg = QSPI_CTRLA_SWRST;
168173
// We don't need to wait because we're running as fast as the CPU.
169174

170-
QSPI->BAUD.bit.BAUD = 1;
175+
// Slow, good for debugging with Saleae
176+
// QSPI->BAUD.bit.BAUD = 32;
177+
// Super fast
178+
QSPI->BAUD.bit.BAUD = 2;
171179
QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY |
172180
QSPI_CTRLB_DATALEN_8BITS |
173181
QSPI_CTRLB_CSMODE_LASTXFER;
174182

175-
QSPI->CTRLA.bit.ENABLE = 1;
183+
QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE;
176184

177185
// The QSPI is only connected to one set of pins in the SAMD51 so we can hard code it.
178186
uint32_t pins[6] = {PIN_PA08, PIN_PA09, PIN_PA10, PIN_PA11, PIN_PB10, PIN_PB11};

ports/atmel-samd/external_flash/spi_flash.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "external_flash/common_commands.h"
3232
#include "peripherals.h"
33+
#include "shared_dma.h"
3334

3435
#include "hal_gpio.h"
3536
#include "hal_spi_m_sync.h"
@@ -91,14 +92,28 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length)
9192
uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00};
9293
// Write the SPI flash write address into the bytes following the command byte.
9394
address_to_bytes(address, request + 1);
94-
return transfer(request, 4, data, NULL, data_length);
95+
struct spi_xfer xfer = { request, NULL, 4 };
96+
flash_enable();
97+
int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer);
98+
if (status >= 0) {
99+
status = sercom_dma_write(spi_flash_desc.dev.prvt, data, data_length);
100+
}
101+
flash_disable();
102+
return status >= 0;
95103
}
96104

97105
bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) {
98106
uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00};
99107
// Write the SPI flash write address into the bytes following the command byte.
100108
address_to_bytes(address, request + 1);
101-
return transfer(request, 4, NULL, data, data_length);
109+
struct spi_xfer xfer = { request, NULL, 4 };
110+
flash_enable();
111+
int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer);
112+
if (status >= 0) {
113+
status = sercom_dma_read(spi_flash_desc.dev.prvt, data, data_length, 0xff);
114+
}
115+
flash_disable();
116+
return status >= 0;
102117
}
103118

104119
void spi_flash_init(void) {

0 commit comments

Comments
 (0)