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_F746NG by
stm32746g_discovery_qspi.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32746g_discovery_qspi.c 00004 * @author MCD Application Team 00005 * @version V1.0.0 00006 * @date 25-June-2015 00007 * @brief This file includes a standard driver for the N25Q128A QSPI 00008 * memory mounted on STM32746G-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 STM32746G-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) 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 STM32746G_DISCOVERY 00075 * @{ 00076 */ 00077 00078 /** @defgroup STM32746G_DISCOVERY_QSPI STM32746G-Discovery QSPI 00079 * @{ 00080 */ 00081 00082 00083 /* Private variables ---------------------------------------------------------*/ 00084 00085 /** @defgroup STM32746G_DISCOVERY_QSPI_Private_Variables STM32746G_DISCOVERY QSPI Private Variables 00086 * @{ 00087 */ 00088 QSPI_HandleTypeDef QSPIHandle; 00089 00090 /** 00091 * @} 00092 */ 00093 00094 00095 00096 /* Private functions ---------------------------------------------------------*/ 00097 00098 /** @defgroup STM32746G_DISCOVERY_QSPI_Private_Functions STM32746G_DISCOVERY QSPI Private Functions 00099 * @{ 00100 */ 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 /** @defgroup STM32746G_DISCOVERY_QSPI_Exported_Functions STM32746G_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 = 216 MHz/(1+1) = 108 Mhz */ 00133 QSPIHandle.Init.FifoThreshold = 4; 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_2_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 /* Configuration of the dummy cycles 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 BSP_QSPI_MspDeInit(&QSPIHandle, NULL); 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 s_command; 00191 00192 /* Initialize the read command */ 00193 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00194 s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; 00195 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00196 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00197 s_command.Address = ReadAddr; 00198 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00199 s_command.DataMode = QSPI_DATA_4_LINES; 00200 s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00201 s_command.NbData = Size; 00202 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00203 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00204 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00205 00206 /* Configure the command */ 00207 if (HAL_QSPI_Command(&QSPIHandle, &s_command, 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 s_command; 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 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00254 s_command.Instruction = EXT_QUAD_IN_FAST_PROG_CMD; 00255 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00256 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00257 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00258 s_command.DataMode = QSPI_DATA_4_LINES; 00259 s_command.DummyCycles = 0; 00260 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00261 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00262 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00263 00264 /* Perform the write page by page */ 00265 do 00266 { 00267 s_command.Address = current_addr; 00268 s_command.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, &s_command, 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 s_command; 00311 00312 /* Initialize the erase command */ 00313 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00314 s_command.Instruction = SUBSECTOR_ERASE_CMD; 00315 s_command.AddressMode = QSPI_ADDRESS_1_LINE; 00316 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00317 s_command.Address = BlockAddress; 00318 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00319 s_command.DataMode = QSPI_DATA_NONE; 00320 s_command.DummyCycles = 0; 00321 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00322 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00323 s_command.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, &s_command, 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 entire QSPI memory. 00348 * @retval QSPI memory status 00349 */ 00350 uint8_t BSP_QSPI_Erase_Chip(void) 00351 { 00352 QSPI_CommandTypeDef s_command; 00353 00354 /* Initialize the erase command */ 00355 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00356 s_command.Instruction = BULK_ERASE_CMD; 00357 s_command.AddressMode = QSPI_ADDRESS_NONE; 00358 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00359 s_command.DataMode = QSPI_DATA_NONE; 00360 s_command.DummyCycles = 0; 00361 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00362 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00363 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00364 00365 /* Enable write operations */ 00366 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00367 { 00368 return QSPI_ERROR; 00369 } 00370 00371 /* Send the command */ 00372 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00373 { 00374 return QSPI_ERROR; 00375 } 00376 00377 /* Configure automatic polling mode to wait for end of erase */ 00378 if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK) 00379 { 00380 return QSPI_ERROR; 00381 } 00382 00383 return QSPI_OK; 00384 } 00385 00386 /** 00387 * @brief Reads current status of the QSPI memory. 00388 * @retval QSPI memory status 00389 */ 00390 uint8_t BSP_QSPI_GetStatus(void) 00391 { 00392 QSPI_CommandTypeDef s_command; 00393 uint8_t reg; 00394 00395 /* Initialize the read flag status register command */ 00396 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00397 s_command.Instruction = READ_FLAG_STATUS_REG_CMD; 00398 s_command.AddressMode = QSPI_ADDRESS_NONE; 00399 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00400 s_command.DataMode = QSPI_DATA_1_LINE; 00401 s_command.DummyCycles = 0; 00402 s_command.NbData = 1; 00403 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00404 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00405 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00406 00407 /* Configure the command */ 00408 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00409 { 00410 return QSPI_ERROR; 00411 } 00412 00413 /* Reception of the data */ 00414 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00415 { 00416 return QSPI_ERROR; 00417 } 00418 00419 /* Check the value of the register */ 00420 if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0) 00421 { 00422 return QSPI_ERROR; 00423 } 00424 else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0) 00425 { 00426 return QSPI_SUSPENDED; 00427 } 00428 else if ((reg & N25Q128A_FSR_READY) != 0) 00429 { 00430 return QSPI_OK; 00431 } 00432 else 00433 { 00434 return QSPI_BUSY; 00435 } 00436 } 00437 00438 /** 00439 * @brief Return the configuration of the QSPI memory. 00440 * @param pInfo: pointer on the configuration structure 00441 * @retval QSPI memory status 00442 */ 00443 uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo) 00444 { 00445 /* Configure the structure with the memory configuration */ 00446 pInfo->FlashSize = N25Q128A_FLASH_SIZE; 00447 pInfo->EraseSectorSize = N25Q128A_SUBSECTOR_SIZE; 00448 pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE/N25Q128A_SUBSECTOR_SIZE); 00449 pInfo->ProgPageSize = N25Q128A_PAGE_SIZE; 00450 pInfo->ProgPagesNumber = (N25Q128A_FLASH_SIZE/N25Q128A_PAGE_SIZE); 00451 00452 return QSPI_OK; 00453 } 00454 00455 /** 00456 * @brief Configure the QSPI in memory-mapped mode 00457 * @retval QSPI memory status 00458 */ 00459 uint8_t BSP_QSPI_MemoryMappedMode(void) 00460 { 00461 QSPI_CommandTypeDef s_command; 00462 QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; 00463 00464 /* Configure the command for the read instruction */ 00465 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00466 s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; 00467 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00468 s_command.AddressSize = QSPI_ADDRESS_24_BITS; 00469 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00470 s_command.DataMode = QSPI_DATA_4_LINES; 00471 s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD; 00472 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00473 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00474 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00475 00476 /* Configure the memory mapped mode */ 00477 s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_ENABLE; 00478 s_mem_mapped_cfg.TimeOutPeriod = 1; 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 /** @addtogroup STM32746G_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 * @retval None 00503 */ 00504 __weak void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params) 00505 { 00506 GPIO_InitTypeDef gpio_init_structure; 00507 00508 /*##-1- Enable peripherals and GPIO Clocks #################################*/ 00509 /* Enable the QuadSPI memory interface clock */ 00510 QSPI_CLK_ENABLE(); 00511 /* Reset the QuadSPI memory interface */ 00512 QSPI_FORCE_RESET(); 00513 QSPI_RELEASE_RESET(); 00514 /* Enable GPIO clocks */ 00515 QSPI_CS_GPIO_CLK_ENABLE(); 00516 QSPI_CLK_GPIO_CLK_ENABLE(); 00517 QSPI_D0_GPIO_CLK_ENABLE(); 00518 QSPI_D1_GPIO_CLK_ENABLE(); 00519 QSPI_D2_GPIO_CLK_ENABLE(); 00520 QSPI_D3_GPIO_CLK_ENABLE(); 00521 00522 /*##-2- Configure peripheral GPIO ##########################################*/ 00523 /* QSPI CS GPIO pin configuration */ 00524 gpio_init_structure.Pin = QSPI_CS_PIN; 00525 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00526 gpio_init_structure.Pull = GPIO_PULLUP; 00527 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00528 gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; 00529 HAL_GPIO_Init(QSPI_CS_GPIO_PORT, &gpio_init_structure); 00530 00531 /* QSPI CLK GPIO pin configuration */ 00532 gpio_init_structure.Pin = QSPI_CLK_PIN; 00533 gpio_init_structure.Pull = GPIO_NOPULL; 00534 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00535 HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure); 00536 00537 /* QSPI D0 GPIO pin configuration */ 00538 gpio_init_structure.Pin = QSPI_D0_PIN; 00539 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00540 HAL_GPIO_Init(QSPI_D0_GPIO_PORT, &gpio_init_structure); 00541 00542 /* QSPI D1 GPIO pin configuration */ 00543 gpio_init_structure.Pin = QSPI_D1_PIN; 00544 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00545 HAL_GPIO_Init(QSPI_D1_GPIO_PORT, &gpio_init_structure); 00546 00547 /* QSPI D2 GPIO pin configuration */ 00548 gpio_init_structure.Pin = QSPI_D2_PIN; 00549 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00550 HAL_GPIO_Init(QSPI_D2_GPIO_PORT, &gpio_init_structure); 00551 00552 /* QSPI D3 GPIO pin configuration */ 00553 gpio_init_structure.Pin = QSPI_D3_PIN; 00554 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00555 HAL_GPIO_Init(QSPI_D3_GPIO_PORT, &gpio_init_structure); 00556 00557 /*##-3- Configure the NVIC for QSPI #########################################*/ 00558 /* NVIC configuration for QSPI interrupt */ 00559 HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0); 00560 HAL_NVIC_EnableIRQ(QUADSPI_IRQn); 00561 } 00562 00563 /** 00564 * @brief QSPI MSP De-Initialization 00565 * This function frees the hardware resources used in this example: 00566 * - Disable the Peripheral's clock 00567 * - Revert GPIO and NVIC configuration to their default state 00568 * @retval None 00569 */ 00570 __weak void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params) 00571 { 00572 /*##-1- Disable the NVIC for QSPI ###########################################*/ 00573 HAL_NVIC_DisableIRQ(QUADSPI_IRQn); 00574 00575 /*##-2- Disable peripherals and GPIO Clocks ################################*/ 00576 /* De-Configure QSPI pins */ 00577 HAL_GPIO_DeInit(QSPI_CS_GPIO_PORT, QSPI_CS_PIN); 00578 HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN); 00579 HAL_GPIO_DeInit(QSPI_D0_GPIO_PORT, QSPI_D0_PIN); 00580 HAL_GPIO_DeInit(QSPI_D1_GPIO_PORT, QSPI_D1_PIN); 00581 HAL_GPIO_DeInit(QSPI_D2_GPIO_PORT, QSPI_D2_PIN); 00582 HAL_GPIO_DeInit(QSPI_D3_GPIO_PORT, QSPI_D3_PIN); 00583 00584 /*##-3- Reset peripherals ##################################################*/ 00585 /* Reset the QuadSPI memory interface */ 00586 QSPI_FORCE_RESET(); 00587 QSPI_RELEASE_RESET(); 00588 00589 /* Disable the QuadSPI memory interface clock */ 00590 QSPI_CLK_DISABLE(); 00591 } 00592 00593 /** 00594 * @brief This function reset the QSPI memory. 00595 * @param hqspi: QSPI handle 00596 * @retval None 00597 */ 00598 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00599 { 00600 QSPI_CommandTypeDef s_command; 00601 00602 /* Initialize the reset enable command */ 00603 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00604 s_command.Instruction = RESET_ENABLE_CMD; 00605 s_command.AddressMode = QSPI_ADDRESS_NONE; 00606 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00607 s_command.DataMode = QSPI_DATA_NONE; 00608 s_command.DummyCycles = 0; 00609 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00610 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00611 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00612 00613 /* Send the command */ 00614 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00615 { 00616 return QSPI_ERROR; 00617 } 00618 00619 /* Send the reset memory command */ 00620 s_command.Instruction = RESET_MEMORY_CMD; 00621 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00622 { 00623 return QSPI_ERROR; 00624 } 00625 00626 /* Configure automatic polling mode to wait the memory is ready */ 00627 if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00628 { 00629 return QSPI_ERROR; 00630 } 00631 00632 return QSPI_OK; 00633 } 00634 00635 /** 00636 * @brief This function configure the dummy cycles on memory side. 00637 * @param hqspi: QSPI handle 00638 * @retval None 00639 */ 00640 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00641 { 00642 QSPI_CommandTypeDef s_command; 00643 uint8_t reg; 00644 00645 /* Initialize the read volatile configuration register command */ 00646 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00647 s_command.Instruction = READ_VOL_CFG_REG_CMD; 00648 s_command.AddressMode = QSPI_ADDRESS_NONE; 00649 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00650 s_command.DataMode = QSPI_DATA_1_LINE; 00651 s_command.DummyCycles = 0; 00652 s_command.NbData = 1; 00653 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00654 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00655 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00656 00657 /* Configure the command */ 00658 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00659 { 00660 return QSPI_ERROR; 00661 } 00662 00663 /* Reception of the data */ 00664 if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00665 { 00666 return QSPI_ERROR; 00667 } 00668 00669 /* Enable write operations */ 00670 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00671 { 00672 return QSPI_ERROR; 00673 } 00674 00675 /* Update volatile configuration register (with new dummy cycles) */ 00676 s_command.Instruction = WRITE_VOL_CFG_REG_CMD; 00677 MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY))); 00678 00679 /* Configure the write volatile configuration register command */ 00680 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00681 { 00682 return QSPI_ERROR; 00683 } 00684 00685 /* Transmission of the data */ 00686 if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00687 { 00688 return QSPI_ERROR; 00689 } 00690 00691 return QSPI_OK; 00692 } 00693 00694 /** 00695 * @brief This function send a Write Enable and wait it is effective. 00696 * @param hqspi: QSPI handle 00697 * @retval None 00698 */ 00699 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 00700 { 00701 QSPI_CommandTypeDef s_command; 00702 QSPI_AutoPollingTypeDef s_config; 00703 00704 /* Enable write operations */ 00705 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00706 s_command.Instruction = WRITE_ENABLE_CMD; 00707 s_command.AddressMode = QSPI_ADDRESS_NONE; 00708 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00709 s_command.DataMode = QSPI_DATA_NONE; 00710 s_command.DummyCycles = 0; 00711 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00712 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00713 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00714 00715 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00716 { 00717 return QSPI_ERROR; 00718 } 00719 00720 /* Configure automatic polling mode to wait for write enabling */ 00721 s_config.Match = N25Q128A_SR_WREN; 00722 s_config.Mask = N25Q128A_SR_WREN; 00723 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00724 s_config.StatusBytesSize = 1; 00725 s_config.Interval = 0x10; 00726 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00727 00728 s_command.Instruction = READ_STATUS_REG_CMD; 00729 s_command.DataMode = QSPI_DATA_1_LINE; 00730 00731 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00732 { 00733 return QSPI_ERROR; 00734 } 00735 00736 return QSPI_OK; 00737 } 00738 00739 /** 00740 * @brief This function read the SR of the memory and wait the EOP. 00741 * @param hqspi: QSPI handle 00742 * @param Timeout 00743 * @retval None 00744 */ 00745 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 00746 { 00747 QSPI_CommandTypeDef s_command; 00748 QSPI_AutoPollingTypeDef s_config; 00749 00750 /* Configure automatic polling mode to wait for memory ready */ 00751 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00752 s_command.Instruction = READ_STATUS_REG_CMD; 00753 s_command.AddressMode = QSPI_ADDRESS_NONE; 00754 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00755 s_command.DataMode = QSPI_DATA_1_LINE; 00756 s_command.DummyCycles = 0; 00757 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00758 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00759 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00760 00761 s_config.Match = 0; 00762 s_config.Mask = N25Q128A_SR_WIP; 00763 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00764 s_config.StatusBytesSize = 1; 00765 s_config.Interval = 0x10; 00766 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00767 00768 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK) 00769 { 00770 return QSPI_ERROR; 00771 } 00772 00773 return QSPI_OK; 00774 } 00775 /** 00776 * @} 00777 */ 00778 00779 /** 00780 * @} 00781 */ 00782 00783 /** 00784 * @} 00785 */ 00786 00787 /** 00788 * @} 00789 */ 00790 00791 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00792
Generated on Wed Jul 13 2022 13:25:21 by
1.7.2
