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
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 }
Generated on Mon Jul 25 2022 14:44:22 by
1.7.2