From 15f626be5869a2dc5d8bc53ad44cc678bb5462d2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Sat, 17 Feb 2018 00:29:03 -0800 Subject: [PATCH] m4 qspi works. m0 compiles --- .../circuitplayground_express/mpconfigboard.h | 6 +- .../boards/feather_m0_express/mpconfigboard.h | 6 +- .../feather_m0_supersized/mpconfigboard.h | 4 +- .../boards/itsybitsy_m0/mpconfigboard.h | 8 +-- .../boards/metro_m0_express/mpconfigboard.h | 6 +- .../boards/metro_m4_express/mpconfigboard.h | 4 +- .../trinket_m0_haxpress/mpconfigboard.h | 4 +- .../atmel-samd/boards/ugame10/mpconfigboard.h | 6 +- .../external_flash/common_commands.h | 1 + .../external_flash/external_flash.c | 15 +++-- ports/atmel-samd/external_flash/qspi_flash.c | 65 +++++++++++++++---- ports/atmel-samd/external_flash/spi_flash.c | 58 ++++++++++------- 12 files changed, 121 insertions(+), 62 deletions(-) diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 2b8fed6b8b..cc09d7f790 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -38,7 +38,7 @@ #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -47,8 +47,8 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" #define CALIBRATE_CRYSTALLESS 1 diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index d0e70d954b..378b0891ad 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -31,7 +31,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -40,5 +40,5 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index 4f9b177bec..b5ed682962 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -42,4 +42,4 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL064L.h" +#include "external_flash/devices/S25FL064L.h" diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h index 116775886c..15a9922211 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -33,7 +33,7 @@ #define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) #define MICROPY_PORT_C (0) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -41,6 +41,6 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "flash_S25FL216K.h" -#include "flash_W25Q80DV.h" -//#include "flash_GD25Q16C.h" +//#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/W25Q80DV.h" +//#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index be1a1a57e0..70e830620d 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -34,7 +34,7 @@ #define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) #define MICROPY_PORT_C (0) -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -43,5 +43,5 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_S25FL216K.h" -#include "flash_GD25Q16C.h" +#include "external_flash/devices/S25FL216K.h" +#include "external_flash/devices/GD25Q16C.h" diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index 6ced2ca706..b8f14e6253 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -33,8 +33,8 @@ #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_PB10 | PORT_PB11 | PORT_PB17) +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB17) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 5dcea945ac..62bca9a413 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -40,7 +40,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -48,4 +48,4 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "flash_W25Q32BV.h" +#include "external_flash/devices/W25Q32BV.h" diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index 3bec61ff96..d0d9296a40 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -33,7 +33,7 @@ #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash.h" +#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -41,5 +41,5 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -//#include "flash_W25Q32BV.h" -#include "flash_S25FL216K.h" +//#include "external_flash/devices/W25Q32BV.h" +#include "external_flash/devices/S25FL216K.h" diff --git a/ports/atmel-samd/external_flash/common_commands.h b/ports/atmel-samd/external_flash/common_commands.h index ca1e877823..fc05e70de7 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/ports/atmel-samd/external_flash/common_commands.h @@ -36,5 +36,6 @@ // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 #define CMD_WRITE_STATUS_BYTE1 0x01 +#define CMD_QUAD_READ 0x6b #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 c046047e4f..48872adda7 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/ports/atmel-samd/external_flash/external_flash.c @@ -195,19 +195,20 @@ void external_flash_init(void) { gpio_set_pin_level(MICROPY_HW_LED_MSC, false); #endif - uint8_t jedec_id_response[4] = {0x00, 0x00, 0x00, 0x00}; - spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 4); + uint8_t jedec_id_response[3] = {0x00, 0x00, 0x00}; + spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3); - uint8_t manufacturer = jedec_id_response[1]; - if ((jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER + uint8_t manufacturer = jedec_id_response[0]; + if ((jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER #ifdef SPI_FLASH_JEDEC_MANUFACTURER_2 - || jedec_id_response[1] == SPI_FLASH_JEDEC_MANUFACTURER_2 + || jedec_id_response[0] == SPI_FLASH_JEDEC_MANUFACTURER_2 #endif ) && - jedec_id_response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && - jedec_id_response[3] == SPI_FLASH_JEDEC_CAPACITY) { + jedec_id_response[1] == SPI_FLASH_JEDEC_MEMORY_TYPE && + jedec_id_response[2] == SPI_FLASH_JEDEC_CAPACITY) { spi_flash_is_initialised = true; } else { + asm("bkpt"); // Unknown flash chip! spi_flash_is_initialised = false; return; diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c index 42d4e5a420..d9dc3bf01e 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/external_flash/qspi_flash.c @@ -95,23 +95,66 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { } bool spi_flash_sector_command(uint8_t command, uint32_t address) { -// QSPI->INSTRCTRL.bit.INSTR = command; -// QSPI->INSTRADDR.reg = addr; -// uint32_t iframe = QSPI->INSTRFRAME.reg; -// -// iframe = QSPI_INSTRFRAME_WIDTH(instr->ioFormat) | instr->options | -// QSPI_INSTRFRAME_OPTCODELEN(instr->opcodeLen) | (instr->addrLen << QSPI_INSTRFRAME_ADDRLEN_Pos) | -// ( instr->continuousRead << QSPI_INSTRFRAME_CRMODE_Pos) | QSPI_INSTRFRAME_TFRTYPE(instr->type) | QSPI_INSTRFRAME_DUMMYLEN(instr->dummylen); -// -// QSPI->INSTRFRAME.reg = iframe; + QSPI->INSTRCTRL.bit.INSTR = command; + QSPI->INSTRADDR.bit.ADDR = address; + + QSPI->INSTRFRAME.reg = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_WRITE | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN; + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } -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 length) { + QSPI->INSTRCTRL.bit.INSTR = CMD_PAGE_PROGRAM; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI; + + QSPI->INSTRFRAME.reg = mode | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_WRITEMEMORY | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN | + QSPI_INSTRFRAME_DATAEN; + + memcpy(((uint8_t *) QSPI_AHB) + address, data, length); + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } -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 length) { + QSPI->INSTRCTRL.bit.INSTR = CMD_QUAD_READ; + uint32_t mode = QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT; + + QSPI->INSTRFRAME.reg = mode | + QSPI_INSTRFRAME_ADDRLEN_24BITS | + QSPI_INSTRFRAME_TFRTYPE_READMEMORY | + QSPI_INSTRFRAME_INSTREN | + QSPI_INSTRFRAME_ADDREN | + QSPI_INSTRFRAME_DATAEN | + QSPI_INSTRFRAME_DUMMYLEN(8); + + memcpy(data, ((uint8_t *) QSPI_AHB) + address, length); + + QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; + + while( !QSPI->INTFLAG.bit.INSTREND ); + + QSPI->INTFLAG.reg = QSPI_INTFLAG_INSTREND; + return true; } diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c index 9695067f17..4b63132eea 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/ports/atmel-samd/external_flash/spi_flash.c @@ -23,11 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "spi_flash.h" +#include "spi_flash_api.h" #include #include +#include "external_flash/common_commands.h" #include "peripherals.h" #include "hal_gpio.h" @@ -45,11 +46,32 @@ static void flash_disable(void) { gpio_set_pin_level(SPI_FLASH_CS_PIN, true); } -void spi_flash_command(uint8_t* request, uint8_t* response, uint32_t length) { - struct spi_xfer xfer = { request, response, length }; +static bool transfer(uint8_t* command, uint32_t command_length, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { + struct spi_xfer xfer = { command, NULL, command_length }; flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &xfer); + int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); + if (status >= 0 && !(data_in == NULL && data_out == NULL)) { + struct spi_xfer data_xfer = {data_in, data_out, data_length}; + status = spi_m_sync_transfer(&spi_flash_desc, &data_xfer); + } flash_disable(); + return status >= 0; +} + +static bool transfer_command(uint8_t command, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { + return transfer(&command, 1, data_in, data_out, data_length); +} + +bool spi_flash_command(uint8_t command) { + return transfer_command(command, NULL, NULL, 0); +} + +bool spi_flash_read_command(uint8_t command, uint8_t* data, uint32_t data_length) { + return transfer_command(command, NULL, data, data_length); +} + +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t data_length) { + return transfer_command(command, data, NULL, data_length); } // Pack the low 24 bits of the address into a uint8_t array. @@ -59,32 +81,24 @@ static void address_to_bytes(uint32_t address, uint8_t* bytes) { bytes[2] = address & 0xff; } -void spi_flash_sector_command(uint8_t command, uint32_t address) { +bool spi_flash_sector_command(uint8_t command, uint32_t address) { uint8_t request[4] = {command, 0x00, 0x00, 0x00}; - address_to_bytes(address, page_program_request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; - flash_enable(); - spi_m_sync_transfer(&spi_flash_desc, &xfer); - flash_disable(); + address_to_bytes(address, request + 1); + return transfer(request, 4, NULL, NULL, 0); } bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) { - flash_enable(); - uint8_t page_program_request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; + uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. - address_to_bytes(address, page_program_request + 1); - struct spi_xfer page_program_xfer = {request, 0, request_length}; - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &page_program_xfer); - if (status >= 0) { - struct spi_xfer write_data_buffer_xfer = {data, 0, data_length}; - status = spi_m_sync_transfer(&spi_flash_desc, &write_data_buffer_xfer); - } - flash_disable(); - return status >= 0; + address_to_bytes(address, request + 1); + return transfer(request, 4, data, NULL, data_length); } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { - + uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + // Write the SPI flash write address into the bytes following the command byte. + address_to_bytes(address, request + 1); + return transfer(request, 4, NULL, data, data_length); } void spi_flash_init(void) {