mbed_example / Mbed OS mbed-os-example-qspi
Revision:
0:f741508e07a3
Child:
1:cc0165946232
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Dec 07 11:13:38 2017 -0600
@@ -0,0 +1,246 @@
+#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
+// Command for reading status register
+#define QSPI_STD_CMD_RDSR                   0x05
+// Command for writing status 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
+// Read/Write commands
+#define QSPI_PP_COMMAND_NRF_ENUM            (0x0) //This corresponds to Flash command 0x02
+#define QSPI_READ2O_COMMAND_NRF_ENUM        (0x1) //This corresponds to Flash command 0x3B
+#define QSPI_READ2IO_COMMAND_NRF_ENUM       (0x2) //This corresponds to Flash command 0xBB
+#define QSPI_PP4IO_COMMAND_NRF_ENUM         (0x3) //This corresponds to Flash command 0x38
+#define QSPI_READ4IO_COMMAND_NRF_ENUM       (0x4) //This corresponds to Flash command 0xEB
+
+//#define DEBUG_ON 1
+#ifdef DEBUG_ON
+    #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();
+    
+// 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");
+    } else {
+        printf("\nERROR: Failed creating QSPI driver object");
+        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");
+        return -1;
+    }
+    
+    if( false == InitializeFlashMem()) {
+        printf("\nUnable to initialize flash memory, tests failed\n");
+        return -1;
+    }
+    
+    if( false == WriteReadSimple() ) {
+        printf("\nUnable to read/write using QuadSPI\n");
+        return -1;
+    }
+        
+    printf("\nDone...\n");
+}
+
+bool WriteReadSimple()
+{
+    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);
+    
+    uint32_t flash_addr = 0x1000;
+    if( false == SectorErase(flash_addr)) {
+        printf("\nERROR: SectorErase failed(addr = 0x%08X)\n", flash_addr);
+        return false;
+    }
+    
+    if( false == WaitForMemReady()) {
+        printf("\nERROR: Device not ready, tests failed\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( false == WaitForMemReady()) {
+        printf("\nERROR: Device not ready, tests failed\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");
+        return false;
+    }
+    if( buf_len != sizeof(rx_buf) ) {
+        printf( "\nERROR: Unable to read the entire buffer" );
+        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);
+    
+    return true;
+}
+
+bool InitializeFlashMem()
+{
+    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]));
+    } else {
+        printf("\nERROR: Reading Status Register failed\n");
+        ret_status = 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;
+                }
+            }
+        }
+    }
+    
+    return ret_status;
+}
+
+bool WaitForMemReady()
+{
+    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]));
+        } else {
+            printf("\nERROR: Reading Status Register failed\n");
+        }
+    } while( (status_value[0] & 0x1) != 0 && retries <10000 );
+    
+    if((status_value[0] & 0x1) != 0) return false;
+    return true;
+}
+
+bool SectorErase(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"));
+    } else {
+        printf("\nERROR: Sending WREN command failed\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"));
+    } else {
+        printf("\nERROR: Readng SECT_ERASE command failed\n");
+        return false;
+    }
+    
+    return true;
+}
+