diff options
| author | Max Holliday <maholli@stanford.edu> | 2020-04-07 18:17:25 -0700 |
|---|---|---|
| committer | Max Holliday <maholli@stanford.edu> | 2020-04-07 18:17:25 -0700 |
| commit | 826837186c9668805b58edb4e57b68363aba0149 (patch) | |
| tree | a0751b7fa01917614a4d6ba806d9847b47e93d18 /supervisor | |
| parent | 78c144876487d21aa6f7fa97ae9482bc43246cf4 (diff) | |
adds standard (non-queued) SPI support to QSPI for external flash
Diffstat (limited to 'supervisor')
| -rw-r--r-- | supervisor/shared/external_flash/common_commands.h | 1 | ||||
| -rw-r--r-- | supervisor/shared/external_flash/devices.h | 17 | ||||
| -rw-r--r-- | supervisor/shared/external_flash/external_flash.c | 105 |
3 files changed, 78 insertions, 45 deletions
diff --git a/supervisor/shared/external_flash/common_commands.h b/supervisor/shared/external_flash/common_commands.h index cc0da2175..2eaa84833 100644 --- a/supervisor/shared/external_flash/common_commands.h +++ b/supervisor/shared/external_flash/common_commands.h @@ -43,5 +43,6 @@ #define CMD_QUAD_READ 0x6b #define CMD_ENABLE_RESET 0x66 #define CMD_RESET 0x99 +#define CMD_WAKE 0xab #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_COMMON_COMMANDS_H diff --git a/supervisor/shared/external_flash/devices.h b/supervisor/shared/external_flash/devices.h index fd9224f56..05e9e3c95 100644 --- a/supervisor/shared/external_flash/devices.h +++ b/supervisor/shared/external_flash/devices.h @@ -426,6 +426,23 @@ typedef struct { .single_status_byte = false, \ } +// Everspin MRAM +#define MR2xH40 {\ + .total_size = (1 << 22), /* 4 MiB */ \ + .start_up_time_us = 10000, \ + .manufacturer_id = 0xef, /*no JDEC*/ \ + .memory_type = 0x40, /*no JDEC*/ \ + .capacity = 0x14, /*no JDEC*/ \ + .max_clock_speed_mhz = 40, \ + .quad_enable_bit_mask = 0x00, \ + .has_sector_protection = false, \ + .supports_fast_read = false, \ + .supports_qspi = false, \ + .supports_qspi_writes = false, \ + .write_status_register_split = false, \ + .single_status_byte = true, \ +} + // Settings for the Macronix MX25L1606 2MiB SPI flash. // Datasheet: #define MX25L1606 {\ diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 9d38c07d8..7f5496d3a 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -27,7 +27,7 @@ #include <stdint.h> #include <string.h> - +#include "mpconfigboard.h" #include "supervisor/spi_flash_api.h" #include "supervisor/shared/external_flash/common_commands.h" #include "extmod/vfs.h" @@ -57,13 +57,18 @@ static supervisor_allocation* supervisor_cache = NULL; // Wait until both the write enable and write in progress bits have cleared. static bool wait_for_flash_ready(void) { - uint8_t read_status_response[1] = {0x00}; bool ok = true; // Both the write enable and write in progress bits should be low. - do { - ok = spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); - } while (ok && (read_status_response[0] & 0x3) != 0); - return ok; + #ifdef EXTERNAL_FLASH_QSPI_SINGLE + // For NVM without a ready bit in status register + return ok; + #else + uint8_t read_status_response[1] = {0x00}; + do { + ok = spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); + } while (ok && (read_status_response[0] & 0x3) != 0); + return ok; + #endif } // Turn on the write enable bit so we can program and erase the flash. @@ -91,16 +96,18 @@ static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_len } // Don't bother writing if the data is all 1s. Thats equivalent to the flash // state after an erase. - bool all_ones = true; - for (uint16_t i = 0; i < data_length; i++) { - if (data[i] != 0xff) { - all_ones = false; - break; + #ifndef EXTERNAL_FLASH_QSPI_SINGLE + bool all_ones = true; + for (uint16_t i = 0; i < data_length; i++) { + if (data[i] != 0xff) { + all_ones = false; + break; + } } - } - if (all_ones) { - return true; - } + if (all_ones) { + return true; + } + #endif for (uint32_t bytes_written = 0; bytes_written < data_length; @@ -191,41 +198,49 @@ void supervisor_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 < EXTERNAL_FLASH_DEVICE_COUNT; i++) { - const external_flash_device* possible_device = &possible_devices[i]; - if (jedec_id_response[0] == possible_device->manufacturer_id && - jedec_id_response[1] == possible_device->memory_type && - jedec_id_response[2] == possible_device->capacity) { +#ifdef EXTERNAL_FLASH_QSPI_SINGLE + // For NVM that don't have JEDEC response + spi_flash_command(CMD_WAKE); + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { + const external_flash_device* possible_device = &possible_devices[i]; flash_device = possible_device; break; } - } - - if (flash_device == NULL) { - 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); - +#else + // 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); + } - spi_flash_command(CMD_ENABLE_RESET); - spi_flash_command(CMD_RESET); + for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { + const external_flash_device* possible_device = &possible_devices[i]; + if (jedec_id_response[0] == possible_device->manufacturer_id && + jedec_id_response[1] == possible_device->memory_type && + jedec_id_response[2] == possible_device->capacity) { + flash_device = possible_device; + break; + } + } +#endif + if (flash_device == NULL) { + 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); +#ifndef EXTERNAL_FLASH_QSPI_SINGLE + // 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); +#endif // Wait 30us for the reset common_hal_mcu_delay_us(30); |
