BSP library for DISCO-STM32F746NG board. Added support for on-board QSPI Flash memory MICRO N25Q128A. Ported from library BSP_DISCO_L476VG.

Dependents:   DISCO-F746NG_QSPI

Fork of BSP_DISCO_F746NG by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32746g_discovery_qspi.c Source File

stm32746g_discovery_qspi.c

00001 /**
00002   ******************************************************************************
00003   * @file    stm32f746g_discovery_qspi.c
00004   * @author  Florian SAVARD
00005   * @version V1.0.0
00006   * @date    15-november-2015
00007   * @brief   This file includes a standard driver for the N25Q128A QSPI 
00008   *          memory mounted on STM32F746G-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 STM32F746G-DISCO evaluation 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) 2015 STMicroelectronics</center></h2>
00041   *
00042   * Redistribution and use in source and binary forms, with or without modification,
00043   * are permitted provided that the following conditions are met:
00044   *   1. Redistributions of source code must retain the above copyright notice,
00045   *      this list of conditions and the following disclaimer.
00046   *   2. Redistributions in binary form must reproduce the above copyright notice,
00047   *      this list of conditions and the following disclaimer in the documentation
00048   *      and/or other materials provided with the distribution.
00049   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00050   *      may be used to endorse or promote products derived from this software
00051   *      without specific prior written permission.
00052   *
00053   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00054   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00055   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00056   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00057   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00058   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00059   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00060   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00061   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00062   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00063   *
00064   ******************************************************************************
00065   */
00066 
00067 /* Includes ------------------------------------------------------------------*/
00068 #include "stm32746g_discovery_qspi.h"
00069 
00070 /** @addtogroup BSP
00071   * @{
00072   */
00073 
00074 /** @addtogroup STM32F746G_DISCOVERY
00075   * @{
00076   */
00077 
00078 /** @defgroup STM32F746G_DISCOVERY_QSPI STM32F746G-DISCOVERY QSPI
00079   * @{
00080   */
00081 
00082 /* Private variables ---------------------------------------------------------*/
00083 
00084 /** @defgroup STM32F746G_DISCOVERY_QSPI_Private_Variables Private Variables
00085   * @{
00086   */
00087 QSPI_HandleTypeDef QSPIHandle;
00088 
00089 /**
00090   * @}
00091   */
00092 
00093 
00094 /* Private functions ---------------------------------------------------------*/
00095 
00096 /** @defgroup STM32F746G_DISCOVERY_QSPI_Private_Functions Private Functions
00097   * @{
00098   */
00099 static void    QSPI_MspInit            (void);
00100 static void    QSPI_MspDeInit          (void);
00101 static uint8_t QSPI_ResetMemory        (QSPI_HandleTypeDef *hqspi);
00102 static uint8_t QSPI_DummyCyclesCfg     (QSPI_HandleTypeDef *hqspi);
00103 static uint8_t QSPI_WriteEnable        (QSPI_HandleTypeDef *hqspi);
00104 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout);
00105 
00106 /**
00107   * @}
00108   */
00109 
00110 /* Exported functions ---------------------------------------------------------*/
00111 
00112 /** @addtogroup STM32F746G_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; // Defines the base address of the register structure of the QSPI peripheral
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   QSPI_MspInit();
00132   
00133   /* QSPI initialization */
00134   QSPIHandle.Init.ClockPrescaler     = 3; /* Clock = Fahb = ? MHz */
00135   QSPIHandle.Init.FifoThreshold      = 4;
00136   QSPIHandle.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_NONE;
00137   QSPIHandle.Init.FlashSize          = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1;
00138   QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
00139   QSPIHandle.Init.ClockMode          = QSPI_CLOCK_MODE_0;
00140 
00141   if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK)
00142   {
00143     return QSPI_ERROR;
00144   }
00145 
00146   /* QSPI memory reset */
00147   if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK)
00148   {
00149     return QSPI_NOT_SUPPORTED;
00150   }
00151  
00152   /* Configuration of the dummy cucles on QSPI memory side */
00153   if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK)
00154   {
00155     return QSPI_NOT_SUPPORTED;
00156   }
00157   
00158   return QSPI_OK;
00159 }
00160 
00161 /**
00162   * @brief  De-Initializes the QSPI interface.
00163   * @retval QSPI memory status
00164   */
00165 uint8_t BSP_QSPI_DeInit(void)
00166 { 
00167   QSPIHandle.Instance = QUADSPI;
00168   
00169   /* Call the DeInit function to reset the driver */
00170   if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
00171   {
00172     return QSPI_ERROR;
00173   }
00174 
00175   /* System level De-initialization */
00176   QSPI_MspDeInit();
00177 
00178     return QSPI_OK;
00179 }
00180 
00181 /**
00182   * @brief  Reads an amount of data from the QSPI memory.
00183   * @param  pData: Pointer to data to be read
00184   * @param  ReadAddr: Read start address
00185   * @param  Size: Size of data to read    
00186   * @retval QSPI memory status
00187   */
00188 uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
00189 {
00190   QSPI_CommandTypeDef sCommand;
00191 
00192   /* Initialize the read command */
00193   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00194   sCommand.Instruction       = QUAD_INOUT_FAST_READ_CMD;
00195   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00196   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00197   sCommand.Address           = ReadAddr;
00198   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00199   sCommand.DataMode          = QSPI_DATA_4_LINES;
00200   sCommand.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
00201   sCommand.NbData            = Size;
00202   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00203   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00204   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00205   
00206   /* Configure the command */
00207   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00208   {
00209     return QSPI_ERROR;
00210   }
00211   
00212   /* Reception of the data */
00213   if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00214   {
00215     return QSPI_ERROR;
00216   }
00217 
00218   return QSPI_OK;
00219 }
00220 
00221 /**
00222   * @brief  Writes an amount of data to the QSPI memory.
00223   * @param  pData: Pointer to data to be written
00224   * @param  WriteAddr: Write start address
00225   * @param  Size: Size of data to write    
00226   * @retval QSPI memory status
00227   */
00228 uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
00229 {
00230   QSPI_CommandTypeDef sCommand;
00231   uint32_t end_addr, current_size, current_addr;
00232 
00233   /* Calculation of the size between the write address and the end of the page */
00234   current_addr = 0;
00235 
00236   while (current_addr <= WriteAddr)
00237   {
00238     current_addr += N25Q128A_PAGE_SIZE;
00239   }
00240   current_size = current_addr - WriteAddr;
00241 
00242   /* Check if the size of the data is less than the remaining place in the page */
00243   if (current_size > Size)
00244   {
00245     current_size = Size;
00246   }
00247 
00248   /* Initialize the adress variables */
00249   current_addr = WriteAddr;
00250   end_addr = WriteAddr + Size;
00251 
00252   /* Initialize the program command */
00253   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00254   sCommand.Instruction       = EXT_QUAD_IN_FAST_PROG_CMD;
00255   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00256   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00257   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00258   sCommand.DataMode          = QSPI_DATA_4_LINES;
00259   sCommand.DummyCycles       = 0;
00260   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00261   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00262   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00263   
00264   /* Perform the write page by page */
00265   do
00266   {
00267     sCommand.Address = current_addr;
00268     sCommand.NbData  = current_size;
00269 
00270     /* Enable write operations */
00271     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00272     {
00273       return QSPI_ERROR;
00274     }
00275     
00276     /* Configure the command */
00277     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00278     {
00279       return QSPI_ERROR;
00280     }
00281     
00282     /* Transmission of the data */
00283     if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00284     {
00285       return QSPI_ERROR;
00286     }
00287     
00288     /* Configure automatic polling mode to wait for end of program */  
00289     if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
00290     {
00291       return QSPI_ERROR;
00292     }
00293     
00294     /* Update the address and size variables for next page programming */
00295     current_addr += current_size;
00296     pData += current_size;
00297     current_size = ((current_addr + N25Q128A_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : N25Q128A_PAGE_SIZE;
00298   } while (current_addr < end_addr);
00299   
00300   return QSPI_OK;
00301 }
00302 
00303 /**
00304   * @brief  Erases the specified block of the QSPI memory. 
00305   * @param  BlockAddress: Block address to erase  
00306   * @retval QSPI memory status
00307   */
00308 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress)
00309 {
00310   QSPI_CommandTypeDef sCommand;
00311 
00312   /* Initialize the erase command */
00313   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00314   sCommand.Instruction       = SUBSECTOR_ERASE_CMD;
00315   sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
00316   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00317   sCommand.Address           = BlockAddress;
00318   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00319   sCommand.DataMode          = QSPI_DATA_NONE;
00320   sCommand.DummyCycles       = 0;
00321   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00322   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00323   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00324 
00325   /* Enable write operations */
00326   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00327   {
00328     return QSPI_ERROR;
00329   }
00330 
00331   /* Send the command */
00332   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00333   {
00334     return QSPI_ERROR;
00335   }
00336   
00337   /* Configure automatic polling mode to wait for end of erase */  
00338   if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK)
00339   {
00340     return QSPI_ERROR;
00341   }
00342 
00343   return QSPI_OK;
00344 }
00345 
00346 /**
00347   * @brief  Erases the specified sector of the QSPI memory. 
00348   * @param  Sector: Sector address to erase (0 to 255) 
00349   * @retval QSPI memory status
00350   * @note This function is non blocking meaning that sector erase
00351   *       operation is started but not completed when the function 
00352   *       returns. Application has to call BSP_QSPI_GetStatus()
00353   *       to know when the device is available again (i.e. erase operation
00354   *       completed).
00355   */
00356 uint8_t BSP_QSPI_Erase_Sector(uint32_t Sector)
00357 {
00358   QSPI_CommandTypeDef sCommand;
00359   
00360   if (Sector >= (uint32_t)(N25Q128A_FLASH_SIZE/N25Q128A_SECTOR_SIZE))
00361   {
00362     return QSPI_ERROR;
00363   }
00364   
00365   /* Initialize the erase command */
00366   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00367   sCommand.Instruction       = SECTOR_ERASE_CMD;
00368   sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
00369   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00370   sCommand.Address           = (Sector * N25Q128A_SECTOR_SIZE);
00371   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00372   sCommand.DataMode          = QSPI_DATA_NONE;
00373   sCommand.DummyCycles       = 0;
00374   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00375   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00376   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00377   
00378   /* Enable write operations */
00379   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00380   {
00381     return QSPI_ERROR;
00382   }
00383   
00384   /* Send the command */
00385   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00386   {
00387     return QSPI_ERROR;
00388   }
00389   
00390   return QSPI_OK;
00391 }
00392 
00393 /**
00394   * @brief  Erases the entire QSPI memory.
00395   * @retval QSPI memory status
00396   */
00397 uint8_t BSP_QSPI_Erase_Chip(void)
00398 {
00399   QSPI_CommandTypeDef sCommand;
00400 
00401   /* Initialize the erase command */
00402   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00403   sCommand.Instruction       = BULK_ERASE_CMD;
00404   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00405   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00406   sCommand.DataMode          = QSPI_DATA_NONE;
00407   sCommand.DummyCycles       = 0;
00408   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00409   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00410   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00411 
00412   /* Enable write operations */
00413   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00414   {
00415     return QSPI_ERROR;
00416   }
00417 
00418   /* Send the command */
00419   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00420   {
00421     return QSPI_ERROR;
00422   }
00423   
00424   /* Configure automatic polling mode to wait for end of erase */  
00425   if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK)
00426   {
00427     return QSPI_ERROR;
00428   }
00429 
00430   return QSPI_OK;
00431 }
00432 
00433 /**
00434   * @brief  Reads current status of the QSPI memory.
00435   * @retval QSPI memory status
00436   */
00437 uint8_t BSP_QSPI_GetStatus(void)
00438 {
00439   QSPI_CommandTypeDef sCommand;
00440   uint8_t reg;
00441 
00442   /* Initialize the read flag status register command */
00443   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00444   sCommand.Instruction       = READ_FLAG_STATUS_REG_CMD;
00445   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00446   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00447   sCommand.DataMode          = QSPI_DATA_1_LINE;
00448   sCommand.DummyCycles       = 0;
00449   sCommand.NbData            = 1;
00450   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00451   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00452   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00453 
00454   /* Configure the command */
00455   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00456   {
00457     return QSPI_ERROR;
00458   }
00459 
00460   /* Reception of the data */
00461   if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00462   {
00463     return QSPI_ERROR;
00464   }
00465   
00466   /* Check the value of the register */
00467   if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0)
00468   {
00469     return QSPI_ERROR;
00470   }
00471   else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0)
00472   {
00473     return QSPI_SUSPENDED;
00474   }
00475   else if ((reg & N25Q128A_FSR_READY) != 0)
00476   {
00477     return QSPI_OK;
00478   }
00479   else
00480   {
00481     return QSPI_BUSY;
00482   }
00483 }
00484 
00485 /**
00486   * @brief  Return the configuration of the QSPI memory.
00487   * @param  pInfo: pointer on the configuration structure  
00488   * @retval QSPI memory status
00489   */
00490 uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo)
00491 {
00492   /* Configure the structure with the memory configuration */
00493   pInfo->FlashSize          = N25Q128A_FLASH_SIZE;
00494   pInfo->EraseSectorSize    = N25Q128A_SUBSECTOR_SIZE;
00495   pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE/N25Q128A_SUBSECTOR_SIZE);
00496   pInfo->ProgPageSize       = N25Q128A_PAGE_SIZE;
00497   pInfo->ProgPagesNumber    = (N25Q128A_FLASH_SIZE/N25Q128A_PAGE_SIZE);
00498   
00499   return QSPI_OK;
00500 }
00501 
00502 /**
00503   * @brief  Configure the QSPI in memory-mapped mode
00504   * @retval QSPI memory status
00505   */
00506 uint8_t BSP_QSPI_EnableMemoryMappedMode(void)
00507 {
00508   QSPI_CommandTypeDef      sCommand;
00509   QSPI_MemoryMappedTypeDef sMemMappedCfg;
00510 
00511   /* Configure the command for the read instruction */
00512   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00513   sCommand.Instruction       = QUAD_INOUT_FAST_READ_CMD;
00514   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00515   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00516   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00517   sCommand.DataMode          = QSPI_DATA_4_LINES;
00518   sCommand.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
00519   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00520   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00521   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00522   
00523   /* Configure the memory mapped mode */
00524   sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_ENABLE;
00525   sMemMappedCfg.TimeOutPeriod     = 4; /* 50 ns (4 periods of a 80 MHz clock) */
00526   
00527   if (HAL_QSPI_MemoryMapped(&QSPIHandle, &sCommand, &sMemMappedCfg) != HAL_OK)
00528   {
00529     return QSPI_ERROR;
00530   }
00531 
00532   return QSPI_OK;
00533 }
00534 
00535 /**
00536   * @brief  This function suspends an ongoing erase command.
00537   * @retval QSPI memory status
00538   */
00539 uint8_t BSP_QSPI_SuspendErase(void)
00540 {
00541   QSPI_CommandTypeDef sCommand;
00542   
00543   /* Check whether the device is busy (erase operation is 
00544   in progress).
00545   */
00546   if (BSP_QSPI_GetStatus() == QSPI_BUSY)
00547   {
00548     /* Initialize the erase command */
00549     sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00550     sCommand.Instruction       = PROG_ERASE_SUSPEND_CMD;
00551     sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00552     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00553     sCommand.DataMode          = QSPI_DATA_NONE;
00554     sCommand.DummyCycles       = 0;
00555     sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00556     sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00557     sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00558     
00559     /* Enable write operations */
00560     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00561     {
00562       return QSPI_ERROR;
00563     }
00564     
00565     /* Send the command */
00566     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00567     {
00568       return QSPI_ERROR;
00569     }
00570     
00571     if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED)
00572     {
00573       return QSPI_OK;
00574     }
00575     
00576     return QSPI_ERROR;
00577   }
00578   
00579   return QSPI_OK;
00580 }
00581 
00582 /**
00583   * @brief  This function resumes a paused erase command.
00584   * @retval QSPI memory status
00585   */
00586 uint8_t BSP_QSPI_ResumeErase(void)
00587 {
00588   QSPI_CommandTypeDef sCommand;
00589   
00590   /* Check whether the device is in suspended state */
00591   if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED)
00592   {
00593     /* Initialize the erase command */
00594     sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00595     sCommand.Instruction       = PROG_ERASE_RESUME_CMD;
00596     sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00597     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00598     sCommand.DataMode          = QSPI_DATA_NONE;
00599     sCommand.DummyCycles       = 0;
00600     sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00601     sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00602     sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00603     
00604     /* Enable write operations */
00605     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00606     {
00607       return QSPI_ERROR;
00608     }
00609     
00610     /* Send the command */
00611     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00612     {
00613       return QSPI_ERROR;
00614     }
00615     
00616     /*
00617     When this command is executed, the status register write in progress bit is set to 1, and
00618     the flag status register program erase controller bit is set to 0. This command is ignored
00619     if the device is not in a suspended state.
00620     */
00621     
00622     if (BSP_QSPI_GetStatus() == QSPI_BUSY)
00623     {
00624       return QSPI_OK;
00625     }
00626     
00627     return QSPI_ERROR;
00628   }
00629 
00630   return QSPI_OK;
00631 }
00632 
00633 /**
00634   * @}
00635   */
00636 
00637 /** @addtogroup STM32F746G_DISCOVERY_QSPI_Private_Functions 
00638   * @{
00639   */
00640 
00641 /**
00642   * @brief  Initializes the QSPI MSP.
00643   * @retval None
00644   */
00645 static void QSPI_MspInit(void)
00646 {
00647   GPIO_InitTypeDef GPIO_InitStruct;
00648 
00649   /* Enable the QuadSPI memory interface clock */
00650   __HAL_RCC_QSPI_CLK_ENABLE();
00651 
00652   /* Reset the QuadSPI memory interface */
00653   __HAL_RCC_QSPI_FORCE_RESET();
00654   __HAL_RCC_QSPI_RELEASE_RESET();
00655 
00656   /* Enable GPIO clocks */
00657   __HAL_RCC_GPIOE_CLK_ENABLE();
00658 
00659   /* QSPI CS GPIO pin configuration  */
00660   /* DISCO-STM32F746NG : CS = PB6 */
00661   GPIO_InitStruct.Pin       = GPIO_PIN_6;
00662   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
00663   GPIO_InitStruct.Pull      = GPIO_PULLUP;
00664   GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
00665   GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
00666   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00667 
00668   /* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration  */
00669   /* DISCO-STM32F746NG : CLK = PB2 | D0 = PD11 | D1 = PD12 | D2 = PE2 | D3 = PD13 */
00670   
00671   GPIO_InitStruct.Pin       = (GPIO_PIN_2); // CLK
00672   GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
00673   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00674   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00675   
00676   GPIO_InitStruct.Pin       = (GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13); // D0, D1, D3
00677   GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
00678   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00679   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
00680   
00681   GPIO_InitStruct.Pin       = (GPIO_PIN_2); // D2
00682   GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
00683   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00684   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00685 }
00686 
00687 /**
00688   * @brief  De-Initializes the QSPI MSP.
00689   * @retval None
00690   */
00691 static void QSPI_MspDeInit(void)
00692 {
00693   GPIO_InitTypeDef GPIO_InitStruct;
00694 
00695   /* QSPI CLK, CS, PE10 - PE15 GPIO pins de-configuration  */
00696 
00697    __HAL_RCC_GPIOE_CLK_ENABLE();
00698       HAL_GPIO_DeInit(GPIOD, (GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13)); // D0, D1, D3
00699       HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2); // D2
00700       
00701   /* Chip select pin de-configuration */
00702   /* Set GPIOE pin 11 in pull up mode (optimum default setting) */
00703   GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
00704   GPIO_InitStruct.Pin       = GPIO_PIN_6;
00705   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00706   GPIO_InitStruct.Speed     = GPIO_SPEED_LOW;
00707   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
00708   
00709   /* CLK pin de-configuration */
00710   /* Set GPIOE pin 10 in no pull, low state (optimum default setting) */
00711   GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP  ;
00712   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00713   GPIO_InitStruct.Pin       = (GPIO_PIN_2);
00714   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00715   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
00716    
00717   /* Reset the QuadSPI memory interface */
00718   __HAL_RCC_QSPI_FORCE_RESET();
00719   __HAL_RCC_QSPI_RELEASE_RESET();
00720 
00721   /* Disable the QuadSPI memory interface clock */
00722   __HAL_RCC_QSPI_CLK_DISABLE();
00723 }
00724 
00725 /**
00726   * @brief  This function reset the QSPI memory.
00727   * @param  hqspi: QSPI handle
00728   * @retval None
00729   */
00730 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi)
00731 {
00732   QSPI_CommandTypeDef sCommand;
00733 
00734   /* Initialize the reset enable command */
00735   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00736   sCommand.Instruction       = RESET_ENABLE_CMD;
00737   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00738   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00739   sCommand.DataMode          = QSPI_DATA_NONE;
00740   sCommand.DummyCycles       = 0;
00741   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00742   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00743   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00744 
00745   /* Send the command */
00746   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00747   {
00748     return QSPI_ERROR;
00749   }
00750 
00751   /* Send the reset memory command */
00752   sCommand.Instruction = RESET_MEMORY_CMD;
00753   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00754   {
00755     return QSPI_ERROR;
00756   }
00757 
00758   /* Configure automatic polling mode to wait the memory is ready */  
00759   if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
00760   {
00761     return QSPI_ERROR;
00762   }
00763 
00764   return QSPI_OK;
00765 }
00766 
00767 /**
00768   * @brief  This function configure the dummy cycles on memory side.
00769   * @param  hqspi: QSPI handle
00770   * @retval None
00771   */
00772 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
00773 {
00774   QSPI_CommandTypeDef sCommand;
00775   uint8_t reg;
00776 
00777   /* Initialize the read volatile configuration register command */
00778   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00779   sCommand.Instruction       = READ_VOL_CFG_REG_CMD;
00780   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00781   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00782   sCommand.DataMode          = QSPI_DATA_1_LINE;
00783   sCommand.DummyCycles       = 0;
00784   sCommand.NbData            = 1;
00785   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00786   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00787   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00788 
00789   /* Configure the command */
00790   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00791   {
00792     return QSPI_ERROR;
00793   }
00794 
00795   /* Reception of the data */
00796   if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00797   {
00798     return QSPI_ERROR;
00799   }
00800 
00801   /* Enable write operations */
00802   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00803   {
00804     return QSPI_ERROR;
00805   }
00806 
00807   /* Update volatile configuration register (with new dummy cycles) */  
00808   sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
00809   MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY)));
00810       
00811   /* Configure the write volatile configuration register command */
00812   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00813   {
00814     return QSPI_ERROR;
00815   }
00816 
00817   /* Transmission of the data */
00818   if (HAL_QSPI_Transmit(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00819   {
00820     return QSPI_ERROR;
00821   }
00822   
00823   return QSPI_OK;
00824 }
00825 
00826 /**
00827   * @brief  This function send a Write Enable and wait it is effective.
00828   * @param  hqspi: QSPI handle
00829   * @retval None
00830   */
00831 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi)
00832 {
00833   QSPI_CommandTypeDef     sCommand;
00834   QSPI_AutoPollingTypeDef sConfig;
00835 
00836   /* Enable write operations */
00837   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00838   sCommand.Instruction       = WRITE_ENABLE_CMD;
00839   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00840   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00841   sCommand.DataMode          = QSPI_DATA_NONE;
00842   sCommand.DummyCycles       = 0;
00843   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00844   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00845   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00846 
00847   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00848   {
00849     return QSPI_ERROR;
00850   }
00851   
00852   /* Configure automatic polling mode to wait for write enabling */  
00853   sConfig.Match           = N25Q128A_SR_WREN;
00854   sConfig.Mask            = N25Q128A_SR_WREN;
00855   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00856   sConfig.StatusBytesSize = 1;
00857   sConfig.Interval        = 0x10;
00858   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00859 
00860   sCommand.Instruction    = READ_STATUS_REG_CMD;
00861   sCommand.DataMode       = QSPI_DATA_1_LINE;
00862 
00863   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00864   {
00865     return QSPI_ERROR;
00866   }
00867 
00868   return QSPI_OK;
00869 }
00870 
00871 /**
00872   * @brief  This function read the SR of the memory and wait the EOP.
00873   * @param  hqspi: QSPI handle
00874   * @param  Timeout: Timeout for auto-polling
00875   * @retval None
00876   */
00877 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
00878 {
00879   QSPI_CommandTypeDef     sCommand;
00880   QSPI_AutoPollingTypeDef sConfig;
00881 
00882   /* Configure automatic polling mode to wait for memory ready */  
00883   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00884   sCommand.Instruction       = READ_STATUS_REG_CMD;
00885   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00886   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00887   sCommand.DataMode          = QSPI_DATA_1_LINE;
00888   sCommand.DummyCycles       = 0;
00889   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00890   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00891   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00892 
00893   sConfig.Match           = 0;
00894   sConfig.Mask            = N25Q128A_SR_WIP;
00895   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00896   sConfig.StatusBytesSize = 1;
00897   sConfig.Interval        = 0x10;
00898   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00899 
00900   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK)
00901   {
00902     return QSPI_ERROR;
00903   }
00904 
00905   return QSPI_OK;
00906 }
00907 
00908 /**
00909   * @}
00910   */
00911 
00912 /**
00913   * @}
00914   */
00915 
00916 /**
00917   * @}
00918   */
00919 
00920 /**
00921   * @}
00922   */
00923 
00924 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00925