Skip to content

Support SPI flash chips for CIRCUITPY, using non-DMA SPI for now. #465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ports/atmel-samd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ SRC_C = \
mphalport.c \
reset.c \
$(CHIP_FAMILY)_peripherals.c \
peripherals.c \
$(CHIP_FAMILY)_pins.c \
tick.c \
usb.c \
Expand Down Expand Up @@ -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 \
Expand All @@ -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 \
Expand Down
2 changes: 1 addition & 1 deletion ports/atmel-samd/asf4
38 changes: 24 additions & 14 deletions ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
37 changes: 23 additions & 14 deletions ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#define USB_REPL

#define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 Express"
#define MICROPY_HW_MCU_NAME "samd21g18"

Expand All @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion ports/atmel-samd/boards/metro_m0_express/pins.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why delete this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted it because it looked like something you might have added for debugging. There are no other named pins for the flash chip (e.g., no FLASH_SCK, etc.). And there were no similar named pins on the Feather M0, so I thought it was just for testing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that may be a hangover from when the SPI bus was shared. Should the others be added or this deleted?

Copy link
Collaborator Author

@dhalbert dhalbert Nov 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave it deleted for now because end-user use of these pins will mess up CIRCUITPY support. If we had some API for enabling/disabling CIRCUITPY on the flash chip, then someone could use the flash chip for something else besides a filesystem, but right now it's dedicated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Approved!

};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
49 changes: 33 additions & 16 deletions ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
3 changes: 1 addition & 2 deletions ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion ports/atmel-samd/common-hal/busio/I2C.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 11 additions & 18 deletions ports/atmel-samd/common-hal/busio/SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -78,15 +68,15 @@ 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++) {
if (!mosi_none) {
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
}
Expand Down Expand Up @@ -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);
Expand All @@ -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.");
}
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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,
Expand All @@ -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.
}
5 changes: 4 additions & 1 deletion ports/atmel-samd/common-hal/storage/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine it'd be enough. It shouldn't require a serial connection to be true.

if (usb_connected()) {
mp_raise_RuntimeError("Cannot remount '/' when USB is active.");
}

Expand Down
2 changes: 1 addition & 1 deletion ports/atmel-samd/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 }, \
Expand Down
Loading