BSP files for STM32H747I-Discovery Copy from ST Cube delivery

Dependents:   DISCO_H747I_LCD_demo DISCO_H747I_AUDIO_demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32h747i_discovery_qspi.c Source File

stm32h747i_discovery_qspi.c

Go to the documentation of this file.
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>&copy; 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*)(&reg), 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 *)(&reg), 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 *)(&reg), 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