STM32L476G-Discovery BSP User Manual: stm32l476g_discovery_qspi.c Source File

STM32L476G-Discovery BSP

stm32l476g_discovery_qspi.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l476g_discovery_qspi.c
00004   * @author  MCD Application Team
00005   * @version $VERSION$
00006   * @date    $DATE$
00007   * @brief   This file includes a standard driver for the N25Q128A QSPI 
00008   *          memory mounted on STM32L476G-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 STM32L476G-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 "stm32l476g_discovery_qspi.h"
00069 
00070 /** @addtogroup BSP
00071   * @{
00072   */
00073 
00074 /** @addtogroup STM32L476G_DISCOVERY
00075   * @{
00076   */
00077 
00078 /** @defgroup STM32L476G_DISCOVERY_QSPI STM32L476G-DISCOVERY QSPI
00079   * @{
00080   */
00081 
00082 /* Private variables ---------------------------------------------------------*/
00083 
00084 /** @defgroup STM32L476G_DISCOVERY_QSPI_Private_Variables Private Variables
00085   * @{
00086   */
00087 QSPI_HandleTypeDef QSPIHandle;
00088 
00089 /**
00090   * @}
00091   */
00092 
00093 
00094 /* Private functions ---------------------------------------------------------*/
00095 
00096 /** @defgroup STM32L476G_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 STM32L476G_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   QSPI_MspInit();
00132   
00133   /* QSPI initialization */
00134   QSPIHandle.Init.ClockPrescaler     = 0; /* Clock = Fahb = 80 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 STM32L476G_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   GPIO_InitStruct.Pin       = GPIO_PIN_11;
00661   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
00662   GPIO_InitStruct.Pull      = GPIO_PULLUP;
00663   GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
00664   GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
00665   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00666 
00667   /* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration  */
00668   GPIO_InitStruct.Pin       = (GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
00669   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00670   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00671 }
00672 
00673 /**
00674   * @brief  De-Initializes the QSPI MSP.
00675   * @retval None
00676   */
00677 static void QSPI_MspDeInit(void)
00678 {
00679   GPIO_InitTypeDef GPIO_InitStruct;
00680 
00681   /* QSPI CLK, CS, PE10 - PE15 GPIO pins de-configuration  */
00682 
00683    __HAL_RCC_GPIOE_CLK_ENABLE();
00684       HAL_GPIO_DeInit(GPIOE, (GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15));
00685   /* Set GPIOE pin 11 in pull up mode (optimum default setting) */
00686   GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
00687   GPIO_InitStruct.Pin       = GPIO_PIN_11;
00688   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00689   GPIO_InitStruct.Speed     = GPIO_SPEED_LOW;
00690   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 
00691   
00692   /* Set GPIOE pin 10 in no pull, low state (optimum default setting) */
00693   GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP  ;
00694   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00695   GPIO_InitStruct.Pin       = (GPIO_PIN_10);
00696   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00697   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10, GPIO_PIN_RESET);
00698    
00699   /* Reset the QuadSPI memory interface */
00700   __HAL_RCC_QSPI_FORCE_RESET();
00701   __HAL_RCC_QSPI_RELEASE_RESET();
00702 
00703   /* Disable the QuadSPI memory interface clock */
00704   __HAL_RCC_QSPI_CLK_DISABLE();
00705 }
00706 
00707 /**
00708   * @brief  This function reset the QSPI memory.
00709   * @param  hqspi: QSPI handle
00710   * @retval None
00711   */
00712 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi)
00713 {
00714   QSPI_CommandTypeDef sCommand;
00715 
00716   /* Initialize the reset enable command */
00717   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00718   sCommand.Instruction       = RESET_ENABLE_CMD;
00719   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00720   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00721   sCommand.DataMode          = QSPI_DATA_NONE;
00722   sCommand.DummyCycles       = 0;
00723   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00724   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00725   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00726 
00727   /* Send the command */
00728   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00729   {
00730     return QSPI_ERROR;
00731   }
00732 
00733   /* Send the reset memory command */
00734   sCommand.Instruction = RESET_MEMORY_CMD;
00735   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00736   {
00737     return QSPI_ERROR;
00738   }
00739 
00740   /* Configure automatic polling mode to wait the memory is ready */  
00741   if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
00742   {
00743     return QSPI_ERROR;
00744   }
00745 
00746   return QSPI_OK;
00747 }
00748 
00749 /**
00750   * @brief  This function configure the dummy cycles on memory side.
00751   * @param  hqspi: QSPI handle
00752   * @retval None
00753   */
00754 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
00755 {
00756   QSPI_CommandTypeDef sCommand;
00757   uint8_t reg;
00758 
00759   /* Initialize the read volatile configuration register command */
00760   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00761   sCommand.Instruction       = READ_VOL_CFG_REG_CMD;
00762   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00763   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00764   sCommand.DataMode          = QSPI_DATA_1_LINE;
00765   sCommand.DummyCycles       = 0;
00766   sCommand.NbData            = 1;
00767   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00768   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00769   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00770 
00771   /* Configure the command */
00772   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00773   {
00774     return QSPI_ERROR;
00775   }
00776 
00777   /* Reception of the data */
00778   if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00779   {
00780     return QSPI_ERROR;
00781   }
00782 
00783   /* Enable write operations */
00784   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00785   {
00786     return QSPI_ERROR;
00787   }
00788 
00789   /* Update volatile configuration register (with new dummy cycles) */  
00790   sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
00791   MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY)));
00792       
00793   /* Configure the write volatile configuration register command */
00794   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00795   {
00796     return QSPI_ERROR;
00797   }
00798 
00799   /* Transmission of the data */
00800   if (HAL_QSPI_Transmit(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00801   {
00802     return QSPI_ERROR;
00803   }
00804   
00805   return QSPI_OK;
00806 }
00807 
00808 /**
00809   * @brief  This function send a Write Enable and wait it is effective.
00810   * @param  hqspi: QSPI handle
00811   * @retval None
00812   */
00813 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi)
00814 {
00815   QSPI_CommandTypeDef     sCommand;
00816   QSPI_AutoPollingTypeDef sConfig;
00817 
00818   /* Enable write operations */
00819   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00820   sCommand.Instruction       = WRITE_ENABLE_CMD;
00821   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00822   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00823   sCommand.DataMode          = QSPI_DATA_NONE;
00824   sCommand.DummyCycles       = 0;
00825   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00826   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00827   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00828 
00829   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00830   {
00831     return QSPI_ERROR;
00832   }
00833   
00834   /* Configure automatic polling mode to wait for write enabling */  
00835   sConfig.Match           = N25Q128A_SR_WREN;
00836   sConfig.Mask            = N25Q128A_SR_WREN;
00837   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00838   sConfig.StatusBytesSize = 1;
00839   sConfig.Interval        = 0x10;
00840   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00841 
00842   sCommand.Instruction    = READ_STATUS_REG_CMD;
00843   sCommand.DataMode       = QSPI_DATA_1_LINE;
00844 
00845   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00846   {
00847     return QSPI_ERROR;
00848   }
00849 
00850   return QSPI_OK;
00851 }
00852 
00853 /**
00854   * @brief  This function read the SR of the memory and wait the EOP.
00855   * @param  hqspi: QSPI handle
00856   * @param  Timeout: Timeout for auto-polling
00857   * @retval None
00858   */
00859 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
00860 {
00861   QSPI_CommandTypeDef     sCommand;
00862   QSPI_AutoPollingTypeDef sConfig;
00863 
00864   /* Configure automatic polling mode to wait for memory ready */  
00865   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00866   sCommand.Instruction       = READ_STATUS_REG_CMD;
00867   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00868   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00869   sCommand.DataMode          = QSPI_DATA_1_LINE;
00870   sCommand.DummyCycles       = 0;
00871   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00872   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00873   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00874 
00875   sConfig.Match           = 0;
00876   sConfig.Mask            = N25Q128A_SR_WIP;
00877   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00878   sConfig.StatusBytesSize = 1;
00879   sConfig.Interval        = 0x10;
00880   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00881 
00882   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK)
00883   {
00884     return QSPI_ERROR;
00885   }
00886 
00887   return QSPI_OK;
00888 }
00889 
00890 /**
00891   * @}
00892   */
00893 
00894 /**
00895   * @}
00896   */
00897 
00898 /**
00899   * @}
00900   */
00901 
00902 /**
00903   * @}
00904   */
00905 
00906 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00907 
Generated on Tue Jun 23 2015 17:15:45 for STM32L476G-Discovery BSP User Manual by   doxygen 1.7.6.1