STM32469I-Discovery BSP User Manual: stm32469i_discovery_qspi.c Source File

STM32469I-Discovery BSP Drivers

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