BSP files for STM32H747I-Discovery Copy from ST Cube delivery
Dependents: DISCO_H747I_LCD_demo DISCO_H747I_AUDIO_demo
stm32h747i_discovery_qspi.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h747i_discovery_qspi.c 00004 * @author MCD Application Team 00005 * @brief This file includes a standard driver for the MT25TL01G QSPI 00006 * memory mounted on STM32H747I-DISCOVERY board. 00007 @verbatim 00008 ============================================================================== 00009 ##### How to use this driver ##### 00010 ============================================================================== 00011 [..] 00012 (#) This driver is used to drive the MT25TL01G QSPI external 00013 memory mounted on STM32H747I-DISCOVERY board. 00014 00015 (#) This driver need a specific component driver (MT25TL01G) 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) 2019 STMicroelectronics. 00039 * All rights reserved.</center></h2> 00040 * 00041 * This software component is licensed by ST under BSD 3-Clause license, 00042 * the "License"; You may not use this file except in compliance with the 00043 * License. You may obtain a copy of the License at: 00044 * opensource.org/licenses/BSD-3-Clause 00045 * 00046 ****************************************************************************** 00047 */ 00048 00049 /* Includes ------------------------------------------------------------------*/ 00050 #include "stm32h747i_discovery_qspi.h" 00051 00052 /** @addtogroup BSP 00053 * @{ 00054 */ 00055 00056 /** @addtogroup STM32H747I_DISCOVERY 00057 * @{ 00058 */ 00059 00060 /** @defgroup STM32H747I_DISCOVERY_QSPI STM32H747I_DISCOVERY_QSPI 00061 * @{ 00062 */ 00063 00064 00065 /* Private variables ---------------------------------------------------------*/ 00066 00067 /** @defgroup STM32H747I_DISCOVERY_QSPI_Private_Variables Private Variables 00068 * @{ 00069 */ 00070 QSPI_HandleTypeDef QSPIHandle; 00071 00072 /** 00073 * @} 00074 */ 00075 00076 /* Private functions ---------------------------------------------------------*/ 00077 00078 /** @defgroup STM32H747I_DISCOVERY_QSPI_Private_Functions Private Functions 00079 * @{ 00080 */ 00081 static uint8_t QSPI_ResetMemory (QSPI_HandleTypeDef *hqspi); 00082 static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi); 00083 static uint8_t QSPI_DummyCyclesCfg (QSPI_HandleTypeDef *hqspi); 00084 static uint8_t QSPI_WriteEnable (QSPI_HandleTypeDef *hqspi); 00085 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout); 00086 static uint8_t QSPI_EnterQPI(QSPI_HandleTypeDef *hqspi); 00087 /** 00088 * @} 00089 */ 00090 00091 /** @defgroup STM32H747I_DISCOVERY_QSPI_Exported_Functions Exported Functions 00092 * @{ 00093 */ 00094 00095 /** 00096 * @brief Initializes the QSPI interface. 00097 * @retval QSPI memory status 00098 */ 00099 uint8_t BSP_QSPI_Init(void) 00100 { 00101 QSPIHandle.Instance = QUADSPI; 00102 00103 /* Call the DeInit function to reset the driver */ 00104 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00105 { 00106 return QSPI_ERROR; 00107 } 00108 00109 /* System level initialization */ 00110 BSP_QSPI_MspInit(&QSPIHandle, NULL); 00111 00112 /* QSPI initialization */ 00113 /* ClockPrescaler set to 1, so QSPI clock = 200MHz / (1+3) = 50MHz */ 00114 QSPIHandle.Init.ClockPrescaler = 3; 00115 QSPIHandle.Init.FifoThreshold = 1; 00116 QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; 00117 QSPIHandle.Init.FlashSize = POSITION_VAL(MT25TL01G_FLASH_SIZE) - 1; 00118 QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE; 00119 QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; 00120 QSPIHandle.Init.FlashID = QSPI_FLASH_ID_2; 00121 QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_ENABLE; 00122 00123 if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) 00124 { 00125 return QSPI_ERROR; 00126 } 00127 00128 /* QSPI memory reset */ 00129 if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) 00130 { 00131 return QSPI_NOT_SUPPORTED; 00132 } 00133 00134 /* Set the QSPI memory in 4-bytes address mode */ 00135 if (QSPI_EnterFourBytesAddress(&QSPIHandle) != QSPI_OK) 00136 { 00137 return QSPI_NOT_SUPPORTED; 00138 } 00139 00140 /* Configuration of the dummy cycles on QSPI memory side */ 00141 if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK) 00142 { 00143 return QSPI_NOT_SUPPORTED; 00144 } 00145 00146 return QSPI_OK; 00147 } 00148 00149 /** 00150 * @brief De-Initializes the QSPI interface. 00151 * @retval QSPI memory status 00152 */ 00153 uint8_t BSP_QSPI_DeInit(void) 00154 { 00155 QSPIHandle.Instance = QUADSPI; 00156 00157 /* Call the DeInit function to reset the driver */ 00158 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00159 { 00160 return QSPI_ERROR; 00161 } 00162 00163 /* System level De-initialization */ 00164 BSP_QSPI_MspDeInit(&QSPIHandle, NULL); 00165 00166 return QSPI_OK; 00167 } 00168 00169 /** 00170 * @brief Reads an amount of data from the QSPI memory. 00171 * @param pData: Pointer to data to be read 00172 * @param ReadAddr: Read start address 00173 * @param Size: Size of data to read 00174 * @retval QSPI memory status 00175 */ 00176 uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) 00177 { 00178 QSPI_CommandTypeDef s_command; 00179 00180 /* Initialize the read command */ 00181 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00182 s_command.Instruction = QUAD_INOUT_FAST_READ_DTR_CMD; /* DTR QUAD INPUT/OUTPUT FAST READ and 4-BYTE DTR FAST READ commands */ 00183 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00184 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00185 s_command.Address = ReadAddr; 00186 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00187 s_command.DataMode = QSPI_DATA_4_LINES; 00188 s_command.DummyCycles = MT25TL01G_DUMMY_CYCLES_READ_QUAD_DTR - 1; 00189 s_command.NbData = Size; 00190 s_command.DdrMode = QSPI_DDR_MODE_ENABLE; 00191 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_HALF_CLK_DELAY; 00192 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00193 00194 /* Configure the command */ 00195 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00196 { 00197 return QSPI_ERROR; 00198 } 00199 00200 /* Reception of the data */ 00201 if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00202 { 00203 return QSPI_ERROR; 00204 } 00205 00206 return QSPI_OK; 00207 } 00208 00209 /** 00210 * @brief Writes an amount of data to the QSPI memory. 00211 * @param pData: Pointer to data to be written 00212 * @param WriteAddr: Write start address 00213 * @param Size: Size of data to write 00214 * @retval QSPI memory status 00215 */ 00216 uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) 00217 { 00218 QSPI_CommandTypeDef s_command; 00219 uint32_t end_addr, current_size, current_addr; 00220 00221 /* Calculation of the size between the write address and the end of the page */ 00222 current_size = MT25TL01G_PAGE_SIZE - (WriteAddr % MT25TL01G_PAGE_SIZE); 00223 00224 /* Check if the size of the data is less than the remaining place in the page */ 00225 if (current_size > Size) 00226 { 00227 current_size = Size; 00228 } 00229 00230 /* Initialize the address variables */ 00231 current_addr = WriteAddr; 00232 end_addr = WriteAddr + Size; 00233 00234 /* Initialize the program command */ 00235 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00236 s_command.Instruction = QUAD_IN_FAST_PROG_4_BYTE_ADDR_CMD; 00237 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00238 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00239 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00240 s_command.DataMode = QSPI_DATA_4_LINES; 00241 s_command.DummyCycles = 0; 00242 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00243 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00244 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00245 00246 /* Perform the write page by page */ 00247 do 00248 { 00249 s_command.Address = current_addr; 00250 s_command.NbData = current_size; 00251 00252 /* Enable write operations */ 00253 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00254 { 00255 return QSPI_ERROR; 00256 } 00257 00258 /* Configure the command */ 00259 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00260 { 00261 return QSPI_ERROR; 00262 } 00263 00264 /* Transmission of the data */ 00265 if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00266 { 00267 return QSPI_ERROR; 00268 } 00269 00270 /* Configure automatic polling mode to wait for end of program */ 00271 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00272 { 00273 return QSPI_ERROR; 00274 } 00275 00276 /* Update the address and size variables for next page programming */ 00277 current_addr += current_size; 00278 pData += current_size; 00279 current_size = ((current_addr + MT25TL01G_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MT25TL01G_PAGE_SIZE; 00280 } while (current_addr < end_addr); 00281 00282 return QSPI_OK; 00283 } 00284 00285 /** 00286 * @brief Erases the specified block of the QSPI memory. 00287 * @param BlockAddress: Block address to erase 00288 * @retval QSPI memory status 00289 */ 00290 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) 00291 { 00292 QSPI_CommandTypeDef s_command; 00293 00294 /* Initialize the erase command */ 00295 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00296 s_command.Instruction = SUBSECTOR_ERASE_4_BYTE_ADDR_CMD; 00297 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00298 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00299 s_command.Address = BlockAddress; 00300 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00301 s_command.DataMode = QSPI_DATA_NONE; 00302 s_command.DummyCycles = 0; 00303 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00304 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00305 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00306 00307 /* Enable write operations */ 00308 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00309 { 00310 return QSPI_ERROR; 00311 } 00312 00313 /* Send the command */ 00314 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00315 { 00316 return QSPI_ERROR; 00317 } 00318 00319 /* Configure automatic polling mode to wait for end of erase */ 00320 if (QSPI_AutoPollingMemReady(&QSPIHandle, MT25TL01G_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK) 00321 { 00322 return QSPI_ERROR; 00323 } 00324 00325 return QSPI_OK; 00326 } 00327 00328 /** 00329 * @brief Erases the entire QSPI memory. 00330 * @retval QSPI memory status 00331 */ 00332 uint8_t BSP_QSPI_Erase_Chip(void) 00333 { 00334 QSPI_CommandTypeDef s_command; 00335 00336 /* Initialize the erase command */ 00337 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00338 s_command.Instruction = DIE_ERASE_CMD; 00339 s_command.AddressMode = QSPI_ADDRESS_NONE; 00340 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00341 s_command.DataMode = QSPI_DATA_NONE; 00342 s_command.DummyCycles = 0; 00343 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00344 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00345 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00346 00347 /* Enable write operations */ 00348 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00349 { 00350 return QSPI_ERROR; 00351 } 00352 00353 /* Send the command */ 00354 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00355 { 00356 return QSPI_ERROR; 00357 } 00358 00359 /* Configure automatic polling mode to wait for end of erase */ 00360 if (QSPI_AutoPollingMemReady(&QSPIHandle, MT25TL01G_DIE_ERASE_MAX_TIME) != QSPI_OK) 00361 { 00362 return QSPI_ERROR; 00363 } 00364 00365 return QSPI_OK; 00366 } 00367 00368 /** 00369 * @brief Reads current status of the QSPI memory. 00370 * @retval QSPI memory status 00371 */ 00372 uint8_t BSP_QSPI_GetStatus(void) 00373 { 00374 QSPI_CommandTypeDef s_command; 00375 uint16_t reg; 00376 00377 /* Initialize the read flag status register command */ 00378 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00379 s_command.Instruction = READ_FLAG_STATUS_REG_CMD; 00380 s_command.AddressMode = QSPI_ADDRESS_NONE; 00381 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00382 s_command.DataMode = QSPI_DATA_4_LINES; 00383 s_command.DummyCycles = 0; 00384 s_command.NbData = 1; 00385 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00386 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00387 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00388 00389 /* Configure the command */ 00390 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00391 { 00392 return QSPI_ERROR; 00393 } 00394 00395 /* Reception of the data */ 00396 if (HAL_QSPI_Receive(&QSPIHandle, (uint8_t*)(®), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00397 { 00398 return QSPI_ERROR; 00399 } 00400 00401 /* Check the value of the register */ 00402 if ((reg & (MT25TL01G_FSR_PRERR | MT25TL01G_FSR_PGERR | MT25TL01G_FSR_ERERR)) != 0) 00403 { 00404 return QSPI_ERROR; 00405 } 00406 else if ((reg & (MT25TL01G_FSR_PGSUS | MT25TL01G_FSR_ERSUS)) != 0) 00407 { 00408 return QSPI_SUSPENDED; 00409 } 00410 else if ((reg & MT25TL01G_FSR_READY) != 0) 00411 { 00412 return QSPI_OK; 00413 } 00414 else 00415 { 00416 return QSPI_BUSY; 00417 } 00418 } 00419 00420 /** 00421 * @brief Return the configuration of the QSPI memory. 00422 * @param pInfo: pointer on the configuration structure 00423 * @retval QSPI memory status 00424 */ 00425 uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo) 00426 { 00427 /* Configure the structure with the memory configuration */ 00428 pInfo->FlashSize = MT25TL01G_FLASH_SIZE; 00429 pInfo->EraseSectorSize = (2 * MT25TL01G_SUBSECTOR_SIZE); 00430 pInfo->ProgPageSize = MT25TL01G_PAGE_SIZE; 00431 pInfo->EraseSectorsNumber = (MT25TL01G_FLASH_SIZE/pInfo->EraseSectorSize); 00432 pInfo->ProgPagesNumber = (MT25TL01G_FLASH_SIZE/pInfo->ProgPageSize); 00433 00434 return QSPI_OK; 00435 } 00436 00437 /** 00438 * @brief Configure the QSPI in memory-mapped mode 00439 * @retval QSPI memory status 00440 */ 00441 uint8_t BSP_QSPI_EnableMemoryMappedMode(void) 00442 { 00443 QSPI_CommandTypeDef s_command; 00444 QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; 00445 00446 /* Configure the command for the read instruction */ 00447 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00448 s_command.Instruction = QUAD_INOUT_FAST_READ_DTR_CMD; /* DTR QUAD INPUT/OUTPUT FAST READ and 4-BYTE DTR FAST READ commands */ 00449 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00450 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00451 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00452 s_command.DataMode = QSPI_DATA_4_LINES; 00453 s_command.DummyCycles = MT25TL01G_DUMMY_CYCLES_READ_QUAD_DTR - 1; 00454 00455 s_command.DdrMode = QSPI_DDR_MODE_ENABLE; 00456 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_HALF_CLK_DELAY; 00457 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00458 00459 /* Configure the memory mapped mode */ 00460 s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; 00461 s_mem_mapped_cfg.TimeOutPeriod = 0; 00462 00463 if (HAL_QSPI_MemoryMapped(&QSPIHandle, &s_command, &s_mem_mapped_cfg) != HAL_OK) 00464 { 00465 return QSPI_ERROR; 00466 } 00467 00468 return QSPI_OK; 00469 } 00470 00471 /** 00472 * @brief QSPI MSP Initialization 00473 * This function configures the hardware resources used in this example: 00474 * - Peripheral's clock enable 00475 * - Peripheral's GPIO Configuration 00476 * - NVIC configuration for QSPI interrupt 00477 * @retval None 00478 */ 00479 __weak void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params) 00480 { 00481 GPIO_InitTypeDef gpio_init_structure; 00482 00483 /*##-1- Enable peripherals and GPIO Clocks #################################*/ 00484 /* Enable the QuadSPI memory interface clock */ 00485 QSPI_CLK_ENABLE(); 00486 /* Reset the QuadSPI memory interface */ 00487 QSPI_FORCE_RESET(); 00488 QSPI_RELEASE_RESET(); 00489 /* Enable GPIO clocks */ 00490 QSPI_CLK_GPIO_CLK_ENABLE(); 00491 QSPI_BK1_CS_GPIO_CLK_ENABLE(); 00492 QSPI_BK1_D0_GPIO_CLK_ENABLE(); 00493 QSPI_BK1_D1_GPIO_CLK_ENABLE(); 00494 QSPI_BK1_D2_GPIO_CLK_ENABLE(); 00495 QSPI_BK1_D3_GPIO_CLK_ENABLE(); 00496 00497 QSPI_BK2_CS_GPIO_CLK_ENABLE(); 00498 QSPI_BK2_D0_GPIO_CLK_ENABLE(); 00499 QSPI_BK2_D1_GPIO_CLK_ENABLE(); 00500 QSPI_BK2_D2_GPIO_CLK_ENABLE(); 00501 QSPI_BK2_D3_GPIO_CLK_ENABLE(); 00502 00503 /*##-2- Configure peripheral GPIO ##########################################*/ 00504 /* QSPI CLK GPIO pin configuration */ 00505 gpio_init_structure.Pin = QSPI_CLK_PIN; 00506 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00507 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00508 gpio_init_structure.Pull = GPIO_NOPULL; 00509 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00510 HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure); 00511 00512 /* QSPI CS GPIO pin configuration */ 00513 gpio_init_structure.Pin = QSPI_BK1_CS_PIN; 00514 gpio_init_structure.Pull = GPIO_PULLUP; 00515 gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; 00516 HAL_GPIO_Init(QSPI_BK1_CS_GPIO_PORT, &gpio_init_structure); 00517 00518 /* QSPI D0 GPIO pin configuration */ 00519 gpio_init_structure.Pin = QSPI_BK1_D0_PIN; 00520 gpio_init_structure.Pull = GPIO_NOPULL; 00521 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00522 HAL_GPIO_Init(QSPI_BK1_D0_GPIO_PORT, &gpio_init_structure); 00523 00524 gpio_init_structure.Pin = QSPI_BK2_D0_PIN; 00525 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00526 HAL_GPIO_Init(QSPI_BK2_D0_GPIO_PORT, &gpio_init_structure); 00527 00528 /* QSPI D1 GPIO pin configuration */ 00529 gpio_init_structure.Pin = QSPI_BK1_D1_PIN; 00530 gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; 00531 HAL_GPIO_Init(QSPI_BK1_D1_GPIO_PORT, &gpio_init_structure); 00532 00533 gpio_init_structure.Pin = QSPI_BK2_D1_PIN; 00534 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00535 HAL_GPIO_Init(QSPI_BK2_D1_GPIO_PORT, &gpio_init_structure); 00536 00537 /* QSPI D2 GPIO pin configuration */ 00538 gpio_init_structure.Pin = QSPI_BK1_D2_PIN; 00539 gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; 00540 HAL_GPIO_Init(QSPI_BK1_D2_GPIO_PORT, &gpio_init_structure); 00541 00542 gpio_init_structure.Pin = QSPI_BK2_D2_PIN; 00543 HAL_GPIO_Init(QSPI_BK2_D2_GPIO_PORT, &gpio_init_structure); 00544 00545 /* QSPI D3 GPIO pin configuration */ 00546 gpio_init_structure.Pin = QSPI_BK1_D3_PIN; 00547 HAL_GPIO_Init(QSPI_BK1_D3_GPIO_PORT, &gpio_init_structure); 00548 00549 gpio_init_structure.Pin = QSPI_BK2_D3_PIN; 00550 HAL_GPIO_Init(QSPI_BK2_D3_GPIO_PORT, &gpio_init_structure); 00551 00552 /*##-3- Configure the NVIC for QSPI #########################################*/ 00553 /* NVIC configuration for QSPI interrupt */ 00554 HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0); 00555 HAL_NVIC_EnableIRQ(QUADSPI_IRQn); 00556 00557 } 00558 00559 /** 00560 * @brief QSPI MSP De-Initialization 00561 * This function frees the hardware resources used in this example: 00562 * - Disable the Peripheral's clock 00563 * - Revert GPIO and NVIC configuration to their default state 00564 * @retval None 00565 */ 00566 __weak void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params) 00567 { 00568 /*##-1- Disable the NVIC for QSPI ###########################################*/ 00569 HAL_NVIC_DisableIRQ(QUADSPI_IRQn); 00570 00571 /*##-2- Disable peripherals and GPIO Clocks ################################*/ 00572 /* De-Configure QSPI pins */ 00573 HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN); 00574 HAL_GPIO_DeInit(QSPI_BK1_CS_GPIO_PORT, QSPI_BK1_CS_PIN); 00575 HAL_GPIO_DeInit(QSPI_BK1_D0_GPIO_PORT, QSPI_BK1_D0_PIN); 00576 HAL_GPIO_DeInit(QSPI_BK1_D1_GPIO_PORT, QSPI_BK1_D1_PIN); 00577 HAL_GPIO_DeInit(QSPI_BK1_D2_GPIO_PORT, QSPI_BK1_D2_PIN); 00578 HAL_GPIO_DeInit(QSPI_BK1_D3_GPIO_PORT, QSPI_BK1_D3_PIN); 00579 00580 HAL_GPIO_DeInit(QSPI_BK2_CS_GPIO_PORT, QSPI_BK2_CS_PIN); 00581 HAL_GPIO_DeInit(QSPI_BK2_D0_GPIO_PORT, QSPI_BK2_D0_PIN); 00582 HAL_GPIO_DeInit(QSPI_BK2_D1_GPIO_PORT, QSPI_BK2_D1_PIN); 00583 HAL_GPIO_DeInit(QSPI_BK2_D2_GPIO_PORT, QSPI_BK2_D2_PIN); 00584 HAL_GPIO_DeInit(QSPI_BK2_D3_GPIO_PORT, QSPI_BK2_D3_PIN); 00585 00586 /*##-3- Reset peripherals ##################################################*/ 00587 /* Reset the QuadSPI memory interface */ 00588 QSPI_FORCE_RESET(); 00589 QSPI_RELEASE_RESET(); 00590 00591 /* Disable the QuadSPI memory interface clock */ 00592 QSPI_CLK_DISABLE(); 00593 } 00594 00595 /** 00596 * @} 00597 */ 00598 00599 /** @defgroup STM32H747I_DISCOVERY_QSPI_Private_Functions Private Functions 00600 * @{ 00601 */ 00602 00603 /** 00604 * @brief This function reset the QSPI memory. 00605 * @param hqspi: QSPI handle 00606 * @retval None 00607 */ 00608 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00609 { 00610 QSPI_CommandTypeDef s_command; 00611 00612 /* Initialize the reset enable command */ 00613 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00614 s_command.Instruction = RESET_ENABLE_CMD; 00615 s_command.AddressMode = QSPI_ADDRESS_NONE; 00616 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00617 s_command.DataMode = QSPI_DATA_NONE; 00618 s_command.DummyCycles = 0; 00619 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00620 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00621 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00622 00623 /* Send the command */ 00624 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00625 { 00626 return QSPI_ERROR; 00627 } 00628 00629 /* Send the reset memory command */ 00630 s_command.Instruction = RESET_MEMORY_CMD; 00631 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00632 { 00633 return QSPI_ERROR; 00634 } 00635 00636 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00637 s_command.Instruction = RESET_ENABLE_CMD; 00638 /* Send the command */ 00639 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00640 { 00641 return QSPI_ERROR; 00642 } 00643 00644 /* Send the reset memory command */ 00645 s_command.Instruction = RESET_MEMORY_CMD; 00646 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00647 { 00648 return QSPI_ERROR; 00649 } 00650 00651 /* Enter QSPI memory in QPI mode */ 00652 if(QSPI_EnterQPI(&QSPIHandle) != QSPI_OK) 00653 { 00654 return QSPI_ERROR; 00655 } 00656 00657 /* Configure automatic polling mode to wait the memory is ready */ 00658 if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00659 { 00660 return QSPI_ERROR; 00661 } 00662 00663 return QSPI_OK; 00664 } 00665 00666 /** 00667 * @brief This function set the QSPI memory in 4-byte address mode 00668 * @param hqspi: QSPI handle 00669 * @retval None 00670 */ 00671 static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi) 00672 { 00673 QSPI_CommandTypeDef s_command; 00674 00675 /* Initialize the command */ 00676 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00677 s_command.Instruction = ENTER_4_BYTE_ADDR_MODE_CMD; 00678 s_command.AddressMode = QSPI_ADDRESS_NONE; 00679 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00680 s_command.DataMode = QSPI_DATA_NONE; 00681 s_command.DummyCycles = 0; 00682 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00683 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00684 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00685 00686 /* Enable write operations */ 00687 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00688 { 00689 return QSPI_ERROR; 00690 } 00691 00692 /* Send the command */ 00693 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00694 { 00695 return QSPI_ERROR; 00696 } 00697 00698 /* Configure automatic polling mode to wait the memory is ready */ 00699 if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00700 { 00701 return QSPI_ERROR; 00702 } 00703 00704 return QSPI_OK; 00705 } 00706 00707 /** 00708 * @brief This function configure the dummy cycles on memory side. 00709 * @param hqspi: QSPI handle 00710 * @retval None 00711 */ 00712 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00713 { 00714 QSPI_CommandTypeDef s_command; 00715 uint16_t reg = 0; 00716 00717 /* Initialize the read volatile configuration register command */ 00718 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00719 s_command.Instruction = READ_VOL_CFG_REG_CMD; 00720 s_command.AddressMode = QSPI_ADDRESS_NONE; 00721 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00722 s_command.DataMode = QSPI_DATA_4_LINES; 00723 s_command.DummyCycles = 0; 00724 s_command.NbData = 2; 00725 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00726 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00727 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00728 00729 /* Configure the command */ 00730 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00731 { 00732 return QSPI_ERROR; 00733 } 00734 00735 /* Reception of the data */ 00736 if (HAL_QSPI_Receive(hqspi, (uint8_t *)(®), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00737 { 00738 return QSPI_ERROR; 00739 } 00740 00741 /* Enable write operations */ 00742 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00743 { 00744 return QSPI_ERROR; 00745 } 00746 00747 /* Update volatile configuration register (with new dummy cycles) */ 00748 s_command.Instruction = WRITE_VOL_CFG_REG_CMD; 00749 MODIFY_REG(reg, 0xF0F0, ((MT25TL01G_DUMMY_CYCLES_READ_QUAD << 4) | 00750 (MT25TL01G_DUMMY_CYCLES_READ_QUAD << 12))); 00751 00752 /* Configure the write volatile configuration register command */ 00753 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00754 { 00755 return QSPI_ERROR; 00756 } 00757 00758 /* Transmission of the data */ 00759 if (HAL_QSPI_Transmit(hqspi, (uint8_t *)(®), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00760 { 00761 return QSPI_ERROR; 00762 } 00763 00764 return QSPI_OK; 00765 } 00766 00767 /** 00768 * @brief This function send a Write Enable and wait it is effective. 00769 * @param hqspi: QSPI handle 00770 * @retval None 00771 */ 00772 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 00773 { 00774 QSPI_CommandTypeDef s_command; 00775 QSPI_AutoPollingTypeDef s_config; 00776 00777 /* Enable write operations */ 00778 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00779 s_command.Instruction = WRITE_ENABLE_CMD; 00780 s_command.AddressMode = QSPI_ADDRESS_NONE; 00781 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00782 s_command.DataMode = QSPI_DATA_NONE; 00783 s_command.DummyCycles = 0; 00784 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00785 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00786 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00787 00788 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00789 { 00790 return QSPI_ERROR; 00791 } 00792 00793 /* Configure automatic polling mode to wait for write enabling */ 00794 s_config.Match = MT25TL01G_SR_WREN | (MT25TL01G_SR_WREN << 8); 00795 s_config.Mask = MT25TL01G_SR_WREN | (MT25TL01G_SR_WREN << 8); 00796 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00797 s_config.StatusBytesSize = 2; 00798 s_config.Interval = 0x10; 00799 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00800 00801 s_command.Instruction = READ_STATUS_REG_CMD; 00802 s_command.DataMode = QSPI_DATA_4_LINES; 00803 00804 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00805 { 00806 return QSPI_ERROR; 00807 } 00808 00809 return QSPI_OK; 00810 } 00811 00812 /** 00813 * @brief This function read the SR of the memory and wait the EOP. 00814 * @param hqspi: QSPI handle 00815 * @param Timeout: timeout in ms 00816 * @retval None 00817 */ 00818 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 00819 { 00820 QSPI_CommandTypeDef s_command; 00821 QSPI_AutoPollingTypeDef s_config; 00822 00823 /* Configure automatic polling mode to wait for memory ready */ 00824 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00825 s_command.Instruction = READ_STATUS_REG_CMD; 00826 s_command.AddressMode = QSPI_ADDRESS_NONE; 00827 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00828 s_command.DataMode = QSPI_DATA_4_LINES; 00829 s_command.DummyCycles = 2; 00830 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00831 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00832 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00833 00834 s_config.Match = 0; 00835 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00836 s_config.Interval = 0x10; 00837 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00838 s_config.Mask = MT25TL01G_SR_WIP | (MT25TL01G_SR_WIP <<8); 00839 s_config.StatusBytesSize = 2; 00840 00841 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK) 00842 { 00843 return QSPI_ERROR; 00844 } 00845 00846 return QSPI_OK; 00847 } 00848 00849 /** 00850 * @brief This function enter the QPSI memory in QPI mode 00851 * @param hqspi QSPI handle 00852 * @retval QSPI status 00853 */ 00854 static uint8_t QSPI_EnterQPI(QSPI_HandleTypeDef *hqspi) 00855 { 00856 QSPI_CommandTypeDef s_command; 00857 00858 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00859 s_command.Instruction = ENTER_QUAD_CMD; 00860 s_command.AddressMode = QSPI_ADDRESS_NONE; 00861 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00862 s_command.DataMode = QSPI_DATA_NONE; 00863 s_command.DummyCycles = 0; 00864 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00865 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00866 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00867 00868 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00869 { 00870 return QSPI_ERROR; 00871 } 00872 00873 return QSPI_OK; 00874 } 00875 00876 /** 00877 * @} 00878 */ 00879 00880 /** 00881 * @} 00882 */ 00883 00884 /** 00885 * @} 00886 */ 00887 00888 /** 00889 * @} 00890 */ 00891 00892 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 00893
Generated on Tue Jul 12 2022 18:45:41 by 1.7.2