Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: main.cpp
- Revision:
- 2:3165b07182ad
- Parent:
- 1:cc0165946232
- Child:
- 5:da509493e3e6
--- a/main.cpp Fri Dec 08 10:48:19 2017 -0600 +++ b/main.cpp Mon Sep 03 14:02:44 2018 +0200 @@ -1,240 +1,365 @@ #include "mbed.h" -#include "cmsis_os.h" -#include "PinNames.h" #include "QSPI.h" // The below values are command codes defined in Datasheet for MX25R6435F Macronix Flash Memory +// should work for whole MX25RXX35F chip family + // Command for reading status register #define QSPI_STD_CMD_RDSR 0x05 -// Command for writing status register +// Command for reading configuration register +#define QSPI_STD_CMD_RDCR 0x15 +// Command for writing status/configuration register #define QSPI_STD_CMD_WRSR 0x01 -// Command for reading control register (supported only by some memories) -#define QSPI_STD_CMD_RDCR 0x35 -// Command for writing control register (supported only by some memories) -#define QSPI_STD_CMD_WRCR 0x3E -// Command for setting Reset Enable (supported only by some memories) -#define QSPI_STD_CMD_RSTEN 0x66 -// Command for setting Reset (supported only by some memories) -#define QSPI_STD_CMD_RST 0x99 // Command for setting WREN (supported only by some memories) #define QSPI_STD_CMD_WREN 0x06 // Command for Sector erase (supported only by some memories) #define QSPI_STD_CMD_SECT_ERASE 0x20 +// +#define QSPI_STD_CMD_WRITE_1IO 0x02 // 1-1-1 mode +#define QSPI_STD_CMD_WRITE_4IO 0x38 // 1-4-4 mode +#define QSPI_STD_CMD_READ_1IO 0x03 // 1-1-1 mode +#define QSPI_STD_CMD_READ_4IO 0xEB // 1-4-4 mode + +#define QSPI_STD_CMD_RSTEN 0x66 +// Command for setting Reset (supported only by some memories) +#define QSPI_STD_CMD_RST 0x99 + +#define STATUS_BIT_WIP (1 << 0) // write in progress bit +#define STATUS_BIT_QE (1 << 6) // Quad Enable + +#define QSPI_STATUS_REG_SIZE 1 + +#define QSPI_READ_4IO_DUMMY_CYCLE 6 + +#define QSPI_MAX_WAIT_TIME 1000 // 1000 ms + + + //#define DEBUG_ON 1 #ifdef DEBUG_ON - #define VERBOSE_PRINT(x) printf x -#else - #define VERBOSE_PRINT(x) +#define VERBOSE_PRINT(x) printf x +#else +#define VERBOSE_PRINT(x) #endif -QSPI *myQspi = NULL; - -bool InitializeFlashMem(); -bool WaitForMemReady(); -bool SectorErase(unsigned int flash_addr); -bool WriteReadSimple(); - + +bool InitializeFlashMem(QSPI &qspi); +bool WaitForMemReady(QSPI &qspi); +bool SectorErase(QSPI &qspi, unsigned int flash_addr); + +bool WriteReadQuad(QSPI &qspi, unsigned int flash_addr); + +bool QuadEnable(QSPI &qspi); +bool QuadDisable(QSPI &qspi); + + +#define TEST_FLASH_ADDRESS 0x1000 + // main() runs in its own thread in the OS -int main() { - myQspi = new QSPI((PinName)QSPI_PIN_IO0, (PinName)QSPI_PIN_IO1, (PinName)QSPI_PIN_IO2, (PinName)QSPI_PIN_IO3, (PinName)QSPI_PIN_SCK, (PinName)QSPI_PIN_CSN); - if(myQspi) { - printf("\nCreated QSPI driver object succesfully"); +int main() +{ + printf(">>> Start...\r\n"); + QSPI myQspi((PinName)QSPI_FLASH1_IO0, (PinName)QSPI_FLASH1_IO1, (PinName)QSPI_FLASH1_IO2, (PinName)QSPI_FLASH1_IO3, (PinName)QSPI_FLASH1_SCK, (PinName)QSPI_FLASH1_CSN); + + if (QSPI_STATUS_OK == myQspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0)) { + printf("[main] Configured QSPI driver succesfully: 1-1-1\r\n"); } else { - printf("\nERROR: Failed creating QSPI driver object"); + printf("[main] ERROR: Failed configuring QSPI driver\r\n"); return -1; } - - printf("\n\nQSPI Config = 1_4_4"); - if(QSPI_STATUS_OK == myQspi->configure_format( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_NONE, QSPI_CFG_BUS_QUAD, 0, 0 )) { - printf("\nConfigured QSPI driver configured succesfully"); - } else { - printf("\nERROR: Failed configuring QSPI driver"); + + if (false == InitializeFlashMem(myQspi)) { + printf("[main] Unable to initialize flash memory, tests failed\r\n"); return -1; } - - if( false == InitializeFlashMem()) { - printf("\nUnable to initialize flash memory, tests failed\n"); + + if (false == WriteReadQuad(myQspi, TEST_FLASH_ADDRESS)) { + printf("[main] Unable to read/write using QuadSPI\r\n"); return -1; } - - if( false == WriteReadSimple() ) { - printf("\nUnable to read/write using QuadSPI\n"); - return -1; - } - - printf("\nDone...\n"); + + printf("<<< Done...\r\n"); } -bool WriteReadSimple() +bool WriteReadQuad(QSPI &qspi, unsigned int flash_addr) { int result = 0; - char tx_buf[] = { 'H', 'E', 'L', 'L', 'O', ' ', 'Q', 'U', 'A', 'D', '-', 'S', 'P', 'I', '!', 0 }; - char rx_buf[16]; + char tx_buf[] = { 'H', 'E', 'L', 'L', 'O', ' ', 'Q', 'U', 'A', 'D', '-', 'S', 'P', 'I', '!', 0 }; + char rx_buf[16]; size_t buf_len = sizeof(tx_buf); - - uint32_t flash_addr = 0x1000; - if( false == SectorErase(flash_addr)) { - printf("\nERROR: SectorErase failed(addr = 0x%08X)\n", flash_addr); + + if (false == SectorErase(qspi, flash_addr)) { + printf("[WriteReadQuad] ERROR: SectorErase failed(addr = 0x%08lX)\r\n", flash_addr); + return false; + } + + if (false == QuadEnable(qspi)) { + printf("[WriteReadQuad] ERROR: Quad enable failed\r\n"); return false; } - - if( false == WaitForMemReady()) { - printf("\nERROR: Device not ready, tests failed\n"); + + // Send write enable + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[WriteReadQuad] Sending WREN command success\r\n")); + } else { + printf("[WriteReadQuad] ERROR: Sending WREN command failed\r\n"); + return false; + } + + if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 0)) { + printf("[WriteReadQuad] Configured QSPI driver succesfully: 1-4-4\r\n"); + } else { + printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n"); + return -1; + } + + printf("[WriteReadQuad] Writing: %s\r\n", tx_buf); + result = qspi.write(QSPI_STD_CMD_WRITE_4IO, 0, flash_addr, tx_buf, &buf_len); + if ((result != QSPI_STATUS_OK) || buf_len != sizeof(tx_buf)) { + printf("[WriteReadQuad] ERROR: Write failed\r\n"); + } + + if (false == WaitForMemReady(qspi)) { + printf("[WriteReadQuad] ERROR: Device not ready, tests failed\r\n"); return false; } - - printf("\nWriting: %s", tx_buf); - result = myQspi->write( flash_addr, tx_buf, &buf_len ); - if( ( result != QSPI_STATUS_OK ) || buf_len != sizeof(tx_buf) ) { - printf("\nERROR: Write failed"); + + if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, QSPI_READ_4IO_DUMMY_CYCLE)) { + printf("[WriteReadQuad] Configured QSPI driver succesfully: 1-4-4\r\n"); + } else { + printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n"); + return -1; } - - if( false == WaitForMemReady()) { - printf("\nERROR: Device not ready, tests failed\n"); + + memset(rx_buf, 0, sizeof(rx_buf)); + result = qspi.read(QSPI_STD_CMD_READ_4IO, 0, flash_addr, rx_buf, &buf_len); + if (result != QSPI_STATUS_OK) { + printf("[WriteReadQuad] ERROR: Read failed\r\n"); return false; } - - memset( rx_buf, 0, sizeof(rx_buf) ); - result = myQspi->read( flash_addr, rx_buf, &buf_len ); - if( result != QSPI_STATUS_OK ) { - printf("\nERROR: Read failed"); + + if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0)) { + printf("[WriteReadQuad] Configured QSPI driver succesfully: 1-1-1\r\n"); + } else { + printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n"); + return -1; + } + + if (false == QuadDisable(qspi)) { + printf("[WriteReadQuad] ERROR: Quad disable failed\r\n"); + return false; + } + + if (buf_len != sizeof(rx_buf)) { + printf("[WriteReadQuad] ERROR: Unable to read the entire buffer\r\n"); return false; } - if( buf_len != sizeof(rx_buf) ) { - printf( "\nERROR: Unable to read the entire buffer" ); + + if (0 != (memcmp(rx_buf, tx_buf, sizeof(rx_buf)))) { + printf("[WriteReadQuad] ERROR: Buffer contents are invalid\r\n"); + printf("tx_buf: "); + for (uint32_t i = 0; i < buf_len; i++) { + printf("%d ", tx_buf[i]); + } + printf("\r\n"); + printf("rx_buf: "); + for (uint32_t i = 0; i < buf_len; i++) { + printf("%d ", rx_buf[i]); + } + printf("\r\n"); return false; } - if(0 != (memcmp( rx_buf, tx_buf, sizeof(rx_buf)))) { - printf("\nERROR: Buffer contents are invalid"); - return false; - } - printf("\nRead: %s", rx_buf); - + printf("[WriteReadQuad] Read: %s\r\n", rx_buf); + return true; } -bool InitializeFlashMem() +bool InitializeFlashMem(QSPI &qspi) { - bool ret_status = true; - char status_value[2]; - - //Read the Status Register from device - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_RDSR, // command to send - 0, // do not transmit - NULL, // do not transmit - status_value, // just receive two bytes of data - 2)) { // store received values in status_value - VERBOSE_PRINT(("\nReading Status Register Success: value = 0x%02X:0x%02X\n", status_value[0], status_value[1])); + char reg_data[QSPI_STATUS_REG_SIZE]; + + // Read the Status Register from device + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + reg_data, QSPI_STATUS_REG_SIZE)) { + VERBOSE_PRINT(("[InitializeFlashMem] Reading Status Register Success: value = 0x%02X\r\n", status_value[0])); } else { - printf("\nERROR: Reading Status Register failed\n"); - ret_status = false; + printf("[InitializeFlashMem] ERROR: Reading Status Register failed\r\n"); + return false; } - - if(ret_status) - { - //Send Reset Enable - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_RSTEN, // command to send - 0, // do not transmit - NULL, // do not transmit - 0, // just receive two bytes of data - NULL)) { // store received values in status_value - VERBOSE_PRINT(("\nSending RSTEN Success\n")); - } else { - printf("\nERROR: Sending RSTEN failed\n"); - ret_status = false; - } - - if(ret_status) - { - //Send Reset - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_RST, // command to send - 0, // do not transmit - NULL, // do not transmit - status_value, // just receive two bytes of data - 2)) { // store received values in status_value - VERBOSE_PRINT(("\nSending RST Success\n")); - } else { - printf("\nERROR: Sending RST failed\n"); - ret_status = false; - } - - if(ret_status) - { - status_value[0] |= 0x40; - //Write the Status Register to set QE enable bit - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_WRSR, // command to send - status_value, - 1, - NULL, - 0)) { // store received values in status_value - VERBOSE_PRINT(("\nWriting Status Register Success\n")); - } else { - printf("\nERROR: Writing Status Register failed\n"); - ret_status = false; - } - } - } + + // Send Reset Enable + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RSTEN, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[InitializeFlashMem] Sending RSTEN Success\r\n")); + } else { + printf("[InitializeFlashMem] ERROR: Sending RSTEN failed\r\n"); + return false; } - - return ret_status; + + // Reset device + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RST, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[InitializeFlashMem] Sending RST Success\r\n")); + } else { + printf("[InitializeFlashMem] ERROR: Sending RST failed\r\n"); + return false; + } + + return true; } -bool WaitForMemReady() +bool WaitForMemReady(QSPI &qspi) { - char status_value[2]; - int retries = 0; - - do - { - retries++; - //Read the Status Register from device - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_RDSR, // command to send - 0, // do not transmit - NULL, // do not transmit - status_value, // just receive two bytes of data - 2)) { // store received values in status_value - VERBOSE_PRINT(("\nReadng Status Register Success: value = 0x%02X:0x%02X\n", status_value[0], status_value[1])); + char status_value[QSPI_STATUS_REG_SIZE]; + Timer timer; + + timer.start(); + do { + // Read the Status Register from device + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + status_value, QSPI_STATUS_REG_SIZE)) { + VERBOSE_PRINT(("[WaitForMemReady] Readng Status Register Success: value = 0x%02X\r\n", status_value[0])); } else { - printf("\nERROR: Reading Status Register failed\n"); + printf("[WaitForMemReady] ERROR: Reading Status Register failed\r\n"); } - } while( (status_value[0] & 0x1) != 0 && retries <10000 ); - - if((status_value[0] & 0x1) != 0) return false; + } while ((status_value[0] & STATUS_BIT_WIP) != 0 && timer.read_ms() < QSPI_MAX_WAIT_TIME); + + if ((status_value[0] & STATUS_BIT_WIP) != 0) { + return false; + } return true; } -bool SectorErase(unsigned int flash_addr) +bool SectorErase(QSPI &qspi, unsigned int flash_addr) { - char addrbytes[3] = {0}; - - addrbytes[2]=flash_addr & 0xFF; - addrbytes[1]=(flash_addr >> 8) & 0xFF; - addrbytes[0]=(flash_addr >> 16) & 0xFF; - - //Send WREN - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_WREN, // command to send - 0, // do not transmit - NULL, // do not transmit - 0, // just receive two bytes of data - NULL)) { // store received values in status_value - VERBOSE_PRINT(("\nSending WREN command success\n")); + // Set wite enable + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[SectorErase] Sending WREN command success\r\n")); } else { - printf("\nERROR: Sending WREN command failed\n"); + printf("[SectorErase] ERROR: Sending WREN command failed\r\n"); return false; } - - if (QSPI_STATUS_OK == myQspi->command_transfer(QSPI_STD_CMD_SECT_ERASE, // command to send - addrbytes, // do not transmit - 3, // do not transmit - 0, // just receive two bytes of data - NULL)) { // store received values in status_value - VERBOSE_PRINT(("\nSending SECT_ERASE command success\n")); + // sector erase + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_SECT_ERASE, // command to send + flash_addr, // sector address (any address within sector) + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[SectorErase] Sending SECT_ERASE command success\r\n")); } else { - printf("\nERROR: Readng SECT_ERASE command failed\n"); + printf("[SectorErase] ERROR: Readng SECT_ERASE command failed\r\n"); return false; } - + + if (false == WaitForMemReady(qspi)) { + printf("[SectorErase] ERROR: Device not ready, tests failed\r\n"); + return false; + } + return true; } +bool QuadEnable(QSPI &qspi) +{ + char reg_data[QSPI_STATUS_REG_SIZE]; + + //Read the Status Register from device + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + reg_data, QSPI_STATUS_REG_SIZE)) { + VERBOSE_PRINT(("[QuadEnable] Reading Status Register Success: value = 0x%02X\r\n", reg_data[0])); + } else { + printf("ERROR: Reading Status Register failed\r\n"); + return false; + } + + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[QuadEnable] Sending WREN command success\r\n")); + } else { + printf("[QuadEnable] ERROR: Sending WREN command failed\r\n"); + return false; + } + + reg_data[0] |= (STATUS_BIT_QE); + //Set the Status Register to set QE enable bit + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WRSR, // command to send + -1, // no address to transmit + reg_data, QSPI_STATUS_REG_SIZE, + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[QuadEnable] Writing Status Register Success\r\n")); + } else { + printf("[QuadEnable] ERROR: Writing Status Register failed\r\n"); + return false; + } + + if (false == WaitForMemReady(qspi)) { + printf("[QuadEnable] ERROR: Device not ready, tests failed\r\n"); + return false; + } + + return true; +} + +bool QuadDisable(QSPI &qspi) +{ + char reg_data[QSPI_STATUS_REG_SIZE]; + + // Read the Status Register from device + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + reg_data, QSPI_STATUS_REG_SIZE)) { + VERBOSE_PRINT(("[QuadDisable] Reading Status Register Success: value = 0x%02X\r\n", reg_data[0])); + } else { + printf("[QuadDisable] ERROR: Reading Status Register failed\r\n"); + return false; + } + + // Set write enable + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send + -1, // no address to transmit + NULL, 0, // do not transmit + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[QuadDisable] Sending WREN command success\r\n")); + } else { + printf("[QuadDisable] ERROR: Sending WREN command failed\r\n"); + return false; + } + + reg_data[0] &= ~(STATUS_BIT_QE); + //Set the Status Register to reset QE enable bit + if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WRSR, // command to send + -1, // no address to transmit + reg_data, QSPI_STATUS_REG_SIZE, + NULL, 0)) { // do not receive + VERBOSE_PRINT(("[QuadDisable] Writing Status Register Success\r\n")); + } else { + printf("[QuadDisable] ERROR: Writing Status Register failed\r\n"); + return false; + } + + if (false == WaitForMemReady(qspi)) { + printf("[QuadDisable] ERROR: Device not ready, tests failed\r\n"); + return false; + } + + return true; +}