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.
main.cpp
- Committer:
- Maciej Bocianski
- Date:
- 2018-09-03
- Revision:
- 2:3165b07182ad
- Parent:
- 1:cc0165946232
- Child:
- 5:da509493e3e6
File content as of revision 2:3165b07182ad:
#include "mbed.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 reading configuration register #define QSPI_STD_CMD_RDCR 0x15 // Command for writing status/configuration register #define QSPI_STD_CMD_WRSR 0x01 // 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) #endif 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() { 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("[main] ERROR: Failed configuring QSPI driver\r\n"); return -1; } if (false == InitializeFlashMem(myQspi)) { printf("[main] Unable to initialize flash memory, tests failed\r\n"); return -1; } if (false == WriteReadQuad(myQspi, TEST_FLASH_ADDRESS)) { printf("[main] Unable to read/write using QuadSPI\r\n"); return -1; } printf("<<< Done...\r\n"); } 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]; size_t buf_len = sizeof(tx_buf); 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; } // 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; } 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; } 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; } 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 (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; } printf("[WriteReadQuad] Read: %s\r\n", rx_buf); return true; } bool InitializeFlashMem(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(("[InitializeFlashMem] Reading Status Register Success: value = 0x%02X\r\n", status_value[0])); } else { printf("[InitializeFlashMem] ERROR: Reading Status Register failed\r\n"); return 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; } // 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(QSPI &qspi) { 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("[WaitForMemReady] ERROR: Reading Status Register failed\r\n"); } } 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(QSPI &qspi, unsigned int flash_addr) { // 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("[SectorErase] ERROR: Sending WREN command failed\r\n"); return false; } // 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("[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; }