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