Skip to content

SPI Flash Issue - SST26VF016B drive not showing #1530

@wallarug

Description

@wallarug

Hi Adafruit Community!

I have been trying to make a custom CircuitPython package for a new board that I have created based around the M0. I am having issues getting the CIRCUITPY USB drive to show up for CircuitPython when attached to a USB port.

COM port is present and working (can log into CircuitPython and use it).

I am using a flash chip that does not appear to be supported by CircuitPython or I am making a mistake somewhere. It is using the SST26VF016B which should be a drop in replacement for the supported S25FL116K 2MiB flash chip.

I can only get the USB drive to show if I use "internal flash". The pre-compiled firmware for Feather M0 Basic works perfectly. The Feather M0 Express does not (even though I used the same SPI pin out as this board).

I have attached the files that I used to customize the CircuitPython install for my board (MM1 HAT).

I do not normally work with such a low level of commands / hardware. I love CircuitPython though!

Any assistance in identifying why the USB drive does not appear would be greatly appreciated!!

Thank you in advance.

Appendix

modified supervisor/shared/external_flash/devices.h

. . .
// Settings for the SST26VF016B 2MiB SPI flash.
// Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20005262D.pdf
#define ST26VF016B {\
    .total_size = (1 << 21), /* 2 MiB */ \
    .start_up_time_us = 10000, \
    .manufacturer_id = 0xbf, \
    .memory_type = 0x26, \
    .capacity = 0x15, \
    .max_clock_speed_mhz = 104, \
    .quad_enable_bit_mask = 0x02, \
    .has_sector_protection = false, \
    .supports_fast_read = true, \
    .supports_qspi = true, \
    .supports_qspi_writes = false, \
    .write_status_register_split = false, \
    .single_status_byte = false, \
}
. . .

ports/at-samd/

Build by:

make -j8 BOARD=mm1_hat

boards/mm1_hat/board.c

#include "boards/board.h"

void board_init(void)
{
}

bool board_requests_safe_mode(void) {
    return false;
}

void reset_board(void) {
}

boards/mm1_hat/mpconfigboard.h

#define MICROPY_HW_BOARD_NAME "Robotics Masters MM1 HAT"
#define MICROPY_HW_MCU_NAME "samd21g18"

#define MICROPY_HW_LED_STATUS   (&pin_PA12)

//#define MICROPY_HW_NEOPIXEL (&pin_PA06)


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

// On-board flash
#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

// These are pins not to reset.
#define MICROPY_PORT_A        ( 0 ) //PORT_PA06
#define MICROPY_PORT_B        ( 0 )
#define MICROPY_PORT_C        ( 0 )


// If you change this, then make sure to update the linker scripts as well to
// make sure you don't overwrite code.
#define CIRCUITPY_INTERNAL_NVM_SIZE 256

#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)

//#define BOARD_HAS_CRYSTAL 0
#define CALIBRATE_CRYSTALLESS 1

#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
#define DEFAULT_I2C_BUS_SDA (&pin_PA22)

#define DEFAULT_SPI_BUS_SCK (&pin_PA05)
#define DEFAULT_SPI_BUS_MOSI (&pin_PA07)
#define DEFAULT_SPI_BUS_MISO (&pin_PA06)

#define DEFAULT_UART_BUS_RX (&pin_PB23)
#define DEFAULT_UART_BUS_TX (&pin_PB22)

// USB is always used internally so skip the pin objects for it.
#define IGNORE_PIN_PA24     1
#define IGNORE_PIN_PA25     1

#define CIRCUITPY_I2CSLAVE
#define CIRCUITPY_DISPLAYIO (0)

boards/mm1_hat/mpconfigboard.mk

LD_FILE = boards/samd21x18-bootloader-external-flash.ld
USB_VID = 0x0005
USB_PID = 0x0005
USB_PRODUCT = "MM1 HAT"
USB_MANUFACTURER = "Robotics Masters"

SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = ST26VF016B
LONGINT_IMPL = MPZ

CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

CFLAGS_INLINE_LIMIT = 55

# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Crickit
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw

boards/mm1_hat/pins.c

#include "shared-bindings/board/__init__.h"

#include "supervisor/shared/board_busses.h"

STATIC const mp_rom_map_elem_t board_global_dict_table[] = {	
	// SIGNAL I/O Pins (Primary)
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL1), MP_ROM_PTR(&pin_PB02) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL2), MP_ROM_PTR(&pin_PB03) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL3), MP_ROM_PTR(&pin_PB08) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL4), MP_ROM_PTR(&pin_PB09) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL5), MP_ROM_PTR(&pin_PA15) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL6), MP_ROM_PTR(&pin_PA18) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL7), MP_ROM_PTR(&pin_PB22) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL8), MP_ROM_PTR(&pin_PB23) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL9), MP_ROM_PTR(&pin_PA02) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL10), MP_ROM_PTR(&pin_PA03) },
	{ MP_ROM_QSTR(MP_QSTR_SIGNAL11), MP_ROM_PTR(&pin_PA12) },
	
	// SERVO Pins (Primary)
	{ MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_PB10) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_PB11) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_PA20) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_PA21) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO5), MP_ROM_PTR(&pin_PA10) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO6), MP_ROM_PTR(&pin_PA11) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO7), MP_ROM_PTR(&pin_PA16) },
	{ MP_ROM_QSTR(MP_QSTR_SERVO8), MP_ROM_PTR(&pin_PA17) },
	
	// RC_CH Pins (Primary)
	{ MP_ROM_QSTR(MP_QSTR_RCH1), MP_ROM_PTR(&pin_PA04) },
	{ MP_ROM_QSTR(MP_QSTR_RCH2), MP_ROM_PTR(&pin_PA05) },
	{ MP_ROM_QSTR(MP_QSTR_RCH3), MP_ROM_PTR(&pin_PA06) },
	{ MP_ROM_QSTR(MP_QSTR_RCH4), MP_ROM_PTR(&pin_PA07) },
	
	// Special Function (Primary)
	{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA19) },
	{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
	{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
	{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB22) },
	{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB23) },
	
	// SPI on SERCOM4(Secondary)
	{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
	{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB08) },
	{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
	{ MP_ROM_QSTR(MP_QSTR_SS1), MP_ROM_PTR(&pin_PB09) },
	{ MP_ROM_QSTR(MP_QSTR_SS2), MP_ROM_PTR(&pin_PB03) },
	
	// I2C on SERCOM1 (Secondary)
	{ MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_PA16) },
	{ MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_PA17) },
	
	// GPS on SERCOM1 (Secondary)
	{ MP_ROM_QSTR(MP_QSTR_GPS_SDA), MP_ROM_PTR(&pin_PA16) },
	{ MP_ROM_QSTR(MP_QSTR_GPS_SCL), MP_ROM_PTR(&pin_PA17) },
	{ MP_ROM_QSTR(MP_QSTR_GPS_TX), MP_ROM_PTR(&pin_PA18) },
	{ MP_ROM_QSTR(MP_QSTR_GPS_RX), MP_ROM_PTR(&pin_PA19) },
	
	// UART on SERCOM0 (Secondary)
	{ MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_PA04) },
	{ MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_PA05) },
	{ MP_ROM_QSTR(MP_QSTR_UART_RTS), MP_ROM_PTR(&pin_PA06) },
	{ MP_ROM_QSTR(MP_QSTR_UART_CTS), MP_ROM_PTR(&pin_PA07) },
	
	// Raspberry Pi (Secondary)
	{ MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_PTR(&pin_PA30) },
	{ MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_PTR(&pin_PA31) },
	{ MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_PTR(&pin_PA28) },
	{ MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_PTR(&pin_PA27) },
	{ MP_ROM_QSTR(MP_QSTR_PI_RX), MP_ROM_PTR(&pin_PB22) },
	{ MP_ROM_QSTR(MP_QSTR_PI_TX), MP_ROM_PTR(&pin_PB23) },
	
	{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
	{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
	{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions