STM32L476G-Discovery BSP User Manual
|
stm32l476g_discovery_qspi.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l476g_discovery_qspi.c 00004 * @author MCD Application Team 00005 * @version $VERSION$ 00006 * @date $DATE$ 00007 * @brief This file includes a standard driver for the N25Q128A QSPI 00008 * memory mounted on STM32L476G-Discovery board. 00009 @verbatim 00010 ============================================================================== 00011 ##### How to use this driver ##### 00012 ============================================================================== 00013 [..] 00014 (#) This driver is used to drive the N25Q128A QSPI external 00015 memory mounted on STM32L476G-DISCO evaluation board. 00016 00017 (#) This driver need a specific component driver (N25Q128A) to be included with. 00018 00019 (#) Initialization steps: 00020 (++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This 00021 function includes the MSP layer hardware resources initialization and the 00022 QSPI interface with the external memory. 00023 00024 (#) QSPI memory operations 00025 (++) QSPI memory can be accessed with read/write operations once it is 00026 initialized. 00027 Read/write operation can be performed with AHB access using the functions 00028 BSP_QSPI_Read()/BSP_QSPI_Write(). 00029 (++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory. 00030 (see the QSPI memory data sheet) 00031 (++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by 00032 specifying the block address. You can perform an erase operation of the whole 00033 chip by calling the function BSP_QSPI_Erase_Chip(). 00034 (++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. 00035 (see the QSPI memory data sheet) 00036 @endverbatim 00037 ****************************************************************************** 00038 * @attention 00039 * 00040 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00041 * 00042 * Redistribution and use in source and binary forms, with or without modification, 00043 * are permitted provided that the following conditions are met: 00044 * 1. Redistributions of source code must retain the above copyright notice, 00045 * this list of conditions and the following disclaimer. 00046 * 2. Redistributions in binary form must reproduce the above copyright notice, 00047 * this list of conditions and the following disclaimer in the documentation 00048 * and/or other materials provided with the distribution. 00049 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00050 * may be used to endorse or promote products derived from this software 00051 * without specific prior written permission. 00052 * 00053 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00054 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00055 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00056 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00057 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00058 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00059 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00060 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00061 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00062 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00063 * 00064 ****************************************************************************** 00065 */ 00066 00067 /* Includes ------------------------------------------------------------------*/ 00068 #include "stm32l476g_discovery_qspi.h" 00069 00070 /** @addtogroup BSP 00071 * @{ 00072 */ 00073 00074 /** @addtogroup STM32L476G_DISCOVERY 00075 * @{ 00076 */ 00077 00078 /** @defgroup STM32L476G_DISCOVERY_QSPI STM32L476G-DISCOVERY QSPI 00079 * @{ 00080 */ 00081 00082 /* Private variables ---------------------------------------------------------*/ 00083 00084 /** @defgroup STM32L476G_DISCOVERY_QSPI_Private_Variables Private Variables 00085 * @{ 00086 */ 00087 QSPI_HandleTypeDef QSPIHandle; 00088 00089 /** 00090 * @} 00091 */ 00092 00093 00094 /* Private functions ---------------------------------------------------------*/ 00095 00096 /** @defgroup STM32L476G_DISCOVERY_QSPI_Private_Functions Private Functions 00097 * @{ 00098 */ 00099 static void QSPI_MspInit (void); 00100 static void QSPI_MspDeInit (void); 00101 static uint8_t QSPI_ResetMemory (QSPI_HandleTypeDef *hqspi); 00102 static uint8_t QSPI_DummyCyclesCfg (QSPI_HandleTypeDef *hqspi); 00103 static uint8_t QSPI_WriteEnable (QSPI_HandleTypeDef *hqspi); 00104 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout); 00105 00106 /** 00107 * @} 00108 */ 00109 00110 /* Exported functions ---------------------------------------------------------*/ 00111 00112 /** @addtogroup STM32L476G_DISCOVERY_QSPI_Exported_Functions 00113 * @{ 00114 */ 00115 00116 /** 00117 * @brief Initializes the QSPI interface. 00118 * @retval QSPI memory status 00119 */ 00120 uint8_t BSP_QSPI_Init(void) 00121 { 00122 QSPIHandle.Instance = QUADSPI; 00123 00124 /* Call the DeInit function to reset the driver */ 00125 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00126 { 00127 return QSPI_ERROR; 00128 } 00129 00130 /* System level initialization */ 00131 QSPI_MspInit(); 00132 00133 /* QSPI initialization */ 00134 QSPIHandle.Init.ClockPrescaler = 0; /* Clock = Fahb = 80 MHz */ 00135 QSPIHandle.Init.FifoThreshold = 4; 00136 QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; 00137 QSPIHandle.Init.FlashSize = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1; 00138 QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; 00139 QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; 00140 00141 if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) 00142 { 00143 return QSPI_ERROR; 00144 } 00145 00146 /* QSPI memory reset */ 00147 if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) 00148 { 00149 return QSPI_NOT_SUPPORTED; 00150 } 00151 00152 /* Configuration of the dummy cucles on QSPI memory side */ 00153 if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK) 00154 { 00155 return QSPI_NOT_SUPPORTED; 00156 } 00157 00158 return QSPI_OK; 00159 } 00160 00161 /** 00162 * @brief De-Initializes the QSPI interface. 00163 * @retval QSPI memory status 00164 */ 00165 uint8_t BSP_QSPI_DeInit(void) 00166 { 00167 QSPIHandle.Instance = QUADSPI; 00168 00169 /* Call the DeInit function to reset the driver */ 00170 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00171 { 00172 return QSPI_ERROR; 00173 } 00174 00175 /* System level De-initialization */ 00176 QSPI_MspDeInit(); 00177 00178 return QSPI_OK; 00179 } 00180 00181 /** 00182 * @brief Reads an amount of data from the QSPI memory. 00183 * @param pData: Pointer to data to be read 00184 * @param ReadAddr: Read start address 00185 * @param Size: Size of data to read 00186 * @retval QSPI memory status 00187 */ 00188 uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) 00189 { 00190 QSPI_CommandTypeDef sCommand; 00191 00192 /* Initialize the read command */ 00193 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00194 sCommand.Instruction = QUAD_INOUT_FAST_READ_CMD; 00195 sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 00196 sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 00197 sCommand.Address = ReadAddr; 00198 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00199 sCommand.DataMode = QSPI_DATA_4_LINES; 00200 sCommand.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00201 sCommand.NbData = Size; 00202 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00203 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00204 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00205 00206 /* Configure the command */ 00207 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00208 { 00209 return QSPI_ERROR; 00210 } 00211 00212 /* Reception of the data */ 00213 if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00214 { 00215 return QSPI_ERROR; 00216 } 00217 00218 return QSPI_OK; 00219 } 00220 00221 /** 00222 * @brief Writes an amount of data to the QSPI memory. 00223 * @param pData: Pointer to data to be written 00224 * @param WriteAddr: Write start address 00225 * @param Size: Size of data to write 00226 * @retval QSPI memory status 00227 */ 00228 uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) 00229 { 00230 QSPI_CommandTypeDef sCommand; 00231 uint32_t end_addr, current_size, current_addr; 00232 00233 /* Calculation of the size between the write address and the end of the page */ 00234 current_addr = 0; 00235 00236 while (current_addr <= WriteAddr) 00237 { 00238 current_addr += N25Q128A_PAGE_SIZE; 00239 } 00240 current_size = current_addr - WriteAddr; 00241 00242 /* Check if the size of the data is less than the remaining place in the page */ 00243 if (current_size > Size) 00244 { 00245 current_size = Size; 00246 } 00247 00248 /* Initialize the adress variables */ 00249 current_addr = WriteAddr; 00250 end_addr = WriteAddr + Size; 00251 00252 /* Initialize the program command */ 00253 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00254 sCommand.Instruction = EXT_QUAD_IN_FAST_PROG_CMD; 00255 sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 00256 sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 00257 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00258 sCommand.DataMode = QSPI_DATA_4_LINES; 00259 sCommand.DummyCycles = 0; 00260 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00261 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00262 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00263 00264 /* Perform the write page by page */ 00265 do 00266 { 00267 sCommand.Address = current_addr; 00268 sCommand.NbData = current_size; 00269 00270 /* Enable write operations */ 00271 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00272 { 00273 return QSPI_ERROR; 00274 } 00275 00276 /* Configure the command */ 00277 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00278 { 00279 return QSPI_ERROR; 00280 } 00281 00282 /* Transmission of the data */ 00283 if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00284 { 00285 return QSPI_ERROR; 00286 } 00287 00288 /* Configure automatic polling mode to wait for end of program */ 00289 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00290 { 00291 return QSPI_ERROR; 00292 } 00293 00294 /* Update the address and size variables for next page programming */ 00295 current_addr += current_size; 00296 pData += current_size; 00297 current_size = ((current_addr + N25Q128A_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : N25Q128A_PAGE_SIZE; 00298 } while (current_addr < end_addr); 00299 00300 return QSPI_OK; 00301 } 00302 00303 /** 00304 * @brief Erases the specified block of the QSPI memory. 00305 * @param BlockAddress: Block address to erase 00306 * @retval QSPI memory status 00307 */ 00308 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) 00309 { 00310 QSPI_CommandTypeDef sCommand; 00311 00312 /* Initialize the erase command */ 00313 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00314 sCommand.Instruction = SUBSECTOR_ERASE_CMD; 00315 sCommand.AddressMode = QSPI_ADDRESS_1_LINE; 00316 sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 00317 sCommand.Address = BlockAddress; 00318 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00319 sCommand.DataMode = QSPI_DATA_NONE; 00320 sCommand.DummyCycles = 0; 00321 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00322 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00323 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00324 00325 /* Enable write operations */ 00326 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00327 { 00328 return QSPI_ERROR; 00329 } 00330 00331 /* Send the command */ 00332 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00333 { 00334 return QSPI_ERROR; 00335 } 00336 00337 /* Configure automatic polling mode to wait for end of erase */ 00338 if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK) 00339 { 00340 return QSPI_ERROR; 00341 } 00342 00343 return QSPI_OK; 00344 } 00345 00346 /** 00347 * @brief Erases the specified sector of the QSPI memory. 00348 * @param Sector: Sector address to erase (0 to 255) 00349 * @retval QSPI memory status 00350 * @note This function is non blocking meaning that sector erase 00351 * operation is started but not completed when the function 00352 * returns. Application has to call BSP_QSPI_GetStatus() 00353 * to know when the device is available again (i.e. erase operation 00354 * completed). 00355 */ 00356 uint8_t BSP_QSPI_Erase_Sector(uint32_t Sector) 00357 { 00358 QSPI_CommandTypeDef sCommand; 00359 00360 if (Sector >= (uint32_t)(N25Q128A_FLASH_SIZE/N25Q128A_SECTOR_SIZE)) 00361 { 00362 return QSPI_ERROR; 00363 } 00364 00365 /* Initialize the erase command */ 00366 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00367 sCommand.Instruction = SECTOR_ERASE_CMD; 00368 sCommand.AddressMode = QSPI_ADDRESS_1_LINE; 00369 sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 00370 sCommand.Address = (Sector * N25Q128A_SECTOR_SIZE); 00371 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00372 sCommand.DataMode = QSPI_DATA_NONE; 00373 sCommand.DummyCycles = 0; 00374 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00375 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00376 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00377 00378 /* Enable write operations */ 00379 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00380 { 00381 return QSPI_ERROR; 00382 } 00383 00384 /* Send the command */ 00385 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00386 { 00387 return QSPI_ERROR; 00388 } 00389 00390 return QSPI_OK; 00391 } 00392 00393 /** 00394 * @brief Erases the entire QSPI memory. 00395 * @retval QSPI memory status 00396 */ 00397 uint8_t BSP_QSPI_Erase_Chip(void) 00398 { 00399 QSPI_CommandTypeDef sCommand; 00400 00401 /* Initialize the erase command */ 00402 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00403 sCommand.Instruction = BULK_ERASE_CMD; 00404 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00405 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00406 sCommand.DataMode = QSPI_DATA_NONE; 00407 sCommand.DummyCycles = 0; 00408 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00409 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00410 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00411 00412 /* Enable write operations */ 00413 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00414 { 00415 return QSPI_ERROR; 00416 } 00417 00418 /* Send the command */ 00419 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00420 { 00421 return QSPI_ERROR; 00422 } 00423 00424 /* Configure automatic polling mode to wait for end of erase */ 00425 if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK) 00426 { 00427 return QSPI_ERROR; 00428 } 00429 00430 return QSPI_OK; 00431 } 00432 00433 /** 00434 * @brief Reads current status of the QSPI memory. 00435 * @retval QSPI memory status 00436 */ 00437 uint8_t BSP_QSPI_GetStatus(void) 00438 { 00439 QSPI_CommandTypeDef sCommand; 00440 uint8_t reg; 00441 00442 /* Initialize the read flag status register command */ 00443 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00444 sCommand.Instruction = READ_FLAG_STATUS_REG_CMD; 00445 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00446 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00447 sCommand.DataMode = QSPI_DATA_1_LINE; 00448 sCommand.DummyCycles = 0; 00449 sCommand.NbData = 1; 00450 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00451 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00452 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00453 00454 /* Configure the command */ 00455 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00456 { 00457 return QSPI_ERROR; 00458 } 00459 00460 /* Reception of the data */ 00461 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00462 { 00463 return QSPI_ERROR; 00464 } 00465 00466 /* Check the value of the register */ 00467 if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0) 00468 { 00469 return QSPI_ERROR; 00470 } 00471 else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0) 00472 { 00473 return QSPI_SUSPENDED; 00474 } 00475 else if ((reg & N25Q128A_FSR_READY) != 0) 00476 { 00477 return QSPI_OK; 00478 } 00479 else 00480 { 00481 return QSPI_BUSY; 00482 } 00483 } 00484 00485 /** 00486 * @brief Return the configuration of the QSPI memory. 00487 * @param pInfo: pointer on the configuration structure 00488 * @retval QSPI memory status 00489 */ 00490 uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo) 00491 { 00492 /* Configure the structure with the memory configuration */ 00493 pInfo->FlashSize = N25Q128A_FLASH_SIZE; 00494 pInfo->EraseSectorSize = N25Q128A_SUBSECTOR_SIZE; 00495 pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE/N25Q128A_SUBSECTOR_SIZE); 00496 pInfo->ProgPageSize = N25Q128A_PAGE_SIZE; 00497 pInfo->ProgPagesNumber = (N25Q128A_FLASH_SIZE/N25Q128A_PAGE_SIZE); 00498 00499 return QSPI_OK; 00500 } 00501 00502 /** 00503 * @brief Configure the QSPI in memory-mapped mode 00504 * @retval QSPI memory status 00505 */ 00506 uint8_t BSP_QSPI_EnableMemoryMappedMode(void) 00507 { 00508 QSPI_CommandTypeDef sCommand; 00509 QSPI_MemoryMappedTypeDef sMemMappedCfg; 00510 00511 /* Configure the command for the read instruction */ 00512 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00513 sCommand.Instruction = QUAD_INOUT_FAST_READ_CMD; 00514 sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 00515 sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 00516 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00517 sCommand.DataMode = QSPI_DATA_4_LINES; 00518 sCommand.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00519 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00520 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00521 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00522 00523 /* Configure the memory mapped mode */ 00524 sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_ENABLE; 00525 sMemMappedCfg.TimeOutPeriod = 4; /* 50 ns (4 periods of a 80 MHz clock) */ 00526 00527 if (HAL_QSPI_MemoryMapped(&QSPIHandle, &sCommand, &sMemMappedCfg) != HAL_OK) 00528 { 00529 return QSPI_ERROR; 00530 } 00531 00532 return QSPI_OK; 00533 } 00534 00535 /** 00536 * @brief This function suspends an ongoing erase command. 00537 * @retval QSPI memory status 00538 */ 00539 uint8_t BSP_QSPI_SuspendErase(void) 00540 { 00541 QSPI_CommandTypeDef sCommand; 00542 00543 /* Check whether the device is busy (erase operation is 00544 in progress). 00545 */ 00546 if (BSP_QSPI_GetStatus() == QSPI_BUSY) 00547 { 00548 /* Initialize the erase command */ 00549 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00550 sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; 00551 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00552 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00553 sCommand.DataMode = QSPI_DATA_NONE; 00554 sCommand.DummyCycles = 0; 00555 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00556 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00557 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00558 00559 /* Enable write operations */ 00560 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00561 { 00562 return QSPI_ERROR; 00563 } 00564 00565 /* Send the command */ 00566 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00567 { 00568 return QSPI_ERROR; 00569 } 00570 00571 if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) 00572 { 00573 return QSPI_OK; 00574 } 00575 00576 return QSPI_ERROR; 00577 } 00578 00579 return QSPI_OK; 00580 } 00581 00582 /** 00583 * @brief This function resumes a paused erase command. 00584 * @retval QSPI memory status 00585 */ 00586 uint8_t BSP_QSPI_ResumeErase(void) 00587 { 00588 QSPI_CommandTypeDef sCommand; 00589 00590 /* Check whether the device is in suspended state */ 00591 if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) 00592 { 00593 /* Initialize the erase command */ 00594 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00595 sCommand.Instruction = PROG_ERASE_RESUME_CMD; 00596 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00597 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00598 sCommand.DataMode = QSPI_DATA_NONE; 00599 sCommand.DummyCycles = 0; 00600 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00601 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00602 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00603 00604 /* Enable write operations */ 00605 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00606 { 00607 return QSPI_ERROR; 00608 } 00609 00610 /* Send the command */ 00611 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00612 { 00613 return QSPI_ERROR; 00614 } 00615 00616 /* 00617 When this command is executed, the status register write in progress bit is set to 1, and 00618 the flag status register program erase controller bit is set to 0. This command is ignored 00619 if the device is not in a suspended state. 00620 */ 00621 00622 if (BSP_QSPI_GetStatus() == QSPI_BUSY) 00623 { 00624 return QSPI_OK; 00625 } 00626 00627 return QSPI_ERROR; 00628 } 00629 00630 return QSPI_OK; 00631 } 00632 00633 /** 00634 * @} 00635 */ 00636 00637 /** @addtogroup STM32L476G_DISCOVERY_QSPI_Private_Functions 00638 * @{ 00639 */ 00640 00641 /** 00642 * @brief Initializes the QSPI MSP. 00643 * @retval None 00644 */ 00645 static void QSPI_MspInit(void) 00646 { 00647 GPIO_InitTypeDef GPIO_InitStruct; 00648 00649 /* Enable the QuadSPI memory interface clock */ 00650 __HAL_RCC_QSPI_CLK_ENABLE(); 00651 00652 /* Reset the QuadSPI memory interface */ 00653 __HAL_RCC_QSPI_FORCE_RESET(); 00654 __HAL_RCC_QSPI_RELEASE_RESET(); 00655 00656 /* Enable GPIO clocks */ 00657 __HAL_RCC_GPIOE_CLK_ENABLE(); 00658 00659 /* QSPI CS GPIO pin configuration */ 00660 GPIO_InitStruct.Pin = GPIO_PIN_11; 00661 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 00662 GPIO_InitStruct.Pull = GPIO_PULLUP; 00663 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 00664 GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; 00665 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 00666 00667 /* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration */ 00668 GPIO_InitStruct.Pin = (GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); 00669 GPIO_InitStruct.Pull = GPIO_NOPULL; 00670 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 00671 } 00672 00673 /** 00674 * @brief De-Initializes the QSPI MSP. 00675 * @retval None 00676 */ 00677 static void QSPI_MspDeInit(void) 00678 { 00679 GPIO_InitTypeDef GPIO_InitStruct; 00680 00681 /* QSPI CLK, CS, PE10 - PE15 GPIO pins de-configuration */ 00682 00683 __HAL_RCC_GPIOE_CLK_ENABLE(); 00684 HAL_GPIO_DeInit(GPIOE, (GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)); 00685 /* Set GPIOE pin 11 in pull up mode (optimum default setting) */ 00686 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 00687 GPIO_InitStruct.Pin = GPIO_PIN_11; 00688 GPIO_InitStruct.Pull = GPIO_NOPULL; 00689 GPIO_InitStruct.Speed = GPIO_SPEED_LOW; 00690 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 00691 00692 /* Set GPIOE pin 10 in no pull, low state (optimum default setting) */ 00693 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP ; 00694 GPIO_InitStruct.Pull = GPIO_NOPULL; 00695 GPIO_InitStruct.Pin = (GPIO_PIN_10); 00696 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 00697 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10, GPIO_PIN_RESET); 00698 00699 /* Reset the QuadSPI memory interface */ 00700 __HAL_RCC_QSPI_FORCE_RESET(); 00701 __HAL_RCC_QSPI_RELEASE_RESET(); 00702 00703 /* Disable the QuadSPI memory interface clock */ 00704 __HAL_RCC_QSPI_CLK_DISABLE(); 00705 } 00706 00707 /** 00708 * @brief This function reset the QSPI memory. 00709 * @param hqspi: QSPI handle 00710 * @retval None 00711 */ 00712 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00713 { 00714 QSPI_CommandTypeDef sCommand; 00715 00716 /* Initialize the reset enable command */ 00717 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00718 sCommand.Instruction = RESET_ENABLE_CMD; 00719 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00720 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00721 sCommand.DataMode = QSPI_DATA_NONE; 00722 sCommand.DummyCycles = 0; 00723 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00724 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00725 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00726 00727 /* Send the command */ 00728 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00729 { 00730 return QSPI_ERROR; 00731 } 00732 00733 /* Send the reset memory command */ 00734 sCommand.Instruction = RESET_MEMORY_CMD; 00735 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00736 { 00737 return QSPI_ERROR; 00738 } 00739 00740 /* Configure automatic polling mode to wait the memory is ready */ 00741 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00742 { 00743 return QSPI_ERROR; 00744 } 00745 00746 return QSPI_OK; 00747 } 00748 00749 /** 00750 * @brief This function configure the dummy cycles on memory side. 00751 * @param hqspi: QSPI handle 00752 * @retval None 00753 */ 00754 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00755 { 00756 QSPI_CommandTypeDef sCommand; 00757 uint8_t reg; 00758 00759 /* Initialize the read volatile configuration register command */ 00760 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00761 sCommand.Instruction = READ_VOL_CFG_REG_CMD; 00762 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00763 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00764 sCommand.DataMode = QSPI_DATA_1_LINE; 00765 sCommand.DummyCycles = 0; 00766 sCommand.NbData = 1; 00767 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00768 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00769 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00770 00771 /* Configure the command */ 00772 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00773 { 00774 return QSPI_ERROR; 00775 } 00776 00777 /* Reception of the data */ 00778 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00779 { 00780 return QSPI_ERROR; 00781 } 00782 00783 /* Enable write operations */ 00784 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00785 { 00786 return QSPI_ERROR; 00787 } 00788 00789 /* Update volatile configuration register (with new dummy cycles) */ 00790 sCommand.Instruction = WRITE_VOL_CFG_REG_CMD; 00791 MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY))); 00792 00793 /* Configure the write volatile configuration register command */ 00794 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00795 { 00796 return QSPI_ERROR; 00797 } 00798 00799 /* Transmission of the data */ 00800 if (HAL_QSPI_Transmit(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00801 { 00802 return QSPI_ERROR; 00803 } 00804 00805 return QSPI_OK; 00806 } 00807 00808 /** 00809 * @brief This function send a Write Enable and wait it is effective. 00810 * @param hqspi: QSPI handle 00811 * @retval None 00812 */ 00813 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 00814 { 00815 QSPI_CommandTypeDef sCommand; 00816 QSPI_AutoPollingTypeDef sConfig; 00817 00818 /* Enable write operations */ 00819 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00820 sCommand.Instruction = WRITE_ENABLE_CMD; 00821 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00822 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00823 sCommand.DataMode = QSPI_DATA_NONE; 00824 sCommand.DummyCycles = 0; 00825 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00826 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00827 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00828 00829 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00830 { 00831 return QSPI_ERROR; 00832 } 00833 00834 /* Configure automatic polling mode to wait for write enabling */ 00835 sConfig.Match = N25Q128A_SR_WREN; 00836 sConfig.Mask = N25Q128A_SR_WREN; 00837 sConfig.MatchMode = QSPI_MATCH_MODE_AND; 00838 sConfig.StatusBytesSize = 1; 00839 sConfig.Interval = 0x10; 00840 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00841 00842 sCommand.Instruction = READ_STATUS_REG_CMD; 00843 sCommand.DataMode = QSPI_DATA_1_LINE; 00844 00845 if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00846 { 00847 return QSPI_ERROR; 00848 } 00849 00850 return QSPI_OK; 00851 } 00852 00853 /** 00854 * @brief This function read the SR of the memory and wait the EOP. 00855 * @param hqspi: QSPI handle 00856 * @param Timeout: Timeout for auto-polling 00857 * @retval None 00858 */ 00859 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 00860 { 00861 QSPI_CommandTypeDef sCommand; 00862 QSPI_AutoPollingTypeDef sConfig; 00863 00864 /* Configure automatic polling mode to wait for memory ready */ 00865 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00866 sCommand.Instruction = READ_STATUS_REG_CMD; 00867 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00868 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00869 sCommand.DataMode = QSPI_DATA_1_LINE; 00870 sCommand.DummyCycles = 0; 00871 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00872 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00873 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00874 00875 sConfig.Match = 0; 00876 sConfig.Mask = N25Q128A_SR_WIP; 00877 sConfig.MatchMode = QSPI_MATCH_MODE_AND; 00878 sConfig.StatusBytesSize = 1; 00879 sConfig.Interval = 0x10; 00880 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00881 00882 if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK) 00883 { 00884 return QSPI_ERROR; 00885 } 00886 00887 return QSPI_OK; 00888 } 00889 00890 /** 00891 * @} 00892 */ 00893 00894 /** 00895 * @} 00896 */ 00897 00898 /** 00899 * @} 00900 */ 00901 00902 /** 00903 * @} 00904 */ 00905 00906 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00907
Generated on Tue Jun 23 2015 17:15:45 for STM32L476G-Discovery BSP User Manual by 1.7.6.1