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