summaryrefslogtreecommitdiff
path: root/ports/atmel-samd
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2017-11-22 23:07:21 -0500
committerDan Halbert <halbert@halwitz.org>2017-11-27 21:00:24 -0500
commit72c911be972d63a5032fa02ecb74d173bf9ef34f (patch)
tree5f09ff39c086dc35d5fe77820a33a8e61e3ae176 /ports/atmel-samd
parentfb1dcd326dbca2bfe7452f1f9c3d94dc25612e30 (diff)
Support SPI flash chips for CIRCUITPY, using non-DMA SPI for now.
Diffstat (limited to 'ports/atmel-samd')
-rw-r--r--ports/atmel-samd/Makefile3
m---------ports/atmel-samd/asf40
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h38
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h37
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/pins.c1
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h49
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/common-hal/busio/I2C.c2
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c29
-rw-r--r--ports/atmel-samd/common-hal/storage/__init__.c5
-rw-r--r--ports/atmel-samd/mpconfigport.h2
-rw-r--r--ports/atmel-samd/peripherals.c43
-rw-r--r--ports/atmel-samd/peripherals.h5
-rw-r--r--ports/atmel-samd/samd21_peripherals.c6
-rw-r--r--ports/atmel-samd/samd21_peripherals.h6
-rw-r--r--ports/atmel-samd/samd51_peripherals.c6
-rw-r--r--ports/atmel-samd/samd51_peripherals.h6
-rw-r--r--ports/atmel-samd/samd_peripherals.h36
-rw-r--r--ports/atmel-samd/shared_dma.c33
-rw-r--r--ports/atmel-samd/spi_flash.c237
-rw-r--r--ports/atmel-samd/usb_mass_storage.c8
23 files changed, 355 insertions, 206 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 3ac4cde9a..486df28c2 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -218,6 +218,7 @@ SRC_C = \
mphalport.c \
reset.c \
$(CHIP_FAMILY)_peripherals.c \
+ peripherals.c \
$(CHIP_FAMILY)_pins.c \
tick.c \
usb.c \
@@ -260,6 +261,7 @@ SRC_COMMON_HAL = \
microcontroller/Processor.c \
neopixel_write/__init__.c \
os/__init__.c \
+ storage/__init__.c \
time/__init__.c \
# analogio/__init__.c \
analogio/AnalogIn.c \
@@ -276,7 +278,6 @@ SRC_COMMON_HAL = \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/PWMOut.c \
- storage/__init__.c \
touchio/__init__.c \
touchio/TouchIn.c \
usb_hid/__init__.c \
diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4
-Subproject 72f76894ba08c9de2ec3ae231fb71daaf3eafb1
+Subproject 0efc3407dd97ef617a5655674a3516693897a96
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
index 83c681061..448c6c52b 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
@@ -3,25 +3,35 @@
#define MICROPY_HW_NEOPIXEL (&pin_PA06)
-// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz.
#define SPI_FLASH_BAUDRATE (8000000)
-#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_C
-#define SPI_FLASH_PAD0_PINMUX PINMUX_PA08D_SERCOM2_PAD0 // MOSI
-// Use default pinmux for the chip select since we manage it ourselves.
-#define SPI_FLASH_PAD1_PINMUX PINMUX_PA09D_SERCOM2_PAD1 // SCK
-#define SPI_FLASH_PAD2_PINMUX PINMUX_PA14C_SERCOM2_PAD2 // MISO
-#define SPI_FLASH_PAD3_PINMUX PINMUX_UNUSED // SCK
-#define SPI_FLASH_SERCOM SERCOM2
-
-#define SPI_FLASH_CS PIN_PA13
-
-#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
+#define SPI_FLASH_MOSI_PIN PIN_PA08
+#define SPI_FLASH_MISO_PIN PIN_PA14
+#define SPI_FLASH_SCK_PIN PIN_PA09
+#define SPI_FLASH_CS_PIN PIN_PA13
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1
+#define SPI_FLASH_SERCOM SERCOM2
+#define SPI_FLASH_SERCOM_INDEX 2
+#define SPI_FLASH_MOSI_PAD 0
+#define SPI_FLASH_MISO_PAD 2
+#define SPI_FLASH_SCK_PAD 1
+// <o> Transmit Data Pinout
+// <0x0=>PAD[0,1]_DO_SCK
+// <0x1=>PAD[2,3]_DO_SCK
+// <0x2=>PAD[3,1]_DO_SCK
+// <0x3=>PAD[0,3]_DO_SCK
+#define SPI_FLASH_DOPO 0
+#define SPI_FLASH_DIPO 2 // same as MISO pad
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B ( 0 )
#define MICROPY_PORT_C ( 0 )
-#include "internal_flash.h"
-//#include "spi_flash.h"
+#include "spi_flash.h"
// If you change this, then make sure to update the linker scripts as well to
// make sure you don't overwrite code.
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index 820ec4eca..5e3a97493 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -4,8 +4,7 @@ USB_PID = 0x8023
USB_PRODUCT = "Feather M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-#SPI_FLASH_FILESYSTEM = 1
-INTERNAL_FLASH_FILESYSTEM = 1
+SPI_FLASH_FILESYSTEM = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
index e3b67de4b..023beb688 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
@@ -1,5 +1,3 @@
-#define USB_REPL
-
#define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 Express"
#define MICROPY_HW_MCU_NAME "samd21g18"
@@ -8,24 +6,35 @@
#define MICROPY_HW_NEOPIXEL (&pin_PA30)
-// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz.
#define SPI_FLASH_BAUDRATE (8000000)
-#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F
-#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // CS
-// Use default pinmux for the chip select since we manage it ourselves.
-#define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO
-#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI
-#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK
-#define SPI_FLASH_CS PIN_PA13
-#define SPI_FLASH_SERCOM SERCOM5
-
+#define SPI_FLASH_MOSI_PIN PIN_PB22
+#define SPI_FLASH_MISO_PIN PIN_PB03
+#define SPI_FLASH_SCK_PIN PIN_PB23
+#define SPI_FLASH_CS_PIN PIN_PA13
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3
+#define SPI_FLASH_SERCOM SERCOM5
+#define SPI_FLASH_SERCOM_INDEX 5
+#define SPI_FLASH_MOSI_PAD 2
+#define SPI_FLASH_MISO_PAD 1
+#define SPI_FLASH_SCK_PAD 3
+// <o> Transmit Data Pinout
+// <0x0=>PAD[0,1]_DO_SCK
+// <0x1=>PAD[2,3]_DO_SCK
+// <0x2=>PAD[3,1]_DO_SCK
+// <0x3=>PAD[0,3]_DO_SCK
+#define SPI_FLASH_DOPO 1
+#define SPI_FLASH_DIPO 1 // same as MISO pad
+
+// These are pins not to reset.
#define MICROPY_PORT_A (PORT_PA13 |PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA30 | PORT_PA31)
#define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23)
#define MICROPY_PORT_C (0)
-#include "internal_flash.h"
-//#include "spi_flash.h"
+#include "spi_flash.h"
// If you change this, then make sure to update the linker scripts as well to
// make sure you don't overwrite code.
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 7d63321af..d624b8191 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -4,8 +4,7 @@ USB_PID = 0x8014
USB_PRODUCT = "Metro M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-#SPI_FLASH_FILESYSTEM = 1
-INTERNAL_FLASH_FILESYSTEM = 1
+SPI_FLASH_FILESYSTEM = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/metro_m0_express/pins.c b/ports/atmel-samd/boards/metro_m0_express/pins.c
index bafd0bc9f..58510faab 100644
--- a/ports/atmel-samd/boards/metro_m0_express/pins.c
+++ b/ports/atmel-samd/boards/metro_m0_express/pins.c
@@ -29,6 +29,5 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) },
- { MP_ROM_QSTR(MP_QSTR_FLASH_CS), MP_ROM_PTR(&pin_PA13) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
index 34a681607..1af18ecbc 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
@@ -8,29 +8,46 @@
#define MICROPY_HW_NEOPIXEL (&pin_PB17)
-#define SPI_FLASH_BAUDRATE (1000000)
-
-// Rev F
-#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F
-#define SPI_FLASH_PAD0_PINMUX PINMUX_PB08 // MOSI
-// Use default pinmux for the chip select since we manage it ourselves.
-#define SPI_FLASH_PAD1_PINMUX PINMUX_PB09 // SCK
-#define SPI_FLASH_PAD2_PINMUX PINMUX_DEFAULT // CS
-#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11 // MISO
-#define SPI_FLASH_CS PIN_PB10
-#define SPI_FLASH_SERCOM SERCOM5
-
+#define SPI_FLASH_BAUDRATE (8000000)
+
+// Rev B: single channel SPI
+// Rev C will be QSPI
+#define SPI_FLASH_MOSI_PIN PIN_PB08
+#define SPI_FLASH_MISO_PIN PIN_PB11
+#define SPI_FLASH_SCK_PIN PIN_PB09
+#define SPI_FLASH_CS_PIN PIN_PB10
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1
+#define SPI_FLASH_SERCOM SERCOM4
+#define SPI_FLASH_SERCOM_INDEX 4
+#define SPI_FLASH_MOSI_PAD 0
+#define SPI_FLASH_MISO_PAD 3
+#define SPI_FLASH_SCK_PAD 1
+// <o> Transmit Data Pinout
+// <0x0=>PAD[0,1]_DO_SCK
+// <0x1=>PAD[2,3]_DO_SCK
+// <0x2=>PAD[3,1]_DO_SCK
+// <0x3=>PAD[0,3]_DO_SCK
+#define SPI_FLASH_DOPO 0
+#define SPI_FLASH_DIPO 3 // same as MISO pad
+
+// These are pins not to reset.
#define MICROPY_PORT_A (PORT_PA27)
-#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB11 | PORT_PB17)
+#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17)
#define MICROPY_PORT_C (0)
#define MICROPY_PORT_D (0)
#define AUTORESET_DELAY_MS 500
-#include "internal_flash.h"
+#include "spi_flash.h"
// If you change this, then make sure to update the linker scripts as well to
-// make sure you don't overwrite code.
+// make sure you don't overwrite code
+// #define CIRCUITPY_INTERNAL_NVM_SIZE 256
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
-#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000)
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#include "flash_S25FL216K.h"
+#include "flash_GD25Q16C.h"
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index 194116545..0369a7dd2 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -4,8 +4,7 @@ USB_PID = 0x8021
USB_PRODUCT = "Metro M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-#SPI_FLASH_FILESYSTEM = 1
-INTERNAL_FLASH_FILESYSTEM = 1
+SPI_FLASH_FILESYSTEM = 1
CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c
index 31b5767e7..4182c8651 100644
--- a/ports/atmel-samd/common-hal/busio/I2C.c
+++ b/ports/atmel-samd/common-hal/busio/I2C.c
@@ -72,7 +72,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
// Set up I2C clocks on sercom.
- samd_peripheral_sercom_clock_init(sercom, sercom_index);
+ samd_peripherals_sercom_clock_init(sercom, sercom_index);
if (i2c_m_sync_init(&self->i2c_desc, sercom) != ERR_NONE) {
mp_raise_OSError(MP_EIO);
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index 21fed5d12..cb6a165de 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -37,17 +37,7 @@
#include "peripherals.h"
#include "pins.h"
-#include "shared_dma.h"
-
-// Convert frequency to clock-speed-dependent value. Return 0 if out of range.
-static uint8_t baudrate_to_baud_reg_value(const uint32_t baudrate) {
- uint32_t baud_reg_value = (uint32_t) (((float) PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY /
- (2 * baudrate)) + 0.5f);
- if (baud_reg_value > 0xff) {
- return 0;
- }
- return (uint8_t) baud_reg_value;
-}
+//#include "shared_dma.h"
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
@@ -78,7 +68,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
}
clock_pinmux = PINMUX(clock->pin, (i == 0) ? MUX_C : MUX_D);
clock_pad = clock->sercom[i].pad;
- if (!samd_peripheral_valid_spi_clock_pad(clock_pad)) {
+ if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) {
continue;
}
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
@@ -86,7 +76,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
if(potential_sercom == mosi->sercom[j].sercom) {
mosi_pinmux = PINMUX(mosi->pin, (j == 0) ? MUX_C : MUX_D);
mosi_pad = mosi->sercom[j].pad;
- dopo = samd_peripheral_get_spi_dopo(clock_pad, mosi_pad);
+ dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad);
if (dopo > 0x3) {
continue; // pad combination not possible
}
@@ -121,7 +111,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
}
// Set up SPI clocks on SERCOM.
- samd_peripheral_sercom_clock_init(sercom, sercom_index);
+ samd_peripherals_sercom_clock_init(sercom, sercom_index);
if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
mp_raise_OSError(MP_EIO);
@@ -132,7 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
// Always start at 250khz which is what SD cards need. They are sensitive to
// SPI bus noise before they are put into SPI mode.
- uint8_t baud_value = baudrate_to_baud_reg_value(250000);
+ uint8_t baud_value = samd_peripherals_baudrate_to_baud_reg_value(250000);
if (baud_value == 0) {
mp_raise_RuntimeError("SPI initial baudrate out of range.");
}
@@ -142,6 +132,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
mp_raise_OSError(MP_EIO);
}
+ gpio_set_pin_direction(clock->pin, GPIO_DIRECTION_OUT);
gpio_set_pin_pull_mode(clock->pin, GPIO_PULL_OFF);
gpio_set_pin_function(clock->pin, clock_pinmux);
claim_pin(clock);
@@ -150,6 +141,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
if (mosi_none) {
self->MOSI_pin = NO_PIN;
} else {
+ gpio_set_pin_direction(mosi->pin, GPIO_DIRECTION_OUT);
gpio_set_pin_pull_mode(mosi->pin, GPIO_PULL_OFF);
gpio_set_pin_function(mosi->pin, mosi_pinmux);
self->MOSI_pin = mosi->pin;
@@ -159,6 +151,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
if (miso_none) {
self->MISO_pin = NO_PIN;
} else {
+ gpio_set_pin_direction(miso->pin, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(miso->pin, GPIO_PULL_OFF);
gpio_set_pin_function(miso->pin, miso_pinmux);
self->MISO_pin = miso->pin;
@@ -186,7 +179,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
- uint8_t baud_reg_value = baudrate_to_baud_reg_value(baudrate);
+ uint8_t baud_reg_value = samd_peripherals_baudrate_to_baud_reg_value(baudrate);
if (baud_reg_value == 0) {
mp_raise_ValueError("baudrate out of range");
}
@@ -248,7 +241,7 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io);
status = spi_io->write(spi_io, data, len);
// }
- return status > 0; // Status is number of chars read or an error code < 0.
+ return status >= 0; // Status is number of chars read or an error code < 0.
}
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,
status = spi_io->read(spi_io, data, len);
// }
- return status > 0; // Status is number of chars read or an error code < 0.
+ return status >= 0; // Status is number of chars read or an error code < 0.
}
diff --git a/ports/atmel-samd/common-hal/storage/__init__.c b/ports/atmel-samd/common-hal/storage/__init__.c
index 184184b8b..c4cb83142 100644
--- a/ports/atmel-samd/common-hal/storage/__init__.c
+++ b/ports/atmel-samd/common-hal/storage/__init__.c
@@ -30,6 +30,7 @@
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/storage/__init__.h"
+#include "usb.h"
extern volatile bool mp_msc_enabled;
@@ -38,7 +39,9 @@ void common_hal_storage_remount(const char* mount_path, bool readonly) {
mp_raise_OSError(MP_EINVAL);
}
- if (mp_msc_enabled) {
+ // TODO(dhalbert): is this is a good enough check? It checks for
+ // CDC enabled. There is no "MSC enabled" check.
+ if (usb_connected()) {
mp_raise_RuntimeError("Cannot remount '/' when USB is active.");
}
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index 1db2d5a67..f15efca96 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -215,7 +215,6 @@ extern const struct _mp_obj_module_t usb_hid_module;
// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module },
-// { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module },
#define MICROPY_PORT_BUILTIN_MODULES \
@@ -226,6 +225,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
diff --git a/ports/atmel-samd/peripherals.c b/ports/atmel-samd/peripherals.c
new file mode 100644
index 000000000..6de813cca
--- /dev/null
+++ b/ports/atmel-samd/peripherals.c
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals.h"
+
+#include "hpl_sercom_config.h"
+
+// Routines that are the same across all samd variants.
+
+
+// Convert frequency to clock-speed-dependent value. Return 0 if out of range.
+uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate) {
+ uint32_t baud_reg_value = (uint32_t) (((float) PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY /
+ (2 * baudrate)) + 0.5f);
+ if (baud_reg_value > 0xff) {
+ return 0;
+ }
+ return (uint8_t) baud_reg_value;
+}
+
diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals.h
index 03828ae74..95bc1ec53 100644
--- a/ports/atmel-samd/peripherals.h
+++ b/ports/atmel-samd/peripherals.h
@@ -27,8 +27,13 @@
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H
#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H
+#include <stdint.h>
+
#include "mpconfigport.h"
+// Routines common across chip families.
+uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate);
+
#ifdef SAMD21
#include "samd21_peripherals.h"
#endif
diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/samd21_peripherals.c
index 0ddc3be52..484c787cb 100644
--- a/ports/atmel-samd/samd21_peripherals.c
+++ b/ports/atmel-samd/samd21_peripherals.c
@@ -58,7 +58,7 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = {
// Clock initialization as done in Atmel START.
-void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
_pm_enable_bus_clock(PM_BUS_APBC, sercom);
_gclk_enable_channel(SERCOMx_GCLK_ID_CORE[sercom_index], GCLK_CLKCTRL_GEN_GCLK0_Val);
_gclk_enable_channel(SERCOMx_GCLK_ID_SLOW[sercom_index], GCLK_CLKCTRL_GEN_GCLK3_Val);
@@ -70,7 +70,7 @@ void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
// <0x1=>PAD[2,3]_DO_SCK
// <0x2=>PAD[3,1]_DO_SCK
// <0x3=>PAD[0,3]_DO_SCK
-uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
if (clock_pad == 1) {
if (mosi_pad == 0) {
return 0;
@@ -87,6 +87,6 @@ uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
return 255;
}
-bool samd_peripheral_valid_spi_clock_pad(uint8_t clock_pad) {
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1 || clock_pad == 3;
}
diff --git a/ports/atmel-samd/samd21_peripherals.h b/ports/atmel-samd/samd21_peripherals.h
index a317d3ddc..7a4477891 100644
--- a/ports/atmel-samd/samd21_peripherals.h
+++ b/ports/atmel-samd/samd21_peripherals.h
@@ -29,8 +29,8 @@
#include "include/sam.h"
-void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
-uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
-bool samd_peripheral_valid_spi_clock_pad(uint8_t clock_pad);
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/samd51_peripherals.c
index f1528f3c1..e06f7f9df 100644
--- a/ports/atmel-samd/samd51_peripherals.c
+++ b/ports/atmel-samd/samd51_peripherals.c
@@ -62,7 +62,7 @@ static const uint8_t SERCOMx_GCLK_ID_SLOW[] = {
// Clock initialization as done in Atmel START.
-void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
hri_gclk_write_PCHCTRL_reg(GCLK,
SERCOMx_GCLK_ID_CORE[sercom_index],
GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
@@ -113,7 +113,7 @@ void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index) {
// <0x1=>PAD[2,3]_DO_SCK [RESERVED]
// <0x2=>PAD[3,1]_DO_SCK
// <0x3=>PAD[0,3]_DO_SCK [RESERVED]
-uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
if (clock_pad != 1) {
return 255;
}
@@ -126,6 +126,6 @@ uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
return 255;
}
-bool samd_peripheral_valid_spi_clock_pad(uint8_t clock_pad) {
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1;
}
diff --git a/ports/atmel-samd/samd51_peripherals.h b/ports/atmel-samd/samd51_peripherals.h
index 3e8097c87..c47e3bee7 100644
--- a/ports/atmel-samd/samd51_peripherals.h
+++ b/ports/atmel-samd/samd51_peripherals.h
@@ -29,9 +29,9 @@
#include "sam.h"
-void samd_peripheral_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
-uint8_t samd_peripheral_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
-bool samd_peripheral_valid_spi_clock_pad(uint8_t clock_pad);
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H
diff --git a/ports/atmel-samd/samd_peripherals.h b/ports/atmel-samd/samd_peripherals.h
new file mode 100644
index 000000000..7a4477891
--- /dev/null
+++ b/ports/atmel-samd/samd_peripherals.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 by Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
+
+#include "include/sam.h"
+
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/shared_dma.c
index a2914c3cf..f8cef0992 100644
--- a/ports/atmel-samd/shared_dma.c
+++ b/ports/atmel-samd/shared_dma.c
@@ -43,28 +43,33 @@ void init_shared_dma(void) {
struct dma_resource_config config;
dma_get_config_defaults(&config);
- // This allocates the lowest channel first so make sure the audio is first
- // so it gets the highest priority.
- config.peripheral_trigger = DAC_DMAC_ID_EMPTY;
- config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
- config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
- config.event_config.event_output_enable = true;
- dma_allocate(&audio_dma, &config);
+ // See asf4_conf/hpl_dmac_config.h for initial settings for DMA channels
+ // DMA Channel 0: audio, highest priority,
+ // normal transfer on input, DAC 0 empty is trigger source, trigger on each beat, beat is one byte
+ // output enable true.
+ // asf3 settings:
+ //config.peripheral_trigger = DAC_DMAC_ID_EMPTY;
+ //config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
+ //config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
+ //config.event_config.event_output_enable = true;
+
// Turn on the transfer complete interrupt so that the job_status changes to done.
g_chan_interrupt_flag[audio_dma.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE);
// Prioritize the RX channel over the TX channel because TX can cause an RX
// overflow.
- dma_get_config_defaults(&config);
- config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
- config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
+
+ // DMA Channel 1: rx channel,
+ // normal transfer on input, trigger on each beat, beat is one byte
+ //config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
+ //config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
dma_allocate(&general_dma_rx, &config);
g_chan_interrupt_flag[general_dma_rx.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE);
- dma_get_config_defaults(&config);
- config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
- config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
- dma_allocate(&general_dma_tx, &config);
+ // DMA Channel 1: rx channel,
+ // normal transfer on input, trigger on each beat, beat is one byte
+ //config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
+ //config.event_config.input_action = DMA_EVENT_INPUT_TRIG;
g_chan_interrupt_flag[general_dma_tx.channel_id] |= (1UL << DMA_CALLBACK_TRANSFER_DONE);
// Be sneaky and reuse the active descriptor memory.
diff --git a/ports/atmel-samd/spi_flash.c b/ports/atmel-samd/spi_flash.c
index 8191887e4..a64c0ed33 100644
--- a/ports/atmel-samd/spi_flash.c
+++ b/ports/atmel-samd/spi_flash.c
@@ -28,20 +28,19 @@
#include <stdint.h>
#include <string.h>
-<<<<<<< HEAD
-#include "asf/sam0/drivers/sercom/spi/spi.h"
-
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
-=======
->>>>>>> WIP
#include "py/gc.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
+#include "peripherals.h"
+#include "supervisor/shared/rgb_led_status.h"
+
+//#include "shared_dma.h"
-#include "rgb_led_status.h"
-#include "shared_dma.h"
+#include "hal_gpio.h"
+#include "hal_spi_m_sync.h"
#define SPI_FLASH_PART1_START_BLOCK (0x1)
@@ -60,7 +59,7 @@
static bool spi_flash_is_initialised = false;
-struct spi_module spi_flash_instance;
+struct spi_m_sync_descriptor spi_flash_desc;
// The currently cached sector in the cache, ram or flash based.
static uint32_t current_sector;
@@ -74,35 +73,37 @@ static uint32_t dirty_mask;
// Enable the flash over SPI.
static void flash_enable(void) {
- port_pin_set_output_level(SPI_FLASH_CS, false);
+ gpio_set_pin_level(SPI_FLASH_CS_PIN, false);
}
// Disable the flash over SPI.
static void flash_disable(void) {
- port_pin_set_output_level(SPI_FLASH_CS, true);
+ gpio_set_pin_level(SPI_FLASH_CS_PIN, true);
}
// Wait until both the write enable and write in progress bits have cleared.
static bool wait_for_flash_ready(void) {
- uint8_t status_request[2] = {CMD_READ_STATUS, 0x00};
- uint8_t response[2] = {0x00, 0x01};
- enum status_code status = STATUS_OK;
+ uint8_t read_status_request[2] = {CMD_READ_STATUS, 0x00};
+ uint8_t read_status_response[2] = {0x00, 0x00};
+ struct spi_xfer read_status_xfer = {read_status_request, read_status_response, 2};
+ int32_t status;
// Both the write enable and write in progress bits should be low.
- while (status == STATUS_OK && (response[1] & 0x3) != 0) {
+ do {
flash_enable();
- status = spi_transceive_buffer_wait(&spi_flash_instance, status_request, response, 2);
+ status = spi_m_sync_transfer(&spi_flash_desc, &read_status_xfer);
flash_disable();
- }
- return status == STATUS_OK;
+ } while (status >= 0 && (read_status_response[1] & 0x3) != 0);
+ return status >= 0; // status is number of chars read or a negative error code.
}
// Turn on the write enable bit so we can program and erase the flash.
static bool write_enable(void) {
flash_enable();
- uint8_t command = CMD_ENABLE_WRITE;
- enum status_code status = spi_write_buffer_wait(&spi_flash_instance, &command, 1);
+ uint8_t enable_write_request[1] = {CMD_ENABLE_WRITE};
+ struct spi_xfer enable_write_xfer = {enable_write_request, 0, 1};
+ int32_t status = spi_m_sync_transfer(&spi_flash_desc, &enable_write_xfer);
flash_disable();
- return status == STATUS_OK;
+ return status >= 0; // status is number of chars read or a negative error code.
}
// Pack the low 24 bits of the address into a uint8_t array.
@@ -120,17 +121,19 @@ static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) {
if (!wait_for_flash_ready()) {
return false;
}
- enum status_code status;
// We can read as much as we want sequentially.
- uint8_t read_request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00};
- address_to_bytes(address, read_request + 1);
+ uint8_t read_data_request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00};
+ struct spi_xfer read_data_xfer = {read_data_request, 0, 4};
+ // Write the SPI flash read address into the bytes following the command byte.
+ address_to_bytes(address, read_data_request + 1);
flash_enable();
- status = spi_write_buffer_wait(&spi_flash_instance, read_request, 4);
- if (status == STATUS_OK) {
- status = shared_dma_read(spi_flash_instance.hw, data, data_length, 0x00);
+ int32_t status = spi_m_sync_transfer(&spi_flash_desc, &read_data_xfer);
+ struct spi_xfer read_data_buffer_xfer = {0, data, data_length};
+ if (status >= 0) {
+ status = spi_m_sync_transfer(&spi_flash_desc, &read_data_buffer_xfer);
}
flash_disable();
- return status == STATUS_OK;
+ return status >= 0;
}
// Writes data_length's worth of bytes starting at address from data. Assumes
@@ -159,26 +162,29 @@ static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_len
if (!wait_for_flash_ready() || !write_enable()) {
return false;
}
- enum status_code status;
+ int32_t status;
#ifdef SPI_FLASH_SECTOR_PROTECTION
// Print out the protection status.
// uint8_t protect_check[5] = {0x3C, 0x00, 0x00, 0x00, 0x00};
// address_to_bytes(address + bytes_written, protect_check + 1);
// flash_enable();
- // status = spi_write_buffer_wait(&spi_flash_instance, protect_check, 5);
+ // status = spi_write_buffer_wait(&spi_flash_desc, protect_check, 5);
// flash_disable();
#endif
flash_enable();
- uint8_t command[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00};
- address_to_bytes(address + bytes_written, command + 1);
- status = spi_write_buffer_wait(&spi_flash_instance, command, 4);
- if (status == STATUS_OK) {
- status = shared_dma_write(spi_flash_instance.hw, data + bytes_written, SPI_FLASH_PAGE_SIZE);
+ uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00};
+ // Write the SPI flash write address into the bytes following the command byte.
+ address_to_bytes(address + bytes_written, page_program_request + 1);
+ struct spi_xfer page_program_xfer = {page_program_request, 0, 4};
+ status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer);
+ if (status >= 0) {
+ struct spi_xfer write_data_buffer_xfer = {(uint8_t*) data + bytes_written, 0, SPI_FLASH_PAGE_SIZE};
+ status = spi_m_sync_transfer(&spi_flash_desc, &write_data_buffer_xfer);
}
flash_disable();
- if (status != STATUS_OK) {
+ if (status < 0) {
return false;
}
}
@@ -224,11 +230,11 @@ static bool erase_sector(uint32_t sector_address) {
uint8_t erase_request[4] = {CMD_SECTOR_ERASE, 0x00, 0x00, 0x00};
address_to_bytes(sector_address, erase_request + 1);
-
+ struct spi_xfer erase_xfer = {erase_request, 0, 4};
flash_enable();
- enum status_code status = spi_write_buffer_wait(&spi_flash_instance, erase_request, 4);
+ int32_t status = spi_m_sync_transfer(&spi_flash_desc, &erase_xfer);
flash_disable();
- return status == STATUS_OK;
+ return status >= 0;
}
// Sector is really 24 bits.
@@ -247,82 +253,103 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) {
}
void spi_flash_init(void) {
- if (!spi_flash_is_initialised) {
- struct spi_config config_spi_master;
- spi_get_config_defaults(&config_spi_master);
- config_spi_master.mux_setting = SPI_FLASH_MUX_SETTING;
- config_spi_master.pinmux_pad0 = SPI_FLASH_PAD0_PINMUX;
- config_spi_master.pinmux_pad1 = SPI_FLASH_PAD1_PINMUX;
- config_spi_master.pinmux_pad2 = SPI_FLASH_PAD2_PINMUX;
- config_spi_master.pinmux_pad3 = SPI_FLASH_PAD3_PINMUX;
- config_spi_master.mode_specific.master.baudrate = SPI_FLASH_BAUDRATE;
- spi_init(&spi_flash_instance, SPI_FLASH_SERCOM, &config_spi_master);
- spi_enable(&spi_flash_instance);
-
- // Manage chip select ourselves.
- struct port_config pin_conf;
- port_get_config_defaults(&pin_conf);
-
- pin_conf.direction = PORT_PIN_DIR_OUTPUT;
- port_pin_set_config(SPI_FLASH_CS, &pin_conf);
- flash_disable();
+ if (spi_flash_is_initialised) {
+ return;
+ }
+
+ samd_peripherals_sercom_clock_init(SPI_FLASH_SERCOM, SPI_FLASH_SERCOM_INDEX);
- // Activity LED for flash writes.
- #ifdef MICROPY_HW_LED_MSC
- port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf);
- port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
- #endif
+ // Set up with defaults, then change.
+ spi_m_sync_init(&spi_flash_desc, SPI_FLASH_SERCOM);
+
+ hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO);
+ hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO);
- uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00};
- uint8_t response[4] = {0x00, 0x00, 0x00, 0x00};
- flash_enable();
- spi_transceive_buffer_wait(&spi_flash_instance, jedec_id_request, response, 4);
- flash_disable();
- uint8_t manufacturer = response[1];
- if ((response[1] == SPI_FLASH_JEDEC_MANUFACTURER
- #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2
- || response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2
- #endif
- ) &&
- response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE &&
- response[3] == SPI_FLASH_JEDEC_CAPACITY) {
- spi_flash_is_initialised = true;
- } else {
- // Unknown flash chip!
- spi_flash_is_initialised = false;
- return;
- }
+ gpio_set_pin_direction(SPI_FLASH_SCK_PIN, GPIO_DIRECTION_OUT);
+ gpio_set_pin_pull_mode(SPI_FLASH_SCK_PIN, GPIO_PULL_OFF);
+ gpio_set_pin_function(SPI_FLASH_SCK_PIN, SPI_FLASH_SCK_PIN_FUNCTION);
- if ((manufacturer == SPI_FLASH_JEDEC_MANUFACTURER && SPI_FLASH_SECTOR_PROTECTION)
- #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2
- || (manufacturer == SPI_FLASH_JEDEC_MANUFACTURER_2 && SPI_FLASH_SECTOR_PROTECTION_2)
- #endif
- ) {
- write_enable();
-
- // Turn off sector protection
- uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00};
- uint8_t disable_protect_response[2] = {0x00, 0x00};
- flash_enable();
- spi_transceive_buffer_wait(&spi_flash_instance, disable_protect_request, disable_protect_response, 2);
- flash_disable();
- }
+ gpio_set_pin_direction(SPI_FLASH_MOSI_PIN, GPIO_DIRECTION_OUT);
+ gpio_set_pin_pull_mode(SPI_FLASH_MOSI_PIN, GPIO_PULL_OFF);
+ gpio_set_pin_function(SPI_FLASH_MOSI_PIN, SPI_FLASH_MOSI_PIN_FUNCTION);
- // Turn off writes in case this is a microcontroller only reset.
- uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE};
- uint8_t disable_response[1] = {0x00};
- flash_enable();
- spi_transceive_buffer_wait(&spi_flash_instance, disable_write_request, disable_response, 1);
- flash_disable();
+ gpio_set_pin_direction(SPI_FLASH_MISO_PIN, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(SPI_FLASH_MISO_PIN, GPIO_PULL_OFF);
+ gpio_set_pin_function(SPI_FLASH_MISO_PIN, SPI_FLASH_MISO_PIN_FUNCTION);
- wait_for_flash_ready();
+ hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO);
+ hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO);
- current_sector = NO_SECTOR_LOADED;
- dirty_mask = 0;
- MP_STATE_VM(flash_ram_cache) = NULL;
+ spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE));
+ gpio_set_pin_direction(SPI_FLASH_CS_PIN, GPIO_DIRECTION_OUT);
+ // There's already a pull-up on the board.
+ gpio_set_pin_pull_mode(SPI_FLASH_CS_PIN, GPIO_PULL_OFF);
+ gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF);
+
+ // Set CS high (disabled).
+ flash_disable();
+
+ spi_m_sync_enable(&spi_flash_desc);
+
+ // Activity LED for flash writes.
+#ifdef MICROPY_HW_LED_MSC
+ gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(MICROPY_HW_LED_MSC, GPIO_DIRECTION_OUT);
+ // There's already a pull-up on the board.
+ gpio_set_pin_level(MICROPY_HW_LED_MSC, false);
+#endif
+
+ uint8_t jedec_id_request[4] = {CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00};
+ uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00};
+ struct spi_xfer jedec_id_xfer = { jedec_id_request, jedec_id_response, 4 };
+ flash_enable();
+ spi_m_sync_transfer(&spi_flash_desc, &jedec_id_xfer);
+ flash_disable();
+ uint8_t manufacturer = jedec_id_response[1];
+ if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER
+#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2
+ || jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2
+#endif
+ ) &&
+ jedec_id_response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE &&
+ jedec_id_response[3] == SPI_FLASH_JEDEC_CAPACITY) {
spi_flash_is_initialised = true;
+ } else {
+ // Unknown flash chip!
+ spi_flash_is_initialised = false;
+ return;
}
+
+ if ((manufacturer == SPI_FLASH_JEDEC_MANUFACTURER && SPI_FLASH_SECTOR_PROTECTION)
+#ifdef SPI_FLASH_JEDEC_MANUFACTURER_2
+ || (manufacturer == SPI_FLASH_JEDEC_MANUFACTURER_2 && SPI_FLASH_SECTOR_PROTECTION_2)
+#endif
+ ) {
+ write_enable();
+
+ // Turn off sector protection
+ uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00};
+ struct spi_xfer disable_protect_xfer = { disable_protect_request, 0, 4 };
+ flash_enable();
+ spi_m_sync_transfer(&spi_flash_desc, &disable_protect_xfer);
+ flash_disable();
+ }
+
+ // Turn off writes in case this is a microcontroller only reset.
+ uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE};
+ struct spi_xfer disable_write_xfer = { disable_write_request, 0, 1 };
+ flash_enable();
+ spi_m_sync_transfer(&spi_flash_desc, &disable_write_xfer);
+ flash_disable();
+
+ wait_for_flash_ready();
+
+ current_sector = NO_SECTOR_LOADED;
+ dirty_mask = 0;
+ MP_STATE_VM(flash_ram_cache) = NULL;
+
+ spi_flash_is_initialised = true;
}
// The size of each individual block.
diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c
index 85c662e77..818736a78 100644
--- a/ports/atmel-samd/usb_mass_storage.c
+++ b/ports/atmel-samd/usb_mass_storage.c
@@ -271,7 +271,11 @@ int32_t usb_msc_xfer_done(uint8_t lun) {
return ERR_NONE;
}
-// The start_read callback begins a read transaction which we accept but delay our response until the "main thread" calls usb_msc_background. Once it does, we read immediately from the drive into our cache and trigger the USB DMA to output the sector. Once the sector is transmitted, xfer_done will be called.
+// The start_read callback begins a read transaction which we accept
+// but delay our response until the "main thread" calls
+// usb_msc_background. Once it does, we read immediately from the
+// drive into our cache and trigger the USB DMA to output the
+// sector. Once the sector is transmitted, xfer_done will be called.
void usb_msc_background(void) {
if (active_read && !usb_busy) {
if (active_nblocks == 0) {
@@ -290,7 +294,7 @@ void usb_msc_background(void) {
fs_user_mount_t * vfs = get_vfs(active_lun);
disk_write(vfs, sector_buffer, active_addr, 1);
// Since by getting here we assume the mount is read-only to
- // MicroPython lets update the cached FatFs sector if its the one
+ // MicroPython let's update the cached FatFs sector if it's the one
// we just wrote.
#if _MAX_SS != _MIN_SS
if (vfs->ssize == FILESYSTEM_BLOCK_SIZE) {