Skip to content

Commit 93978bc

Browse files
authored
Merge pull request #465 from dhalbert/3.0_spi_flash
Support SPI flash chips for CIRCUITPY, using non-DMA SPI for now.
2 parents fb1dcd3 + 72c911b commit 93978bc

24 files changed

+357
-208
lines changed

ports/atmel-samd/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ SRC_C = \
218218
mphalport.c \
219219
reset.c \
220220
$(CHIP_FAMILY)_peripherals.c \
221+
peripherals.c \
221222
$(CHIP_FAMILY)_pins.c \
222223
tick.c \
223224
usb.c \
@@ -260,6 +261,7 @@ SRC_COMMON_HAL = \
260261
microcontroller/Processor.c \
261262
neopixel_write/__init__.c \
262263
os/__init__.c \
264+
storage/__init__.c \
263265
time/__init__.c \
264266
# analogio/__init__.c \
265267
analogio/AnalogIn.c \
@@ -276,7 +278,6 @@ SRC_COMMON_HAL = \
276278
pulseio/PulseIn.c \
277279
pulseio/PulseOut.c \
278280
pulseio/PWMOut.c \
279-
storage/__init__.c \
280281
touchio/__init__.c \
281282
touchio/TouchIn.c \
282283
usb_hid/__init__.c \

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

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,35 @@
33

44
#define MICROPY_HW_NEOPIXEL (&pin_PA06)
55

6-
// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
6+
// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz.
77
#define SPI_FLASH_BAUDRATE (8000000)
88

9-
#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_C
10-
#define SPI_FLASH_PAD0_PINMUX PINMUX_PA08D_SERCOM2_PAD0 // MOSI
11-
// Use default pinmux for the chip select since we manage it ourselves.
12-
#define SPI_FLASH_PAD1_PINMUX PINMUX_PA09D_SERCOM2_PAD1 // SCK
13-
#define SPI_FLASH_PAD2_PINMUX PINMUX_PA14C_SERCOM2_PAD2 // MISO
14-
#define SPI_FLASH_PAD3_PINMUX PINMUX_UNUSED // SCK
15-
#define SPI_FLASH_SERCOM SERCOM2
16-
17-
#define SPI_FLASH_CS PIN_PA13
18-
19-
#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
9+
#define SPI_FLASH_MOSI_PIN PIN_PA08
10+
#define SPI_FLASH_MISO_PIN PIN_PA14
11+
#define SPI_FLASH_SCK_PIN PIN_PA09
12+
#define SPI_FLASH_CS_PIN PIN_PA13
13+
#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0
14+
#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2
15+
#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1
16+
#define SPI_FLASH_SERCOM SERCOM2
17+
#define SPI_FLASH_SERCOM_INDEX 2
18+
#define SPI_FLASH_MOSI_PAD 0
19+
#define SPI_FLASH_MISO_PAD 2
20+
#define SPI_FLASH_SCK_PAD 1
21+
// <o> Transmit Data Pinout
22+
// <0x0=>PAD[0,1]_DO_SCK
23+
// <0x1=>PAD[2,3]_DO_SCK
24+
// <0x2=>PAD[3,1]_DO_SCK
25+
// <0x3=>PAD[0,3]_DO_SCK
26+
#define SPI_FLASH_DOPO 0
27+
#define SPI_FLASH_DIPO 2 // same as MISO pad
28+
29+
// These are pins not to reset.
30+
#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
2031
#define MICROPY_PORT_B ( 0 )
2132
#define MICROPY_PORT_C ( 0 )
2233

23-
#include "internal_flash.h"
24-
//#include "spi_flash.h"
34+
#include "spi_flash.h"
2535

2636
// If you change this, then make sure to update the linker scripts as well to
2737
// make sure you don't overwrite code.

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ USB_PID = 0x8023
44
USB_PRODUCT = "Feather M0 Express"
55
USB_MANUFACTURER = "Adafruit Industries LLC"
66

7-
#SPI_FLASH_FILESYSTEM = 1
8-
INTERNAL_FLASH_FILESYSTEM = 1
7+
SPI_FLASH_FILESYSTEM = 1
98

109
CHIP_VARIANT = SAMD21G18A
1110
CHIP_FAMILY = samd21

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

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#define USB_REPL
2-
31
#define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 Express"
42
#define MICROPY_HW_MCU_NAME "samd21g18"
53

@@ -8,24 +6,35 @@
86

97
#define MICROPY_HW_NEOPIXEL (&pin_PA30)
108

11-
// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
9+
// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz.
1210
#define SPI_FLASH_BAUDRATE (8000000)
1311

14-
#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F
15-
#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // CS
16-
// Use default pinmux for the chip select since we manage it ourselves.
17-
#define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO
18-
#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI
19-
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK
20-
#define SPI_FLASH_CS PIN_PA13
21-
#define SPI_FLASH_SERCOM SERCOM5
22-
12+
#define SPI_FLASH_MOSI_PIN PIN_PB22
13+
#define SPI_FLASH_MISO_PIN PIN_PB03
14+
#define SPI_FLASH_SCK_PIN PIN_PB23
15+
#define SPI_FLASH_CS_PIN PIN_PA13
16+
#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2
17+
#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1
18+
#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3
19+
#define SPI_FLASH_SERCOM SERCOM5
20+
#define SPI_FLASH_SERCOM_INDEX 5
21+
#define SPI_FLASH_MOSI_PAD 2
22+
#define SPI_FLASH_MISO_PAD 1
23+
#define SPI_FLASH_SCK_PAD 3
24+
// <o> Transmit Data Pinout
25+
// <0x0=>PAD[0,1]_DO_SCK
26+
// <0x1=>PAD[2,3]_DO_SCK
27+
// <0x2=>PAD[3,1]_DO_SCK
28+
// <0x3=>PAD[0,3]_DO_SCK
29+
#define SPI_FLASH_DOPO 1
30+
#define SPI_FLASH_DIPO 1 // same as MISO pad
31+
32+
// These are pins not to reset.
2333
#define MICROPY_PORT_A (PORT_PA13 |PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA30 | PORT_PA31)
2434
#define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23)
2535
#define MICROPY_PORT_C (0)
2636

27-
#include "internal_flash.h"
28-
//#include "spi_flash.h"
37+
#include "spi_flash.h"
2938

3039
// If you change this, then make sure to update the linker scripts as well to
3140
// make sure you don't overwrite code.

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ USB_PID = 0x8014
44
USB_PRODUCT = "Metro M0 Express"
55
USB_MANUFACTURER = "Adafruit Industries LLC"
66

7-
#SPI_FLASH_FILESYSTEM = 1
8-
INTERNAL_FLASH_FILESYSTEM = 1
7+
SPI_FLASH_FILESYSTEM = 1
98

109
CHIP_VARIANT = SAMD21G18A
1110
CHIP_FAMILY = samd21

ports/atmel-samd/boards/metro_m0_express/pins.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,5 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
2929
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
3030
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
3131
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) },
32-
{ MP_ROM_QSTR(MP_QSTR_FLASH_CS), MP_ROM_PTR(&pin_PA13) },
3332
};
3433
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

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

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,46 @@
88

99
#define MICROPY_HW_NEOPIXEL (&pin_PB17)
1010

11-
#define SPI_FLASH_BAUDRATE (1000000)
12-
13-
// Rev F
14-
#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F
15-
#define SPI_FLASH_PAD0_PINMUX PINMUX_PB08 // MOSI
16-
// Use default pinmux for the chip select since we manage it ourselves.
17-
#define SPI_FLASH_PAD1_PINMUX PINMUX_PB09 // SCK
18-
#define SPI_FLASH_PAD2_PINMUX PINMUX_DEFAULT // CS
19-
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11 // MISO
20-
#define SPI_FLASH_CS PIN_PB10
21-
#define SPI_FLASH_SERCOM SERCOM5
22-
11+
#define SPI_FLASH_BAUDRATE (8000000)
12+
13+
// Rev B: single channel SPI
14+
// Rev C will be QSPI
15+
#define SPI_FLASH_MOSI_PIN PIN_PB08
16+
#define SPI_FLASH_MISO_PIN PIN_PB11
17+
#define SPI_FLASH_SCK_PIN PIN_PB09
18+
#define SPI_FLASH_CS_PIN PIN_PB10
19+
#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0
20+
#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3
21+
#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1
22+
#define SPI_FLASH_SERCOM SERCOM4
23+
#define SPI_FLASH_SERCOM_INDEX 4
24+
#define SPI_FLASH_MOSI_PAD 0
25+
#define SPI_FLASH_MISO_PAD 3
26+
#define SPI_FLASH_SCK_PAD 1
27+
// <o> Transmit Data Pinout
28+
// <0x0=>PAD[0,1]_DO_SCK
29+
// <0x1=>PAD[2,3]_DO_SCK
30+
// <0x2=>PAD[3,1]_DO_SCK
31+
// <0x3=>PAD[0,3]_DO_SCK
32+
#define SPI_FLASH_DOPO 0
33+
#define SPI_FLASH_DIPO 3 // same as MISO pad
34+
35+
// These are pins not to reset.
2336
#define MICROPY_PORT_A (PORT_PA27)
24-
#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB11 | PORT_PB17)
37+
#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17)
2538
#define MICROPY_PORT_C (0)
2639
#define MICROPY_PORT_D (0)
2740

2841
#define AUTORESET_DELAY_MS 500
2942

30-
#include "internal_flash.h"
43+
#include "spi_flash.h"
3144

3245
// If you change this, then make sure to update the linker scripts as well to
33-
// make sure you don't overwrite code.
46+
// make sure you don't overwrite code
47+
// #define CIRCUITPY_INTERNAL_NVM_SIZE 256
3448
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
3549

36-
#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000)
50+
#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
51+
52+
#include "flash_S25FL216K.h"
53+
#include "flash_GD25Q16C.h"

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ USB_PID = 0x8021
44
USB_PRODUCT = "Metro M4 Express"
55
USB_MANUFACTURER = "Adafruit Industries LLC"
66

7-
#SPI_FLASH_FILESYSTEM = 1
8-
INTERNAL_FLASH_FILESYSTEM = 1
7+
SPI_FLASH_FILESYSTEM = 1
98

109
CHIP_VARIANT = SAMD51J19A
1110
CHIP_FAMILY = samd51

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
7272

7373

7474
// Set up I2C clocks on sercom.
75-
samd_peripheral_sercom_clock_init(sercom, sercom_index);
75+
samd_peripherals_sercom_clock_init(sercom, sercom_index);
7676

7777
if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) {
7878
mp_raise_OSError(MP_EIO);

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

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,7 @@
3737

3838
#include "peripherals.h"
3939
#include "pins.h"
40-
#include "shared_dma.h"
41-
42-
// Convert frequency to clock-speed-dependent value. Return 0 if out of range.
43-
static uint8_t baudrate_to_baud_reg_value(const uint32_t baudrate) {
44-
uint32_t baud_reg_value = (uint32_t) (((float) PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY /
45-
(2 * baudrate)) + 0.5f);
46-
if (baud_reg_value > 0xff) {
47-
return 0;
48-
}
49-
return (uint8_t) baud_reg_value;
50-
}
40+
//#include "shared_dma.h"
5141

5242
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
5343
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
@@ -78,15 +68,15 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
7868
}
7969
clock_pinmux = PINMUX(clock->pin, (i == 0) ? MUX_C : MUX_D);
8070
clock_pad = clock->sercom[i].pad;
81-
if (!samd_peripheral_valid_spi_clock_pad(clock_pad)) {
71+
if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) {
8272
continue;
8373
}
8474
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
8575
if (!mosi_none) {
8676
if(potential_sercom == mosi->sercom[j].sercom) {
8777
mosi_pinmux = PINMUX(mosi->pin, (j == 0) ? MUX_C : MUX_D);
8878
mosi_pad = mosi->sercom[j].pad;
89-
dopo = samd_peripheral_get_spi_dopo(clock_pad, mosi_pad);
79+
dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad);
9080
if (dopo > 0x3) {
9181
continue; // pad combination not possible
9282
}
@@ -121,7 +111,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
121111
}
122112

123113
// Set up SPI clocks on SERCOM.
124-
samd_peripheral_sercom_clock_init(sercom, sercom_index);
114+
samd_peripherals_sercom_clock_init(sercom, sercom_index);
125115

126116
if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
127117
mp_raise_OSError(MP_EIO);
@@ -132,7 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
132122

133123
// Always start at 250khz which is what SD cards need. They are sensitive to
134124
// SPI bus noise before they are put into SPI mode.
135-
uint8_t baud_value = baudrate_to_baud_reg_value(250000);
125+
uint8_t baud_value = samd_peripherals_baudrate_to_baud_reg_value(250000);
136126
if (baud_value == 0) {
137127
mp_raise_RuntimeError("SPI initial baudrate out of range.");
138128
}
@@ -142,6 +132,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
142132
mp_raise_OSError(MP_EIO);
143133
}
144134

135+
gpio_set_pin_direction(clock->pin, GPIO_DIRECTION_OUT);
145136
gpio_set_pin_pull_mode(clock->pin, GPIO_PULL_OFF);
146137
gpio_set_pin_function(clock->pin, clock_pinmux);
147138
claim_pin(clock);
@@ -150,6 +141,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
150141
if (mosi_none) {
151142
self->MOSI_pin = NO_PIN;
152143
} else {
144+
gpio_set_pin_direction(mosi->pin, GPIO_DIRECTION_OUT);
153145
gpio_set_pin_pull_mode(mosi->pin, GPIO_PULL_OFF);
154146
gpio_set_pin_function(mosi->pin, mosi_pinmux);
155147
self->MOSI_pin = mosi->pin;
@@ -159,6 +151,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
159151
if (miso_none) {
160152
self->MISO_pin = NO_PIN;
161153
} else {
154+
gpio_set_pin_direction(miso->pin, GPIO_DIRECTION_IN);
162155
gpio_set_pin_pull_mode(miso->pin, GPIO_PULL_OFF);
163156
gpio_set_pin_function(miso->pin, miso_pinmux);
164157
self->MISO_pin = miso->pin;
@@ -186,7 +179,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
186179

187180
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
188181
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
189-
uint8_t baud_reg_value = baudrate_to_baud_reg_value(baudrate);
182+
uint8_t baud_reg_value = samd_peripherals_baudrate_to_baud_reg_value(baudrate);
190183
if (baud_reg_value == 0) {
191184
mp_raise_ValueError("baudrate out of range");
192185
}
@@ -248,7 +241,7 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
248241
spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io);
249242
status = spi_io->write(spi_io, data, len);
250243
// }
251-
return status > 0; // Status is number of chars read or an error code < 0.
244+
return status >= 0; // Status is number of chars read or an error code < 0.
252245
}
253246

254247
bool common_hal_busio_spi_read(busio_spi_obj_t *self,
@@ -267,5 +260,5 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
267260

268261
status = spi_io->read(spi_io, data, len);
269262
// }
270-
return status > 0; // Status is number of chars read or an error code < 0.
263+
return status >= 0; // Status is number of chars read or an error code < 0.
271264
}

ports/atmel-samd/common-hal/storage/__init__.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "py/mperrno.h"
3131
#include "py/runtime.h"
3232
#include "shared-bindings/storage/__init__.h"
33+
#include "usb.h"
3334

3435
extern volatile bool mp_msc_enabled;
3536

@@ -38,7 +39,9 @@ void common_hal_storage_remount(const char* mount_path, bool readonly) {
3839
mp_raise_OSError(MP_EINVAL);
3940
}
4041

41-
if (mp_msc_enabled) {
42+
// TODO(dhalbert): is this is a good enough check? It checks for
43+
// CDC enabled. There is no "MSC enabled" check.
44+
if (usb_connected()) {
4245
mp_raise_RuntimeError("Cannot remount '/' when USB is active.");
4346
}
4447

ports/atmel-samd/mpconfigport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ extern const struct _mp_obj_module_t usb_hid_module;
215215

216216
// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module },
217217
// { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module },
218-
// { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module },
219218

220219

221220
#define MICROPY_PORT_BUILTIN_MODULES \
@@ -226,6 +225,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
226225
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module }, \
227226
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \
228227
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
228+
{ MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
229229
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \
230230
{ MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \
231231
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \

0 commit comments

Comments
 (0)