Skip to content

Commit e7fc0b6

Browse files
committed
Use DMA for long SPI transactions including those to the SPI Flash.
QSPI is not currently working so its commented out. This is progress on adafruit#652.
1 parent f00d281 commit e7fc0b6

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)