mbed_example / Mbed OS mbed-os-example-qspi
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017-2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "QSPI.h"
00019 
00020 // The below values are command codes defined in Datasheet for MX25R6435F Macronix Flash Memory
00021 // should work for whole MX25RXX35F chip family
00022 
00023 // Command for reading status register
00024 #define QSPI_STD_CMD_RDSR                   0x05
00025 // Command for reading configuration register
00026 #define QSPI_STD_CMD_RDCR                   0x15
00027 // Command for writing status/configuration register
00028 #define QSPI_STD_CMD_WRSR                   0x01
00029 // Command for setting WREN (supported only by some memories)
00030 #define QSPI_STD_CMD_WREN                   0x06
00031 // Command for Sector erase (supported only by some memories)
00032 #define QSPI_STD_CMD_SECT_ERASE             0x20
00033 //
00034 #define QSPI_STD_CMD_WRITE_1IO              0x02   // 1-1-1 mode
00035 #define QSPI_STD_CMD_WRITE_4IO              0x38   // 1-4-4 mode
00036 #define QSPI_STD_CMD_READ_1IO               0x03   // 1-1-1 mode
00037 #define QSPI_STD_CMD_READ_4IO               0xEB   // 1-4-4 mode
00038 
00039 #define QSPI_STD_CMD_RSTEN                  0x66
00040 // Command for setting Reset (supported only by some memories)
00041 #define QSPI_STD_CMD_RST                    0x99
00042 
00043 #define STATUS_BIT_WIP   (1 << 0)   // write in progress bit
00044 #define STATUS_BIT_QE    (1 << 6)   // Quad Enable
00045 
00046 #define QSPI_STATUS_REG_SIZE                1
00047 
00048 #define QSPI_READ_4IO_DUMMY_CYCLE           6
00049 
00050 #define QSPI_MAX_WAIT_TIME                  1000      // 1000 ms
00051 
00052 #define TEST_FLASH_ADDRESS  0x1000
00053 
00054 //#define DEBUG_ON 1
00055 #ifdef DEBUG_ON
00056 #define VERBOSE_PRINT(x) printf x
00057 #else
00058 #define VERBOSE_PRINT(x)
00059 #endif
00060 
00061 bool InitializeFlashMem(QSPI &qspi);
00062 bool WaitForMemReady(QSPI &qspi);
00063 bool SectorErase(QSPI &qspi, unsigned int flash_addr);
00064 bool WriteReadQuad(QSPI &qspi, unsigned int flash_addr);
00065 bool QuadEnable(QSPI &qspi);
00066 bool QuadDisable(QSPI &qspi);
00067 
00068 
00069 // main() runs in its own thread in the OS
00070 int main()
00071 {
00072     printf(">>> Start...\r\n");
00073     QSPI myQspi((PinName)QSPI_FLASH1_IO0, (PinName)QSPI_FLASH1_IO1, (PinName)QSPI_FLASH1_IO2,
00074                 (PinName)QSPI_FLASH1_IO3, (PinName)QSPI_FLASH1_SCK, (PinName)QSPI_FLASH1_CSN);
00075 
00076     if (false == InitializeFlashMem(myQspi)) {
00077         printf("[main] Unable to initialize flash memory, tests failed\r\n");
00078         return -1;
00079     }
00080 
00081     if (false == WriteReadQuad(myQspi, TEST_FLASH_ADDRESS)) {
00082         printf("[main] Unable to read/write using QuadSPI\r\n");
00083         return -1;
00084     }
00085 
00086     printf("<<< Done...\r\n\r\n");
00087 }
00088 
00089 bool WriteReadQuad(QSPI &qspi, unsigned int flash_addr)
00090 {
00091     int result = 0;
00092     char tx_buf[] = { 'H', 'E', 'L', 'L', 'O', ' ', 'Q', 'U', 'A', 'D', '-', 'S', 'P', 'I', '!', 0 };
00093     char rx_buf[16];
00094     size_t buf_len = sizeof(tx_buf);
00095 
00096     if (false == SectorErase(qspi, flash_addr)) {
00097         printf("[WriteReadQuad] ERROR: SectorErase failed(addr = 0x%08lX)\r\n", flash_addr);
00098         return false;
00099     }
00100 
00101     if (false == QuadEnable(qspi)) {
00102         printf("[WriteReadQuad] ERROR: Quad enable failed\r\n");
00103         return false;
00104     }
00105 
00106     // Send write enable
00107     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send
00108                                                 -1,                // no address to transmit
00109                                                 NULL, 0,           // do not transmit
00110                                                 NULL, 0)) {        // do not receive
00111         VERBOSE_PRINT(("[WriteReadQuad] Sending WREN command success\r\n"));
00112     } else {
00113         printf("[WriteReadQuad] ERROR: Sending WREN command failed\r\n");
00114         return false;
00115     }
00116 
00117     if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24,
00118                                                 QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 0)) {
00119         printf("Configured QSPI driver succesfully: 1-4-4\r\n");
00120     } else {
00121         printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n");
00122         return -1;
00123     }
00124 
00125     printf("Writing: %s\r\n", tx_buf);
00126     result = qspi.write(QSPI_STD_CMD_WRITE_4IO, 0, flash_addr, tx_buf, &buf_len);
00127     if ((result != QSPI_STATUS_OK) || buf_len != sizeof(tx_buf)) {
00128         printf("[WriteReadQuad] ERROR: Write failed\r\n");
00129     }
00130 
00131     if (false == WaitForMemReady(qspi)) {
00132         printf("[WriteReadQuad] ERROR: Device not ready, tests failed\r\n");
00133         return false;
00134     }
00135 
00136     // Set dummy cycle count for read operation
00137     if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24,
00138                                                 QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, QSPI_READ_4IO_DUMMY_CYCLE)) {
00139         printf("Configured QSPI driver succesfully: dummy cycle set to 6\r\n");
00140     } else {
00141         printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n");
00142         return -1;
00143     }
00144 
00145     memset(rx_buf, 0, sizeof(rx_buf));
00146     result = qspi.read(QSPI_STD_CMD_READ_4IO, 0, flash_addr, rx_buf, &buf_len);
00147     if (result != QSPI_STATUS_OK) {
00148         printf("[WriteReadQuad] ERROR: Read failed\r\n");
00149         return false;
00150     }
00151 
00152     if (buf_len != sizeof(rx_buf)) {
00153         printf("[WriteReadQuad] ERROR: Unable to read the entire buffer\r\n");
00154         return false;
00155     }
00156 
00157     if (0 != (memcmp(rx_buf, tx_buf, sizeof(rx_buf)))) {
00158         printf("[WriteReadQuad] ERROR: Buffer contents are invalid\r\n");
00159         printf("tx_buf: ");
00160         for (uint32_t i = 0; i < buf_len; i++) {
00161             printf("%d ", tx_buf[i]);
00162         }
00163         printf("\r\n");
00164         printf("rx_buf: ");
00165         for (uint32_t i = 0; i < buf_len; i++) {
00166             printf("%d ", rx_buf[i]);
00167         }
00168         printf("\r\n");
00169         return false;
00170     }
00171     printf("Read: %s\r\n", rx_buf);
00172 
00173     // Reset dummy cycle count
00174     if (QSPI_STATUS_OK == qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_ADDR_SIZE_24,
00175                                                 QSPI_CFG_BUS_QUAD, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_QUAD, 0)) {
00176         printf("Configured QSPI driver succesfully: dummy cycle set to 0\r\n");
00177     } else {
00178         printf("[WriteReadQuad] ERROR: Failed configuring QSPI driver\r\n");
00179         return -1;
00180     }
00181 
00182     if (false == QuadDisable(qspi)) {
00183         printf("[WriteReadQuad] ERROR: Quad disable failed\r\n");
00184         return false;
00185     }
00186 
00187     return true;
00188 }
00189 
00190 bool InitializeFlashMem(QSPI &qspi)
00191 {
00192     char reg_data[QSPI_STATUS_REG_SIZE];
00193 
00194     // Read the Status Register from device
00195     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR,   // command to send
00196                                                 -1,                  // no address to transmit
00197                                                 NULL, 0,             // do not transmit
00198                                                 reg_data, QSPI_STATUS_REG_SIZE)) {
00199         VERBOSE_PRINT(("[InitializeFlashMem] Reading Status Register Success: value = 0x%02X\r\n", status_value[0]));
00200     } else {
00201         printf("[InitializeFlashMem] ERROR: Reading Status Register failed\r\n");
00202         return false;
00203     }
00204 
00205     // Send Reset Enable
00206     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RSTEN,  // command to send
00207                                                 -1,                  // no address to transmit
00208                                                 NULL, 0,             // do not transmit
00209                                                 NULL, 0)) {          // do not receive
00210         VERBOSE_PRINT(("[InitializeFlashMem] Sending RSTEN Success\r\n"));
00211     } else {
00212         printf("[InitializeFlashMem] ERROR: Sending RSTEN failed\r\n");
00213         return false;
00214     }
00215 
00216     // Reset device
00217     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RST,   // command to send
00218                                                 -1,                 // no address to transmit
00219                                                 NULL, 0,            // do not transmit
00220                                                 NULL, 0)) {         // do not receive
00221         VERBOSE_PRINT(("[InitializeFlashMem] Sending RST Success\r\n"));
00222     } else {
00223         printf("[InitializeFlashMem] ERROR: Sending RST failed\r\n");
00224         return false;
00225     }
00226 
00227     return true;
00228 }
00229 
00230 bool WaitForMemReady(QSPI &qspi)
00231 {
00232     char status_value[QSPI_STATUS_REG_SIZE];
00233     Timer timer;
00234 
00235     timer.start();
00236     do {
00237         // Read the Status Register from device
00238         if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR,                  // command to send
00239                                                     -1,                                 // no address to transmit
00240                                                     NULL, 0,                            // do not transmit
00241                                                     status_value, QSPI_STATUS_REG_SIZE)) {
00242             VERBOSE_PRINT(("[WaitForMemReady] Readng Status Register Success: value = 0x%02X\r\n", status_value[0]));
00243         } else {
00244             printf("[WaitForMemReady] ERROR: Reading Status Register failed\r\n");
00245         }
00246     } while ((status_value[0] & STATUS_BIT_WIP) != 0 && timer.read_ms() < QSPI_MAX_WAIT_TIME);
00247 
00248     if ((status_value[0] & STATUS_BIT_WIP) != 0) {
00249         return false;
00250     }
00251     return true;
00252 }
00253 
00254 bool SectorErase(QSPI &qspi, unsigned int flash_addr)
00255 {
00256     //  Set wite enable
00257     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN, // command to send
00258                                                 -1,                 // no address to transmit
00259                                                 NULL, 0,             // do not transmit
00260                                                 NULL, 0)) {   // do not receive
00261         VERBOSE_PRINT(("[SectorErase] Sending WREN command success\r\n"));
00262     } else {
00263         printf("[SectorErase] ERROR: Sending WREN command failed\r\n");
00264         return false;
00265     }
00266     // sector erase
00267     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_SECT_ERASE, // command to send
00268                                                 flash_addr,              // sector address (any address within sector)
00269                                                 NULL, 0,                 // do not transmit
00270                                                 NULL, 0)) {              // do not receive
00271         VERBOSE_PRINT(("[SectorErase] Sending SECT_ERASE command success\r\n"));
00272     } else {
00273         printf("[SectorErase] ERROR: Readng SECT_ERASE command failed\r\n");
00274         return false;
00275     }
00276 
00277     if (false == WaitForMemReady(qspi)) {
00278         printf("[SectorErase] ERROR: Device not ready, tests failed\r\n");
00279         return false;
00280     }
00281 
00282     return true;
00283 }
00284 
00285 bool QuadEnable(QSPI &qspi)
00286 {
00287     char reg_data[QSPI_STATUS_REG_SIZE];
00288 
00289     //Read the Status Register from device
00290     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR,                  // command to send
00291                                                 -1,                                 // no address to transmit
00292                                                 NULL, 0,                            // do not transmit
00293                                                 reg_data, QSPI_STATUS_REG_SIZE)) {
00294         VERBOSE_PRINT(("[QuadEnable] Reading Status Register Success: value = 0x%02X\r\n", reg_data[0]));
00295     } else {
00296         printf("ERROR: Reading Status Register failed\r\n");
00297         return false;
00298     }
00299     //  Set wite enable
00300     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN,  // command to send
00301                                                 -1,                 // no address to transmit
00302                                                 NULL, 0,            // do not transmit
00303                                                 NULL, 0)) {         // do not receive
00304         VERBOSE_PRINT(("[QuadEnable] Sending WREN command success\r\n"));
00305     } else {
00306         printf("[QuadEnable] ERROR: Sending WREN command failed\r\n");
00307         return false;
00308     }
00309     //Set the Status Register to set QE enable bit
00310     reg_data[0] |= (STATUS_BIT_QE);
00311     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WRSR,               // command to send
00312                                                 -1,                              // no address to transmit
00313                                                 reg_data, QSPI_STATUS_REG_SIZE,
00314                                                 NULL, 0)) {                      // do not receive
00315         VERBOSE_PRINT(("[QuadEnable] Writing Status Register Success\r\n"));
00316     } else {
00317         printf("[QuadEnable] ERROR: Writing Status Register failed\r\n");
00318         return false;
00319     }
00320 
00321     if (false == WaitForMemReady(qspi)) {
00322         printf("[QuadEnable] ERROR: Device not ready, tests failed\r\n");
00323         return false;
00324     }
00325 
00326     return true;
00327 }
00328 
00329 bool QuadDisable(QSPI &qspi)
00330 {
00331     char reg_data[QSPI_STATUS_REG_SIZE];
00332 
00333     // Read the Status Register from device
00334     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_RDSR,  // command to send
00335                                                 -1,                 // no address to transmit
00336                                                 NULL, 0,            // do not transmit
00337                                                 reg_data, QSPI_STATUS_REG_SIZE)) {
00338         VERBOSE_PRINT(("[QuadDisable] Reading Status Register Success: value = 0x%02X\r\n", reg_data[0]));
00339     } else {
00340         printf("[QuadDisable] ERROR: Reading Status Register failed\r\n");
00341         return false;
00342     }
00343 
00344     // Set write enable
00345     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WREN,  // command to send
00346                                                 -1,                 // no address to transmit
00347                                                 NULL, 0,            // do not transmit
00348                                                 NULL, 0)) {         // do not receive
00349         VERBOSE_PRINT(("[QuadDisable] Sending WREN command success\r\n"));
00350     } else {
00351         printf("[QuadDisable] ERROR: Sending WREN command failed\r\n");
00352         return false;
00353     }
00354     //Set the Status Register to reset QE enable bit
00355     reg_data[0] &= ~(STATUS_BIT_QE);
00356     if (QSPI_STATUS_OK == qspi.command_transfer(QSPI_STD_CMD_WRSR,               // command to send
00357                                                 -1,                              // no address to transmit
00358                                                 reg_data, QSPI_STATUS_REG_SIZE,
00359                                                 NULL, 0)) {                      // do not receive
00360         VERBOSE_PRINT(("[QuadDisable] Writing Status Register Success\r\n"));
00361     } else {
00362         printf("[QuadDisable] ERROR: Writing Status Register failed\r\n");
00363         return false;
00364     }
00365 
00366     if (false == WaitForMemReady(qspi)) {
00367         printf("[QuadDisable] ERROR: Device not ready, tests failed\r\n");
00368         return false;
00369     }
00370 
00371     return true;
00372 }