Update Metro M4 to rev F and make flash reset on start.

This commit is contained in:
Scott Shawcroft 2018-03-22 16:42:47 -07:00
parent 0c4bbefdf0
commit 3bf4d69f67
7 changed files with 58 additions and 19 deletions

View File

@ -3,18 +3,18 @@
#define CIRCUITPY_MCU_FAMILY samd51 #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_TX PIN_PA27
#define MICROPY_HW_LED_RX PIN_PB06 #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. // These are pins not to reset.
// QSPI Data pins and TX LED // QSPI Data pins and TX LED
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27)
// RX LED, QSPI CS, QSPI SCK and NeoPixel pin // 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_C (0)
#define MICROPY_PORT_D (0) #define MICROPY_PORT_D (0)

View File

@ -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_A0), (mp_obj_t)&pin_PA02 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 }, { 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_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_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_D0), (mp_obj_t)&pin_PA23 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX), (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_D1), (mp_obj_t)&pin_PA22 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TX), (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_D3), (mp_obj_t)&pin_PB16 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB13 }, { 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_D5), (mp_obj_t)&pin_PB14 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 }, { 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_D7), (mp_obj_t)&pin_PB12 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA21 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 }, { 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_D10), (mp_obj_t)&pin_PA18 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 }, { 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_D12), (mp_obj_t)&pin_PA17 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 }, { 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_SDA), (mp_obj_t)&pin_PB02 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 }, { 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_SCK), (mp_obj_t)&pin_PA13 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 }, { 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_RX), (mp_obj_t)&pin_PB06 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 },

View File

@ -35,7 +35,10 @@
#define CMD_PAGE_PROGRAM 0x02 #define CMD_PAGE_PROGRAM 0x02
// #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID
#define CMD_READ_STATUS 0x05 #define CMD_READ_STATUS 0x05
#define CMD_READ_STATUS2 0x35
#define CMD_WRITE_STATUS_BYTE1 0x01 #define CMD_WRITE_STATUS_BYTE1 0x01
#define CMD_QUAD_READ 0x6b #define CMD_QUAD_READ 0x6b
#define CMD_ENABLE_RESET 0x66
#define CMD_RESET 0x99
#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H

View File

@ -199,10 +199,15 @@ void external_flash_init(void) {
spi_flash_init(); 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++) { for (uint8_t i = 0; i < num_possible_devices; i++) {
const external_flash_device* possible_device = &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 && if (jedec_id_response[0] == possible_device->manufacturer_id &&
jedec_id_response[1] == possible_device->memory_type && jedec_id_response[1] == possible_device->memory_type &&
jedec_id_response[2] == possible_device->capacity) { jedec_id_response[2] == possible_device->capacity) {
@ -215,6 +220,26 @@ void external_flash_init(void) {
return; 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. // Activity LED for flash writes.
#ifdef MICROPY_HW_LED_MSC #ifdef MICROPY_HW_LED_MSC
gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF);

View File

@ -189,14 +189,17 @@ void spi_flash_init(void) {
gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF); gpio_set_pin_pull_mode(pins[i], GPIO_PULL_OFF);
gpio_set_pin_function(pins[i], GPIO_PIN_FUNCTION_H); 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. // Verify that QSPI mode is enabled.
uint8_t status; 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) { 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_command(CMD_ENABLE_WRITE);
spi_flash_write_command(0x01, full_status, 3); spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2);
} }
} }

View File

@ -152,3 +152,7 @@ void spi_flash_init(void) {
spi_m_sync_enable(&spi_flash_desc); spi_m_sync_enable(&spi_flash_desc);
} }
void spi_flash_init_device(const external_flash_device* device) {
}

View File

@ -29,6 +29,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "external_flash/devices.h"
// This API is implemented for both normal SPI peripherals and QSPI peripherals. // This API is implemented for both normal SPI peripherals and QSPI peripherals.
bool spi_flash_command(uint8_t command); 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_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); bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length);
void spi_flash_init(void); void spi_flash_init(void);
void spi_flash_init_device(const external_flash_device* device);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H #endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H