diff options
| author | Dan Halbert <halbert@halwitz.org> | 2018-03-22 22:01:33 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-22 22:01:33 -0400 |
| commit | 00eacbf45e970f5bdc6b868f7136c4740a356744 (patch) | |
| tree | 021ca777f93616892858544902a29f1783b17951 | |
| parent | 0c4bbefdf06cfbf1785d76d0c825694558031e12 (diff) | |
| parent | 06b4c83f59fc073e582e64f7fc09af88b4a87819 (diff) | |
Merge pull request #692 from tannewt/latest_m4
Add support for the Metro M4 Rev F and make the SPI flash code more robust
| -rw-r--r-- | ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h | 6 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/metro_m4_express/pins.c | 23 | ||||
| -rw-r--r-- | ports/atmel-samd/external_flash/common_commands.h | 3 | ||||
| -rw-r--r-- | ports/atmel-samd/external_flash/external_flash.c | 29 | ||||
| -rw-r--r-- | ports/atmel-samd/external_flash/qspi_flash.c | 11 | ||||
| -rw-r--r-- | ports/atmel-samd/external_flash/spi_flash.c | 4 | ||||
| -rw-r--r-- | ports/atmel-samd/external_flash/spi_flash_api.h | 3 |
7 files changed, 59 insertions, 20 deletions
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index b541af80c..e2b7f9982 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -3,18 +3,18 @@ #define CIRCUITPY_MCU_FAMILY samd51 -// This is for Rev D which is light blue +// This is for Rev F which is green #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB06 -#define MICROPY_HW_NEOPIXEL (&pin_PB17) +#define MICROPY_HW_NEOPIXEL (&pin_PB22) // These are pins not to reset. // QSPI Data pins and TX LED #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) // RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB22) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c index 33b69b32b..32ecdf492 100644 --- a/ports/atmel-samd/boards/metro_m4_express/pins.c +++ b/ports/atmel-samd/boards/metro_m4_express/pins.c @@ -7,36 +7,37 @@ STATIC const mp_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PB08 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 }, - + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PB09 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PB17 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PB16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PB12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA21 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA20 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA20 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), (mp_obj_t)&pin_PA03 }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB22 }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 }, { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA14 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index fc05e70de..79178af9c 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -35,7 +35,10 @@ #define CMD_PAGE_PROGRAM 0x02 // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 +#define CMD_READ_STATUS2 0x35 #define CMD_WRITE_STATUS_BYTE1 0x01 #define CMD_QUAD_READ 0x6b +#define CMD_ENABLE_RESET 0x66 +#define CMD_RESET 0x99 #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c index 304bf6462..315eb7506 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -199,10 +199,15 @@ void external_flash_init(void) { spi_flash_init(); + // The response will be 0xff if the flash needs more time to start up. + uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff}; + while (jedec_id_response[0] == 0xff) { + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + } + for (uint8_t i = 0; i < num_possible_devices; i++) { const external_flash_device* possible_device = &possible_devices[i]; - uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; - spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); + if (jedec_id_response[0] == possible_device->manufacturer_id && jedec_id_response[1] == possible_device->memory_type && jedec_id_response[2] == possible_device->capacity) { @@ -215,6 +220,26 @@ void external_flash_init(void) { return; } + // We don't know what state the flash is in so wait for any remaining writes and then reset. + uint8_t read_status_response[1] = {0x00}; + // The write in progress bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); + } while ((read_status_response[0] & 0x1) != 0); + // The suspended write/erase bit should be low. + do { + spi_flash_read_command(CMD_READ_STATUS2, read_status_response, 1); + } while ((read_status_response[0] & 0x80) != 0); + + + spi_flash_command(CMD_ENABLE_RESET); + spi_flash_command(CMD_RESET); + + // Wait 30us for the reset + common_hal_mcu_delay_us(30); + + spi_flash_init_device(flash_device); + // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 46e3cb92a..fc6c8dfea 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -174,7 +174,7 @@ void spi_flash_init(void) { // Slow, good for debugging with Saleae // QSPI->BAUD.bit.BAUD = 32; - // Super fast + // Super fast, may be unreliable when Saleae is connected to high speed lines. QSPI->BAUD.bit.BAUD = 2; QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | @@ -189,14 +189,17 @@ void spi_flash_init(void) { gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); } +} +void spi_flash_init_device(const external_flash_device* device) { // Verify that QSPI mode is enabled. uint8_t status; - spi_flash_read_command(0x35, &status, 1); + spi_flash_read_command(CMD_READ_STATUS2, &status, 1); + // Bit 1 is Quad Enable if ((status & 0x2) == 0) { - uint8_t full_status[3] = { 0, status | 0x2, 0x70}; + uint8_t full_status[2] = { 0x0, 0x2}; spi_flash_command(CMD_ENABLE_WRITE); - spi_flash_write_command(0x01, full_status, 3); + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); } } diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index fcaedcaac..8a8cbaef8 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -152,3 +152,7 @@ void spi_flash_init(void) { spi_m_sync_enable(&spi_flash_desc); } + +void spi_flash_init_device(const external_flash_device* device) { + +} diff --git a/ports/atmel-samd/external_flash/spi_flash_api.h b/ports/atmel-samd/external_flash/spi_flash_api.h index b858ff0ea..a6df0c459 100644 --- a/ports/atmel-samd/external_flash/spi_flash_api.h +++ b/ports/atmel-samd/external_flash/spi_flash_api.h @@ -29,6 +29,8 @@ #include <stdbool.h> #include <stdint.h> +#include "external_flash/devices.h" + // This API is implemented for both normal SPI peripherals and QSPI peripherals. bool spi_flash_command(uint8_t command); @@ -38,5 +40,6 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address); bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length); bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); void spi_flash_init(void); +void spi_flash_init_device(const external_flash_device* device); #endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H |
