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