BSP library for DISCO-STM32F746NG board. Added support for on-board QSPI Flash memory MICRO N25Q128A. Ported from library BSP_DISCO_L476VG.
Fork of BSP_DISCO_F746NG by
stm32746g_discovery_qspi.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f746g_discovery_qspi.c 00004 * @author Florian SAVARD 00005 * @version V1.0.0 00006 * @date 15-november-2015 00007 * @brief This file includes a standard driver for the N25Q128A QSPI 00008 * memory mounted on STM32F746G-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 STM32F746G-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 "stm32746g_discovery_qspi.h" 00069 00070 /** @addtogroup BSP 00071 * @{ 00072 */ 00073 00074 /** @addtogroup STM32F746G_DISCOVERY 00075 * @{ 00076 */ 00077 00078 /** @defgroup STM32F746G_DISCOVERY_QSPI STM32F746G-DISCOVERY QSPI 00079 * @{ 00080 */ 00081 00082 /* Private variables ---------------------------------------------------------*/ 00083 00084 /** @defgroup STM32F746G_DISCOVERY_QSPI_Private_Variables Private Variables 00085 * @{ 00086 */ 00087 QSPI_HandleTypeDef QSPIHandle; 00088 00089 /** 00090 * @} 00091 */ 00092 00093 00094 /* Private functions ---------------------------------------------------------*/ 00095 00096 /** @defgroup STM32F746G_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 STM32F746G_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; // Defines the base address of the register structure of the QSPI peripheral 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 = 3; /* Clock = Fahb = ? 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 STM32F746G_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 /* DISCO-STM32F746NG : CS = PB6 */ 00661 GPIO_InitStruct.Pin = GPIO_PIN_6; 00662 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 00663 GPIO_InitStruct.Pull = GPIO_PULLUP; 00664 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 00665 GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; 00666 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00667 00668 /* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration */ 00669 /* DISCO-STM32F746NG : CLK = PB2 | D0 = PD11 | D1 = PD12 | D2 = PE2 | D3 = PD13 */ 00670 00671 GPIO_InitStruct.Pin = (GPIO_PIN_2); // CLK 00672 GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; 00673 GPIO_InitStruct.Pull = GPIO_NOPULL; 00674 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00675 00676 GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13); // D0, D1, D3 00677 GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; 00678 GPIO_InitStruct.Pull = GPIO_NOPULL; 00679 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); 00680 00681 GPIO_InitStruct.Pin = (GPIO_PIN_2); // D2 00682 GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; 00683 GPIO_InitStruct.Pull = GPIO_NOPULL; 00684 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 00685 } 00686 00687 /** 00688 * @brief De-Initializes the QSPI MSP. 00689 * @retval None 00690 */ 00691 static void QSPI_MspDeInit(void) 00692 { 00693 GPIO_InitTypeDef GPIO_InitStruct; 00694 00695 /* QSPI CLK, CS, PE10 - PE15 GPIO pins de-configuration */ 00696 00697 __HAL_RCC_GPIOE_CLK_ENABLE(); 00698 HAL_GPIO_DeInit(GPIOD, (GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13)); // D0, D1, D3 00699 HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2); // D2 00700 00701 /* Chip select pin de-configuration */ 00702 /* Set GPIOE pin 11 in pull up mode (optimum default setting) */ 00703 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 00704 GPIO_InitStruct.Pin = GPIO_PIN_6; 00705 GPIO_InitStruct.Pull = GPIO_NOPULL; 00706 GPIO_InitStruct.Speed = GPIO_SPEED_LOW; 00707 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00708 00709 /* CLK pin de-configuration */ 00710 /* Set GPIOE pin 10 in no pull, low state (optimum default setting) */ 00711 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP ; 00712 GPIO_InitStruct.Pull = GPIO_NOPULL; 00713 GPIO_InitStruct.Pin = (GPIO_PIN_2); 00714 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00715 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); 00716 00717 /* Reset the QuadSPI memory interface */ 00718 __HAL_RCC_QSPI_FORCE_RESET(); 00719 __HAL_RCC_QSPI_RELEASE_RESET(); 00720 00721 /* Disable the QuadSPI memory interface clock */ 00722 __HAL_RCC_QSPI_CLK_DISABLE(); 00723 } 00724 00725 /** 00726 * @brief This function reset the QSPI memory. 00727 * @param hqspi: QSPI handle 00728 * @retval None 00729 */ 00730 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00731 { 00732 QSPI_CommandTypeDef sCommand; 00733 00734 /* Initialize the reset enable command */ 00735 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00736 sCommand.Instruction = RESET_ENABLE_CMD; 00737 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00738 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00739 sCommand.DataMode = QSPI_DATA_NONE; 00740 sCommand.DummyCycles = 0; 00741 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00742 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00743 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00744 00745 /* Send the command */ 00746 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00747 { 00748 return QSPI_ERROR; 00749 } 00750 00751 /* Send the reset memory command */ 00752 sCommand.Instruction = RESET_MEMORY_CMD; 00753 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00754 { 00755 return QSPI_ERROR; 00756 } 00757 00758 /* Configure automatic polling mode to wait the memory is ready */ 00759 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00760 { 00761 return QSPI_ERROR; 00762 } 00763 00764 return QSPI_OK; 00765 } 00766 00767 /** 00768 * @brief This function configure the dummy cycles on memory side. 00769 * @param hqspi: QSPI handle 00770 * @retval None 00771 */ 00772 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00773 { 00774 QSPI_CommandTypeDef sCommand; 00775 uint8_t reg; 00776 00777 /* Initialize the read volatile configuration register command */ 00778 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00779 sCommand.Instruction = READ_VOL_CFG_REG_CMD; 00780 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00781 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00782 sCommand.DataMode = QSPI_DATA_1_LINE; 00783 sCommand.DummyCycles = 0; 00784 sCommand.NbData = 1; 00785 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00786 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00787 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00788 00789 /* Configure the command */ 00790 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00791 { 00792 return QSPI_ERROR; 00793 } 00794 00795 /* Reception of the data */ 00796 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00797 { 00798 return QSPI_ERROR; 00799 } 00800 00801 /* Enable write operations */ 00802 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00803 { 00804 return QSPI_ERROR; 00805 } 00806 00807 /* Update volatile configuration register (with new dummy cycles) */ 00808 sCommand.Instruction = WRITE_VOL_CFG_REG_CMD; 00809 MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY))); 00810 00811 /* Configure the write volatile configuration register command */ 00812 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00813 { 00814 return QSPI_ERROR; 00815 } 00816 00817 /* Transmission of the data */ 00818 if (HAL_QSPI_Transmit(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00819 { 00820 return QSPI_ERROR; 00821 } 00822 00823 return QSPI_OK; 00824 } 00825 00826 /** 00827 * @brief This function send a Write Enable and wait it is effective. 00828 * @param hqspi: QSPI handle 00829 * @retval None 00830 */ 00831 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 00832 { 00833 QSPI_CommandTypeDef sCommand; 00834 QSPI_AutoPollingTypeDef sConfig; 00835 00836 /* Enable write operations */ 00837 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00838 sCommand.Instruction = WRITE_ENABLE_CMD; 00839 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00840 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00841 sCommand.DataMode = QSPI_DATA_NONE; 00842 sCommand.DummyCycles = 0; 00843 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00844 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00845 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00846 00847 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00848 { 00849 return QSPI_ERROR; 00850 } 00851 00852 /* Configure automatic polling mode to wait for write enabling */ 00853 sConfig.Match = N25Q128A_SR_WREN; 00854 sConfig.Mask = N25Q128A_SR_WREN; 00855 sConfig.MatchMode = QSPI_MATCH_MODE_AND; 00856 sConfig.StatusBytesSize = 1; 00857 sConfig.Interval = 0x10; 00858 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00859 00860 sCommand.Instruction = READ_STATUS_REG_CMD; 00861 sCommand.DataMode = QSPI_DATA_1_LINE; 00862 00863 if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00864 { 00865 return QSPI_ERROR; 00866 } 00867 00868 return QSPI_OK; 00869 } 00870 00871 /** 00872 * @brief This function read the SR of the memory and wait the EOP. 00873 * @param hqspi: QSPI handle 00874 * @param Timeout: Timeout for auto-polling 00875 * @retval None 00876 */ 00877 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 00878 { 00879 QSPI_CommandTypeDef sCommand; 00880 QSPI_AutoPollingTypeDef sConfig; 00881 00882 /* Configure automatic polling mode to wait for memory ready */ 00883 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00884 sCommand.Instruction = READ_STATUS_REG_CMD; 00885 sCommand.AddressMode = QSPI_ADDRESS_NONE; 00886 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00887 sCommand.DataMode = QSPI_DATA_1_LINE; 00888 sCommand.DummyCycles = 0; 00889 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 00890 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00891 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00892 00893 sConfig.Match = 0; 00894 sConfig.Mask = N25Q128A_SR_WIP; 00895 sConfig.MatchMode = QSPI_MATCH_MODE_AND; 00896 sConfig.StatusBytesSize = 1; 00897 sConfig.Interval = 0x10; 00898 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00899 00900 if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK) 00901 { 00902 return QSPI_ERROR; 00903 } 00904 00905 return QSPI_OK; 00906 } 00907 00908 /** 00909 * @} 00910 */ 00911 00912 /** 00913 * @} 00914 */ 00915 00916 /** 00917 * @} 00918 */ 00919 00920 /** 00921 * @} 00922 */ 00923 00924 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00925
Generated on Tue Jul 12 2022 16:12:49 by 1.7.2