Contains the BSP driver for the DISCO_F413ZH board.

Dependents:   DISCO_F413ZH-LCD-demo DISCO_F413ZH-touch-screen-demo DISCO_F413ZH-SD-demo DISCO_F413ZH-PSRAM-demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f413h_discovery_qspi.c Source File

stm32f413h_discovery_qspi.c

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