mbed_example / Mbed OS mbed-os-example-qspi

main.cpp

Committer:
Senthil Ramakrishnan
Date:
2017-12-07
Revision:
0:f741508e07a3
Child:
1:cc0165946232

File content as of revision 0:f741508e07a3:

#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;
}