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.
Fork of BSP_DISCO_F469NI by
stm32469i_discovery_qspi.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32469i_discovery_qspi.c 00004 * @author MCD Application Team 00005 * @version V2.0.0 00006 * @date 27-January-2017 00007 * @brief This file includes a standard driver for the N25Q128A QSPI 00008 * memory mounted on STM32469I-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 STM32469I-Discovery 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) 2017 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 "stm32469i_discovery_qspi.h" 00069 00070 /** @addtogroup BSP 00071 * @{ 00072 */ 00073 00074 /** @addtogroup STM32469I_Discovery 00075 * @{ 00076 */ 00077 00078 /** @defgroup STM32469I_Discovery_QSPI STM32469I Discovery QSPI 00079 * @{ 00080 */ 00081 00082 00083 /* Private variables ---------------------------------------------------------*/ 00084 00085 00086 /** @defgroup STM32469I_Discovery_QSPI_Private_Variables STM32469I Discovery QSPI Private Variables 00087 * @{ 00088 */ 00089 QSPI_HandleTypeDef QSPIHandle; 00090 00091 /** 00092 * @} 00093 */ 00094 00095 00096 00097 /* Private functions ---------------------------------------------------------*/ 00098 00099 /** @defgroup STM32469I_Discovery_QSPI_Private_Functions STM32469I Discovery QSPI Private Functions 00100 * @{ 00101 */ 00102 static uint8_t QSPI_ResetMemory (QSPI_HandleTypeDef *hqspi); 00103 static uint8_t QSPI_DummyCyclesCfg (QSPI_HandleTypeDef *hqspi); 00104 static uint8_t QSPI_WriteEnable (QSPI_HandleTypeDef *hqspi); 00105 static uint8_t QSPI_AutoPollingMemReady (QSPI_HandleTypeDef *hqspi, uint32_t Timeout); 00106 00107 00108 /** 00109 * @} 00110 */ 00111 00112 /** @defgroup STM32469I_Discovery_QSPI_Exported_Functions STM32469I 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 BSP_QSPI_MspInit(&QSPIHandle, NULL); 00132 00133 /* QSPI initialization */ 00134 QSPIHandle.Init.ClockPrescaler = 1; /* QSPI Freq= 180 MHz / (1+1) = 90 MHz */ 00135 QSPIHandle.Init.FifoThreshold = 1; 00136 QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; 00137 QSPIHandle.Init.FlashSize = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1; 00138 QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE; 00139 QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; 00140 QSPIHandle.Init.FlashID = QSPI_FLASH_ID_1; 00141 QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_DISABLE; 00142 00143 if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) 00144 { 00145 return QSPI_ERROR; 00146 } 00147 00148 /* QSPI memory reset */ 00149 if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) 00150 { 00151 return QSPI_NOT_SUPPORTED; 00152 } 00153 00154 00155 /* Configuration of the dummy cucles on QSPI memory side */ 00156 if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK) 00157 { 00158 return QSPI_NOT_SUPPORTED; 00159 } 00160 00161 return QSPI_OK; 00162 } 00163 00164 /** 00165 * @brief De-Initializes the QSPI interface. 00166 * @retval QSPI memory status 00167 */ 00168 uint8_t BSP_QSPI_DeInit(void) 00169 { 00170 QSPIHandle.Instance = QUADSPI; 00171 00172 /* Call the DeInit function to reset the driver */ 00173 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00174 { 00175 return QSPI_ERROR; 00176 } 00177 00178 /* System level De-initialization */ 00179 BSP_QSPI_MspDeInit(&QSPIHandle, NULL); 00180 00181 return QSPI_OK; 00182 } 00183 00184 /** 00185 * @brief Reads an amount of data from the QSPI memory. 00186 * @param pData: Pointer to data to be read 00187 * @param ReadAddr: Read start address 00188 * @param Size: Size of data to read 00189 * @retval QSPI memory status 00190 */ 00191 uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) 00192 { 00193 QSPI_CommandTypeDef s_command; 00194 00195 /* Initialize the read command */ 00196 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00197 s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; 00198 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00199 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00200 s_command.Address = ReadAddr; 00201 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00202 s_command.DataMode = QSPI_DATA_4_LINES; 00203 s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00204 s_command.NbData = Size; 00205 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00206 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00207 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00208 00209 /* Configure the command */ 00210 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00211 { 00212 return QSPI_ERROR; 00213 } 00214 00215 /* Set S# timing for Read command: Min 20ns for N25Q128A memory */ 00216 MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_2_CYCLE); 00217 00218 /* Reception of the data */ 00219 if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00220 { 00221 return QSPI_ERROR; 00222 } 00223 00224 /* Restore S# timing for nonRead commands */ 00225 MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_5_CYCLE); 00226 00227 return QSPI_OK; 00228 } 00229 00230 /** 00231 * @brief Writes an amount of data to the QSPI memory. 00232 * @param pData: Pointer to data to be written 00233 * @param WriteAddr: Write start address 00234 * @param Size: Size of data to write 00235 * @retval QSPI memory status 00236 */ 00237 uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) 00238 { 00239 QSPI_CommandTypeDef s_command; 00240 uint32_t end_addr, current_size, current_addr; 00241 00242 /* Calculation of the size between the write address and the end of the page */ 00243 current_size = N25Q128A_PAGE_SIZE - (WriteAddr % N25Q128A_PAGE_SIZE); 00244 00245 /* Check if the size of the data is less than the remaining place in the page */ 00246 if (current_size > Size) 00247 { 00248 current_size = Size; 00249 } 00250 00251 /* Initialize the address variables */ 00252 current_addr = WriteAddr; 00253 end_addr = WriteAddr + Size; 00254 00255 /* Initialize the program command */ 00256 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00257 s_command.Instruction = EXT_QUAD_IN_FAST_PROG_CMD; 00258 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00259 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00260 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00261 s_command.DataMode = QSPI_DATA_4_LINES; 00262 s_command.DummyCycles = 0; 00263 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00264 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00265 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00266 00267 /* Perform the write page by page */ 00268 do 00269 { 00270 s_command.Address = current_addr; 00271 s_command.NbData = current_size; 00272 00273 /* Enable write operations */ 00274 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00275 { 00276 return QSPI_ERROR; 00277 } 00278 00279 /* Configure the command */ 00280 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00281 { 00282 return QSPI_ERROR; 00283 } 00284 00285 /* Transmission of the data */ 00286 if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00287 { 00288 return QSPI_ERROR; 00289 } 00290 00291 /* Configure automatic polling mode to wait for end of program */ 00292 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00293 { 00294 return QSPI_ERROR; 00295 } 00296 00297 /* Update the address and size variables for next page programming */ 00298 current_addr += current_size; 00299 pData += current_size; 00300 current_size = ((current_addr + N25Q128A_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : N25Q128A_PAGE_SIZE; 00301 } while (current_addr < end_addr); 00302 00303 return QSPI_OK; 00304 } 00305 00306 /** 00307 * @brief Erases the specified block of the QSPI memory. 00308 * @param BlockAddress: Block address to erase 00309 * @retval QSPI memory status 00310 */ 00311 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) 00312 { 00313 QSPI_CommandTypeDef s_command; 00314 00315 /* Initialize the erase command */ 00316 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00317 s_command.Instruction = SUBSECTOR_ERASE_CMD; 00318 s_command.AddressMode = QSPI_ADDRESS_1_LINE; 00319 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00320 s_command.Address = BlockAddress; 00321 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00322 s_command.DataMode = QSPI_DATA_NONE; 00323 s_command.DummyCycles = 0; 00324 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00325 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00326 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00327 00328 /* Enable write operations */ 00329 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00330 { 00331 return QSPI_ERROR; 00332 } 00333 00334 /* Send the command */ 00335 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00336 { 00337 return QSPI_ERROR; 00338 } 00339 00340 /* Configure automatic polling mode to wait for end of erase */ 00341 if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK) 00342 { 00343 return QSPI_ERROR; 00344 } 00345 00346 return QSPI_OK; 00347 } 00348 00349 /** 00350 * @brief Erases the entire QSPI memory. 00351 * @retval QSPI memory status 00352 */ 00353 uint8_t BSP_QSPI_Erase_Chip(void) 00354 { 00355 QSPI_CommandTypeDef s_command; 00356 00357 /* Initialize the erase command */ 00358 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00359 s_command.Instruction = BULK_ERASE_CMD; 00360 s_command.AddressMode = QSPI_ADDRESS_NONE; 00361 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00362 s_command.DataMode = QSPI_DATA_NONE; 00363 s_command.DummyCycles = 0; 00364 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00365 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00366 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00367 00368 /* Enable write operations */ 00369 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00370 { 00371 return QSPI_ERROR; 00372 } 00373 00374 /* Send the command */ 00375 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00376 { 00377 return QSPI_ERROR; 00378 } 00379 00380 /* Configure automatic polling mode to wait for end of erase */ 00381 if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK) 00382 { 00383 return QSPI_ERROR; 00384 } 00385 00386 return QSPI_OK; 00387 } 00388 00389 /** 00390 * @brief Reads current status of the QSPI memory. 00391 * @retval QSPI memory status 00392 */ 00393 uint8_t BSP_QSPI_GetStatus(void) 00394 { 00395 QSPI_CommandTypeDef s_command; 00396 uint8_t reg; 00397 00398 /* Initialize the read flag status register command */ 00399 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00400 s_command.Instruction = READ_FLAG_STATUS_REG_CMD; 00401 s_command.AddressMode = QSPI_ADDRESS_NONE; 00402 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00403 s_command.DataMode = QSPI_DATA_1_LINE; 00404 s_command.DummyCycles = 0; 00405 s_command.NbData = 1; 00406 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00407 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00408 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00409 00410 /* Configure the command */ 00411 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00412 { 00413 return QSPI_ERROR; 00414 } 00415 00416 /* Reception of the data */ 00417 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00418 { 00419 return QSPI_ERROR; 00420 } 00421 00422 /* Check the value of the register */ 00423 if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0) 00424 { 00425 return QSPI_ERROR; 00426 } 00427 else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0) 00428 { 00429 return QSPI_SUSPENDED; 00430 } 00431 else if ((reg & N25Q128A_FSR_READY) != 0) 00432 { 00433 return QSPI_OK; 00434 } 00435 else 00436 { 00437 return QSPI_BUSY; 00438 } 00439 } 00440 00441 /** 00442 * @brief Reads the configuration of the memory and fills QspiInfo struct 00443 * @param pInfo pointer to Info structure 00444 * @retval QSPI memory status 00445 */ 00446 uint8_t BSP_QSPI_GetInfo(QSPI_InfoTypeDef* pInfo) 00447 { 00448 /* Configure the structure with the memory configuration */ 00449 pInfo->FlashSize = N25Q128A_FLASH_SIZE; 00450 pInfo->EraseSectorSize = N25Q128A_SUBSECTOR_SIZE; 00451 pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE/N25Q128A_SUBSECTOR_SIZE); 00452 pInfo->ProgPageSize = N25Q128A_PAGE_SIZE; 00453 pInfo->ProgPagesNumber = (N25Q128A_FLASH_SIZE/N25Q128A_PAGE_SIZE); 00454 00455 return QSPI_OK; 00456 } 00457 00458 /** 00459 * @brief Configure the QSPI in memory-mapped mode 00460 * @retval QSPI memory status 00461 */ 00462 uint8_t BSP_QSPI_EnableMemoryMappedMode(void) 00463 { 00464 QSPI_CommandTypeDef s_command; 00465 QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; 00466 00467 /* Configure the command for the read instruction */ 00468 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00469 s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; 00470 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00471 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00472 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00473 s_command.DataMode = QSPI_DATA_4_LINES; 00474 s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00475 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00476 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00477 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00478 00479 /* Configure the memory mapped mode */ 00480 s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; 00481 00482 if (HAL_QSPI_MemoryMapped(&QSPIHandle, &s_command, &s_mem_mapped_cfg) != HAL_OK) 00483 { 00484 return QSPI_ERROR; 00485 } 00486 00487 return QSPI_OK; 00488 } 00489 00490 /** 00491 * @} 00492 */ 00493 00494 /** @defgroup STM32469I_Discovery_QSPI_Private_Functions STM32469I Discovery QSPI Private Functions 00495 * @{ 00496 */ 00497 00498 /** 00499 * @brief QSPI MSP Initialization 00500 * This function configures the hardware resources used in this example: 00501 * - Peripheral's clock enable 00502 * - Peripheral's GPIO Configuration 00503 * - NVIC configuration for QSPI interrupt 00504 */ 00505 __weak void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params) 00506 { 00507 GPIO_InitTypeDef gpio_init_structure; 00508 00509 /*##-1- Enable peripherals and GPIO Clocks #################################*/ 00510 /* Enable the QuadSPI memory interface clock */ 00511 QSPI_CLK_ENABLE(); 00512 /* Reset the QuadSPI memory interface */ 00513 QSPI_FORCE_RESET(); 00514 QSPI_RELEASE_RESET(); 00515 /* Enable GPIO clocks */ 00516 QSPI_CS_GPIO_CLK_ENABLE(); 00517 QSPI_DX_CLK_GPIO_CLK_ENABLE(); 00518 00519 /*##-2- Configure peripheral GPIO ##########################################*/ 00520 /* QSPI CS GPIO pin configuration */ 00521 gpio_init_structure.Pin = QSPI_CS_PIN; 00522 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00523 gpio_init_structure.Pull = GPIO_PULLUP; 00524 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00525 gpio_init_structure.Alternate = GPIO_AF10_QSPI; 00526 HAL_GPIO_Init(QSPI_CS_GPIO_PORT, &gpio_init_structure); 00527 00528 /* QSPI CLK GPIO pin configuration */ 00529 gpio_init_structure.Pin = QSPI_CLK_PIN; 00530 gpio_init_structure.Pull = GPIO_NOPULL; 00531 gpio_init_structure.Alternate = GPIO_AF9_QSPI; 00532 HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure); 00533 00534 /* QSPI D0 and D1 GPIO pin configuration */ 00535 gpio_init_structure.Pin = (QSPI_D0_PIN | QSPI_D1_PIN); 00536 gpio_init_structure.Alternate = GPIO_AF10_QSPI; 00537 HAL_GPIO_Init(QSPI_DX_GPIO_PORT, &gpio_init_structure); 00538 00539 /* QSPI D2 and D3 GPIO pin configuration */ 00540 gpio_init_structure.Pin = (QSPI_D2_PIN | QSPI_D3_PIN) ; 00541 gpio_init_structure.Alternate = GPIO_AF9_QSPI; 00542 HAL_GPIO_Init(QSPI_DX_GPIO_PORT, &gpio_init_structure); 00543 00544 /*##-3- Configure the NVIC for QSPI #########################################*/ 00545 /* NVIC configuration for QSPI interrupt */ 00546 HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0); 00547 HAL_NVIC_EnableIRQ(QUADSPI_IRQn); 00548 00549 } 00550 00551 /** 00552 * @brief QSPI MSP De-Initialization 00553 * This function frees the hardware resources used in this example: 00554 * - Disable the Peripheral's clock 00555 * - Revert GPIO and NVIC configuration to their default state 00556 */ 00557 __weak void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params) 00558 { 00559 /*##-1- Disable the NVIC for QSPI ###########################################*/ 00560 HAL_NVIC_DisableIRQ(QUADSPI_IRQn); 00561 00562 /*##-2- Disable peripherals and GPIO Clocks ################################*/ 00563 /* De-Configure QSPI pins */ 00564 HAL_GPIO_DeInit(QSPI_CS_GPIO_PORT, QSPI_CS_PIN); 00565 HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN); 00566 HAL_GPIO_DeInit(QSPI_DX_GPIO_PORT, QSPI_D0_PIN); 00567 HAL_GPIO_DeInit(QSPI_DX_GPIO_PORT, QSPI_D1_PIN); 00568 HAL_GPIO_DeInit(QSPI_DX_GPIO_PORT, QSPI_D2_PIN); 00569 HAL_GPIO_DeInit(QSPI_DX_GPIO_PORT, QSPI_D3_PIN); 00570 00571 /*##-3- Reset peripherals ##################################################*/ 00572 /* Reset the QuadSPI memory interface */ 00573 QSPI_FORCE_RESET(); 00574 QSPI_RELEASE_RESET(); 00575 00576 /* Disable the QuadSPI memory interface clock */ 00577 QSPI_CLK_DISABLE(); 00578 } 00579 00580 /** 00581 * @brief This function reset the QSPI memory. 00582 * @param hqspi: QSPI handle 00583 */ 00584 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00585 { 00586 QSPI_CommandTypeDef s_command; 00587 00588 /* Initialize the reset enable command */ 00589 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00590 s_command.Instruction = RESET_ENABLE_CMD; 00591 s_command.AddressMode = QSPI_ADDRESS_NONE; 00592 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00593 s_command.DataMode = QSPI_DATA_NONE; 00594 s_command.DummyCycles = 0; 00595 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00596 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00597 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00598 00599 /* Send the command */ 00600 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00601 { 00602 return QSPI_ERROR; 00603 } 00604 00605 /* Send the reset memory command */ 00606 s_command.Instruction = RESET_MEMORY_CMD; 00607 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00608 { 00609 return QSPI_ERROR; 00610 } 00611 00612 /* Configure automatic polling mode to wait the memory is ready */ 00613 if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00614 { 00615 return QSPI_ERROR; 00616 } 00617 00618 return QSPI_OK; 00619 } 00620 00621 /** 00622 * @brief This function configure the dummy cycles on memory side. 00623 * @param hqspi: QSPI handle 00624 */ 00625 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00626 { 00627 QSPI_CommandTypeDef s_command; 00628 uint8_t reg; 00629 00630 /* Initialize the read volatile configuration register command */ 00631 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00632 s_command.Instruction = READ_VOL_CFG_REG_CMD; 00633 s_command.AddressMode = QSPI_ADDRESS_NONE; 00634 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00635 s_command.DataMode = QSPI_DATA_1_LINE; 00636 s_command.DummyCycles = 0; 00637 s_command.NbData = 1; 00638 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00639 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00640 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00641 00642 /* Configure the command */ 00643 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00644 { 00645 return QSPI_ERROR; 00646 } 00647 00648 /* Reception of the data */ 00649 if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00650 { 00651 return QSPI_ERROR; 00652 } 00653 00654 /* Enable write operations */ 00655 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00656 { 00657 return QSPI_ERROR; 00658 } 00659 00660 /* Update volatile configuration register (with new dummy cycles) */ 00661 s_command.Instruction = WRITE_VOL_CFG_REG_CMD; 00662 MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY))); 00663 00664 /* Configure the write volatile configuration register command */ 00665 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00666 { 00667 return QSPI_ERROR; 00668 } 00669 00670 /* Transmission of the data */ 00671 if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00672 { 00673 return QSPI_ERROR; 00674 } 00675 00676 return QSPI_OK; 00677 } 00678 00679 /** 00680 * @brief This function send a Write Enable and wait it is effective. 00681 * @param hqspi: QSPI handle 00682 */ 00683 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 00684 { 00685 QSPI_CommandTypeDef s_command; 00686 QSPI_AutoPollingTypeDef s_config; 00687 00688 /* Enable write operations */ 00689 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00690 s_command.Instruction = WRITE_ENABLE_CMD; 00691 s_command.AddressMode = QSPI_ADDRESS_NONE; 00692 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00693 s_command.DataMode = QSPI_DATA_NONE; 00694 s_command.DummyCycles = 0; 00695 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00696 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00697 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00698 00699 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00700 { 00701 return QSPI_ERROR; 00702 } 00703 00704 /* Configure automatic polling mode to wait for write enabling */ 00705 s_config.Match = N25Q128A_SR_WREN; 00706 s_config.Mask = N25Q128A_SR_WREN; 00707 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00708 s_config.StatusBytesSize = 1; 00709 s_config.Interval = 0x10; 00710 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00711 00712 s_command.Instruction = READ_STATUS_REG_CMD; 00713 s_command.DataMode = QSPI_DATA_1_LINE; 00714 00715 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00716 { 00717 return QSPI_ERROR; 00718 } 00719 00720 return QSPI_OK; 00721 } 00722 00723 /** 00724 * @brief This function read the SR of the memory and wait the EOP. 00725 * @param hqspi: QSPI handle 00726 * @param Timeout: timeout value before returning an error 00727 */ 00728 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 00729 { 00730 QSPI_CommandTypeDef s_command; 00731 QSPI_AutoPollingTypeDef s_config; 00732 00733 /* Configure automatic polling mode to wait for memory ready */ 00734 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00735 s_command.Instruction = READ_STATUS_REG_CMD; 00736 s_command.AddressMode = QSPI_ADDRESS_NONE; 00737 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00738 s_command.DataMode = QSPI_DATA_1_LINE; 00739 s_command.DummyCycles = 0; 00740 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00741 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00742 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00743 00744 s_config.Match = 0; 00745 s_config.Mask = N25Q128A_SR_WIP; 00746 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00747 s_config.StatusBytesSize = 1; 00748 s_config.Interval = 0x10; 00749 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00750 00751 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK) 00752 { 00753 return QSPI_ERROR; 00754 } 00755 00756 return QSPI_OK; 00757 } 00758 /** 00759 * @} 00760 */ 00761 00762 /** 00763 * @} 00764 */ 00765 00766 /** 00767 * @} 00768 */ 00769 00770 /** 00771 * @} 00772 */ 00773 00774 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00775
Generated on Wed Jul 13 2022 22:17:00 by
1.7.2
