E&R S3 prime / BSP_DISCO_L476VG
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l476g_discovery_qspi.c Source File

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   * @brief   This file includes a standard driver for the N25Q128A QSPI
00006   *          memory mounted on STM32L476G-Discovery board.
00007   @verbatim
00008   ==============================================================================
00009                      ##### How to use this driver #####
00010   ==============================================================================
00011   [..]
00012    (#) This driver is used to drive the N25Q128A QSPI external
00013        memory mounted on STM32L476G-DISCO evaluation board.
00014 
00015    (#) This driver need a specific component driver (N25Q128A) to be included with.
00016 
00017    (#) Initialization steps:
00018        (++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This
00019             function includes the MSP layer hardware resources initialization and the
00020             QSPI interface with the external memory. The BSP_QSPI_DeInit() can be used
00021             to deactivate the QSPI interface.
00022 
00023    (#) QSPI memory operations
00024        (++) QSPI memory can be accessed with read/write operations once it is
00025             initialized.
00026             Read/write operation can be performed with AHB access using the functions
00027             BSP_QSPI_Read()/BSP_QSPI_Write().
00028        (++) The function to the QSPI memory in memory-mapped mode is possible after
00029             the call of the function BSP_QSPI_EnableMemoryMappedMode().
00030        (++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory.
00031             (see the QSPI memory data sheet)
00032        (++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by
00033             specifying the block address. You can perform an erase operation of the whole
00034             chip by calling the function BSP_QSPI_Erase_Chip().
00035        (++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory.
00036             (see the QSPI memory data sheet)
00037        (++) Perform erase sector operation using the function BSP_QSPI_Erase_Sector()
00038             which is not blocking. So the function BSP_QSPI_GetStatus() should be used
00039             to check if the memory is busy, and the functions BSP_QSPI_SuspendErase()/
00040             BSP_QSPI_ResumeErase() can be used to perform other operations during the
00041             sector erase.
00042   @endverbatim
00043   ******************************************************************************
00044   * @attention
00045   *
00046   * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
00047   * All rights reserved.</center></h2>
00048   *
00049   * This software component is licensed by ST under BSD 3-Clause license,
00050   * the "License"; You may not use this file except in compliance with the
00051   * License. You may obtain a copy of the License at:
00052   *                        opensource.org/licenses/BSD-3-Clause
00053   *
00054   ******************************************************************************
00055   */
00056 
00057 /* Includes ------------------------------------------------------------------*/
00058 #include "stm32l476g_discovery_qspi.h"
00059 
00060 /** @addtogroup BSP
00061   * @{
00062   */
00063 
00064 /** @addtogroup STM32L476G_DISCOVERY
00065   * @{
00066   */
00067 
00068 /** @defgroup STM32L476G_DISCOVERY_QSPI STM32L476G-DISCOVERY QSPI
00069   * @{
00070   */
00071 
00072 /* Private variables ---------------------------------------------------------*/
00073 
00074 /** @defgroup STM32L476G_DISCOVERY_QSPI_Private_Variables Private Variables
00075   * @{
00076   */
00077 QSPI_HandleTypeDef QSPIHandle;
00078 
00079 /**
00080   * @}
00081   */
00082 
00083 
00084 /* Private functions ---------------------------------------------------------*/
00085 
00086 /** @defgroup STM32L476G_DISCOVERY_QSPI_Private_Functions Private Functions
00087   * @{
00088   */
00089 static void    QSPI_MspInit(void);
00090 static void    QSPI_MspDeInit(void);
00091 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi);
00092 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi);
00093 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi);
00094 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout);
00095 
00096 /**
00097   * @}
00098   */
00099 
00100 /* Exported functions ---------------------------------------------------------*/
00101 
00102 /** @addtogroup STM32L476G_DISCOVERY_QSPI_Exported_Functions
00103   * @{
00104   */
00105 
00106 /**
00107   * @brief  Initializes the QSPI interface.
00108   * @retval QSPI memory status
00109   */
00110 uint8_t BSP_QSPI_Init(void)
00111 {
00112   QSPIHandle.Instance = QUADSPI;
00113 
00114   /* Call the DeInit function to reset the driver */
00115   if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
00116   {
00117     return QSPI_ERROR;
00118   }
00119 
00120   /* System level initialization */
00121   QSPI_MspInit();
00122 
00123   /* QSPI initialization */
00124   QSPIHandle.Init.ClockPrescaler     = 1; /* QSPI clock = 80MHz / (ClockPrescaler+1) = 40MHz */
00125   QSPIHandle.Init.FifoThreshold      = 4;
00126   QSPIHandle.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_NONE;
00127   QSPIHandle.Init.FlashSize          = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1;
00128   QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
00129   QSPIHandle.Init.ClockMode          = QSPI_CLOCK_MODE_0;
00130 
00131   if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK)
00132   {
00133     return QSPI_ERROR;
00134   }
00135 
00136   /* QSPI memory reset */
00137   if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK)
00138   {
00139     return QSPI_NOT_SUPPORTED;
00140   }
00141 
00142   /* Configuration of the dummy cucles on QSPI memory side */
00143   if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK)
00144   {
00145     return QSPI_NOT_SUPPORTED;
00146   }
00147 
00148   return QSPI_OK;
00149 }
00150 
00151 /**
00152   * @brief  De-Initializes the QSPI interface.
00153   * @retval QSPI memory status
00154   */
00155 uint8_t BSP_QSPI_DeInit(void)
00156 {
00157   QSPIHandle.Instance = QUADSPI;
00158 
00159   /* Call the DeInit function to reset the driver */
00160   if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
00161   {
00162     return QSPI_ERROR;
00163   }
00164 
00165   /* System level De-initialization */
00166   QSPI_MspDeInit();
00167 
00168   return QSPI_OK;
00169 }
00170 
00171 /**
00172   * @brief  Reads an amount of data from the QSPI memory.
00173   * @param  pData: Pointer to data to be read
00174   * @param  ReadAddr: Read start address
00175   * @param  Size: Size of data to read
00176   * @retval QSPI memory status
00177   */
00178 uint8_t BSP_QSPI_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size)
00179 {
00180   QSPI_CommandTypeDef sCommand;
00181 
00182   /* Initialize the read command */
00183   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00184   sCommand.Instruction       = QUAD_INOUT_FAST_READ_CMD;
00185   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00186   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00187   sCommand.Address           = ReadAddr;
00188   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00189   sCommand.DataMode          = QSPI_DATA_4_LINES;
00190   sCommand.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
00191   sCommand.NbData            = Size;
00192   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00193   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00194   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00195 
00196   /* Configure the command */
00197   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00198   {
00199     return QSPI_ERROR;
00200   }
00201 
00202   /* Reception of the data */
00203   if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00204   {
00205     return QSPI_ERROR;
00206   }
00207 
00208   return QSPI_OK;
00209 }
00210 
00211 /**
00212   * @brief  Writes an amount of data to the QSPI memory.
00213   * @param  pData: Pointer to data to be written
00214   * @param  WriteAddr: Write start address
00215   * @param  Size: Size of data to write
00216   * @retval QSPI memory status
00217   */
00218 uint8_t BSP_QSPI_Write(uint8_t *pData, uint32_t WriteAddr, uint32_t Size)
00219 {
00220   QSPI_CommandTypeDef sCommand;
00221   uint32_t end_addr, current_size, current_addr;
00222 
00223   /* Calculation of the size between the write address and the end of the page */
00224   current_size = N25Q128A_PAGE_SIZE - (WriteAddr % N25Q128A_PAGE_SIZE);
00225 
00226   /* Check if the size of the data is less than the remaining place in the page */
00227   if (current_size > Size)
00228   {
00229     current_size = Size;
00230   }
00231 
00232   /* Initialize the adress variables */
00233   current_addr = WriteAddr;
00234   end_addr = WriteAddr + Size;
00235 
00236   /* Initialize the program command */
00237   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00238   sCommand.Instruction       = EXT_QUAD_IN_FAST_PROG_CMD;
00239   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00240   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00241   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00242   sCommand.DataMode          = QSPI_DATA_4_LINES;
00243   sCommand.DummyCycles       = 0;
00244   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00245   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00246   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00247 
00248   /* Perform the write page by page */
00249   do
00250   {
00251     sCommand.Address = current_addr;
00252     sCommand.NbData  = current_size;
00253 
00254     /* Enable write operations */
00255     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00256     {
00257       return QSPI_ERROR;
00258     }
00259 
00260     /* Configure the command */
00261     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00262     {
00263       return QSPI_ERROR;
00264     }
00265 
00266     /* Transmission of the data */
00267     if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00268     {
00269       return QSPI_ERROR;
00270     }
00271 
00272     /* Configure automatic polling mode to wait for end of program */
00273     if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
00274     {
00275       return QSPI_ERROR;
00276     }
00277 
00278     /* Update the address and size variables for next page programming */
00279     current_addr += current_size;
00280     pData += current_size;
00281     current_size = ((current_addr + N25Q128A_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : N25Q128A_PAGE_SIZE;
00282   }
00283   while (current_addr < end_addr);
00284 
00285   return QSPI_OK;
00286 }
00287 
00288 /**
00289   * @brief  Erases the specified block of the QSPI memory.
00290   * @param  BlockAddress: Block address to erase
00291   * @retval QSPI memory status
00292   */
00293 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress)
00294 {
00295   QSPI_CommandTypeDef sCommand;
00296 
00297   /* Initialize the erase command */
00298   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00299   sCommand.Instruction       = SUBSECTOR_ERASE_CMD;
00300   sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
00301   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00302   sCommand.Address           = BlockAddress;
00303   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00304   sCommand.DataMode          = QSPI_DATA_NONE;
00305   sCommand.DummyCycles       = 0;
00306   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00307   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00308   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00309 
00310   /* Enable write operations */
00311   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00312   {
00313     return QSPI_ERROR;
00314   }
00315 
00316   /* Send the command */
00317   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00318   {
00319     return QSPI_ERROR;
00320   }
00321 
00322   /* Configure automatic polling mode to wait for end of erase */
00323   if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK)
00324   {
00325     return QSPI_ERROR;
00326   }
00327 
00328   return QSPI_OK;
00329 }
00330 
00331 /**
00332   * @brief  Erases the specified sector of the QSPI memory.
00333   * @param  Sector: Sector address to erase (0 to 255)
00334   * @retval QSPI memory status
00335   * @note This function is non blocking meaning that sector erase
00336   *       operation is started but not completed when the function
00337   *       returns. Application has to call BSP_QSPI_GetStatus()
00338   *       to know when the device is available again (i.e. erase operation
00339   *       completed).
00340   */
00341 uint8_t BSP_QSPI_Erase_Sector(uint32_t Sector)
00342 {
00343   QSPI_CommandTypeDef sCommand;
00344 
00345   if (Sector >= (uint32_t)(N25Q128A_FLASH_SIZE / N25Q128A_SECTOR_SIZE))
00346   {
00347     return QSPI_ERROR;
00348   }
00349 
00350   /* Initialize the erase command */
00351   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00352   sCommand.Instruction       = SECTOR_ERASE_CMD;
00353   sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
00354   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00355   sCommand.Address           = (Sector * N25Q128A_SECTOR_SIZE);
00356   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00357   sCommand.DataMode          = QSPI_DATA_NONE;
00358   sCommand.DummyCycles       = 0;
00359   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00360   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00361   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00362 
00363   /* Enable write operations */
00364   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00365   {
00366     return QSPI_ERROR;
00367   }
00368 
00369   /* Send the command */
00370   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00371   {
00372     return QSPI_ERROR;
00373   }
00374 
00375   return QSPI_OK;
00376 }
00377 
00378 /**
00379   * @brief  Erases the entire QSPI memory.
00380   * @retval QSPI memory status
00381   */
00382 uint8_t BSP_QSPI_Erase_Chip(void)
00383 {
00384   QSPI_CommandTypeDef sCommand;
00385 
00386   /* Initialize the erase command */
00387   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00388   sCommand.Instruction       = BULK_ERASE_CMD;
00389   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00390   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00391   sCommand.DataMode          = QSPI_DATA_NONE;
00392   sCommand.DummyCycles       = 0;
00393   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00394   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00395   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00396 
00397   /* Enable write operations */
00398   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00399   {
00400     return QSPI_ERROR;
00401   }
00402 
00403   /* Send the command */
00404   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00405   {
00406     return QSPI_ERROR;
00407   }
00408 
00409   /* Configure automatic polling mode to wait for end of erase */
00410   if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK)
00411   {
00412     return QSPI_ERROR;
00413   }
00414 
00415   return QSPI_OK;
00416 }
00417 
00418 /**
00419   * @brief  Reads current status of the QSPI memory.
00420   * @retval QSPI memory status
00421   */
00422 uint8_t BSP_QSPI_GetStatus(void)
00423 {
00424   QSPI_CommandTypeDef sCommand;
00425   uint8_t reg;
00426 
00427   /* Initialize the read flag status register command */
00428   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00429   sCommand.Instruction       = READ_FLAG_STATUS_REG_CMD;
00430   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00431   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00432   sCommand.DataMode          = QSPI_DATA_1_LINE;
00433   sCommand.DummyCycles       = 0;
00434   sCommand.NbData            = 1;
00435   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00436   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00437   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00438 
00439   /* Configure the command */
00440   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00441   {
00442     return QSPI_ERROR;
00443   }
00444 
00445   /* Reception of the data */
00446   if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00447   {
00448     return QSPI_ERROR;
00449   }
00450 
00451   /* Check the value of the register */
00452   if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0)
00453   {
00454     return QSPI_ERROR;
00455   }
00456   else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0)
00457   {
00458     return QSPI_SUSPENDED;
00459   }
00460   else if ((reg & N25Q128A_FSR_READY) != 0)
00461   {
00462     return QSPI_OK;
00463   }
00464   else
00465   {
00466     return QSPI_BUSY;
00467   }
00468 }
00469 
00470 /**
00471   * @brief  Return the configuration of the QSPI memory.
00472   * @param  pInfo: pointer on the configuration structure
00473   * @retval QSPI memory status
00474   */
00475 uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo)
00476 {
00477   /* Configure the structure with the memory configuration */
00478   pInfo->FlashSize          = N25Q128A_FLASH_SIZE;
00479   pInfo->EraseSectorSize    = N25Q128A_SUBSECTOR_SIZE;
00480   pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE / N25Q128A_SUBSECTOR_SIZE);
00481   pInfo->ProgPageSize       = N25Q128A_PAGE_SIZE;
00482   pInfo->ProgPagesNumber    = (N25Q128A_FLASH_SIZE / N25Q128A_PAGE_SIZE);
00483 
00484   return QSPI_OK;
00485 }
00486 
00487 /**
00488   * @brief  Configure the QSPI in memory-mapped mode
00489   * @retval QSPI memory status
00490   */
00491 uint8_t BSP_QSPI_EnableMemoryMappedMode(void)
00492 {
00493   QSPI_CommandTypeDef      sCommand;
00494   QSPI_MemoryMappedTypeDef sMemMappedCfg;
00495 
00496   /* Configure the command for the read instruction */
00497   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00498   sCommand.Instruction       = QUAD_INOUT_FAST_READ_CMD;
00499   sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
00500   sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
00501   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00502   sCommand.DataMode          = QSPI_DATA_4_LINES;
00503   sCommand.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
00504   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00505   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00506   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00507 
00508   /* Configure the memory mapped mode */
00509   sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
00510 
00511   if (HAL_QSPI_MemoryMapped(&QSPIHandle, &sCommand, &sMemMappedCfg) != HAL_OK)
00512   {
00513     return QSPI_ERROR;
00514   }
00515 
00516   return QSPI_OK;
00517 }
00518 
00519 /**
00520   * @brief  This function suspends an ongoing erase command.
00521   * @retval QSPI memory status
00522   */
00523 uint8_t BSP_QSPI_SuspendErase(void)
00524 {
00525   QSPI_CommandTypeDef sCommand;
00526 
00527   /* Check whether the device is busy (erase operation is
00528   in progress).
00529   */
00530   if (BSP_QSPI_GetStatus() == QSPI_BUSY)
00531   {
00532     /* Initialize the erase command */
00533     sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00534     sCommand.Instruction       = PROG_ERASE_SUSPEND_CMD;
00535     sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00536     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00537     sCommand.DataMode          = QSPI_DATA_NONE;
00538     sCommand.DummyCycles       = 0;
00539     sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00540     sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00541     sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00542 
00543     /* Enable write operations */
00544     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00545     {
00546       return QSPI_ERROR;
00547     }
00548 
00549     /* Send the command */
00550     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00551     {
00552       return QSPI_ERROR;
00553     }
00554 
00555     if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED)
00556     {
00557       return QSPI_OK;
00558     }
00559 
00560     return QSPI_ERROR;
00561   }
00562 
00563   return QSPI_OK;
00564 }
00565 
00566 /**
00567   * @brief  This function resumes a paused erase command.
00568   * @retval QSPI memory status
00569   */
00570 uint8_t BSP_QSPI_ResumeErase(void)
00571 {
00572   QSPI_CommandTypeDef sCommand;
00573 
00574   /* Check whether the device is in suspended state */
00575   if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED)
00576   {
00577     /* Initialize the erase command */
00578     sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00579     sCommand.Instruction       = PROG_ERASE_RESUME_CMD;
00580     sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00581     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00582     sCommand.DataMode          = QSPI_DATA_NONE;
00583     sCommand.DummyCycles       = 0;
00584     sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00585     sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00586     sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00587 
00588     /* Enable write operations */
00589     if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00590     {
00591       return QSPI_ERROR;
00592     }
00593 
00594     /* Send the command */
00595     if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00596     {
00597       return QSPI_ERROR;
00598     }
00599 
00600     /*
00601     When this command is executed, the status register write in progress bit is set to 1, and
00602     the flag status register program erase controller bit is set to 0. This command is ignored
00603     if the device is not in a suspended state.
00604     */
00605 
00606     if (BSP_QSPI_GetStatus() == QSPI_BUSY)
00607     {
00608       return QSPI_OK;
00609     }
00610 
00611     return QSPI_ERROR;
00612   }
00613 
00614   return QSPI_OK;
00615 }
00616 
00617 /**
00618   * @}
00619   */
00620 
00621 /** @addtogroup STM32L476G_DISCOVERY_QSPI_Private_Functions
00622   * @{
00623   */
00624 
00625 /**
00626   * @brief  Initializes the QSPI MSP.
00627   * @retval None
00628   */
00629 static void QSPI_MspInit(void)
00630 {
00631   GPIO_InitTypeDef GPIO_InitStruct;
00632 
00633   /* Enable the QuadSPI memory interface clock */
00634   __HAL_RCC_QSPI_CLK_ENABLE();
00635 
00636   /* Reset the QuadSPI memory interface */
00637   __HAL_RCC_QSPI_FORCE_RESET();
00638   __HAL_RCC_QSPI_RELEASE_RESET();
00639 
00640   /* Enable GPIO clocks */
00641   __HAL_RCC_GPIOE_CLK_ENABLE();
00642 
00643   /* QSPI CS GPIO pin configuration  */
00644   GPIO_InitStruct.Pin       = GPIO_PIN_11;
00645   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
00646   GPIO_InitStruct.Pull      = GPIO_PULLUP;
00647   GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
00648   GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
00649   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00650 
00651   /* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration  */
00652   GPIO_InitStruct.Pin       = (GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
00653   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00654   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00655 }
00656 
00657 /**
00658   * @brief  De-Initializes the QSPI MSP.
00659   * @retval None
00660   */
00661 static void QSPI_MspDeInit(void)
00662 {
00663   GPIO_InitTypeDef GPIO_InitStruct;
00664 
00665   /* QSPI CLK, CS, PE10 - PE15 GPIO pins de-configuration  */
00666 
00667   __HAL_RCC_GPIOE_CLK_ENABLE();
00668   HAL_GPIO_DeInit(GPIOE, (GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15));
00669   /* Set GPIOE pin 11 in pull up mode (optimum default setting) */
00670   GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
00671   GPIO_InitStruct.Pin       = GPIO_PIN_11;
00672   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00673   GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_LOW;
00674   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00675 
00676   /* Set GPIOE pin 10 in no pull, low state (optimum default setting) */
00677   GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP  ;
00678   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00679   GPIO_InitStruct.Pin       = (GPIO_PIN_10);
00680   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
00681   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10, GPIO_PIN_RESET);
00682 
00683   /* Reset the QuadSPI memory interface */
00684   __HAL_RCC_QSPI_FORCE_RESET();
00685   __HAL_RCC_QSPI_RELEASE_RESET();
00686 
00687   /* Disable the QuadSPI memory interface clock */
00688   __HAL_RCC_QSPI_CLK_DISABLE();
00689 }
00690 
00691 /**
00692   * @brief  This function reset the QSPI memory.
00693   * @param  hqspi: QSPI handle
00694   * @retval None
00695   */
00696 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi)
00697 {
00698   QSPI_CommandTypeDef sCommand;
00699 
00700   /* Initialize the reset enable command */
00701   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00702   sCommand.Instruction       = RESET_ENABLE_CMD;
00703   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00704   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00705   sCommand.DataMode          = QSPI_DATA_NONE;
00706   sCommand.DummyCycles       = 0;
00707   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00708   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00709   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00710 
00711   /* Send the command */
00712   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00713   {
00714     return QSPI_ERROR;
00715   }
00716 
00717   /* Send the reset memory command */
00718   sCommand.Instruction = RESET_MEMORY_CMD;
00719   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00720   {
00721     return QSPI_ERROR;
00722   }
00723 
00724   /* Configure automatic polling mode to wait the memory is ready */
00725   if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
00726   {
00727     return QSPI_ERROR;
00728   }
00729 
00730   return QSPI_OK;
00731 }
00732 
00733 /**
00734   * @brief  This function configure the dummy cycles on memory side.
00735   * @param  hqspi: QSPI handle
00736   * @retval None
00737   */
00738 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
00739 {
00740   QSPI_CommandTypeDef sCommand;
00741   uint8_t reg;
00742 
00743   /* Initialize the read volatile configuration register command */
00744   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00745   sCommand.Instruction       = READ_VOL_CFG_REG_CMD;
00746   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00747   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00748   sCommand.DataMode          = QSPI_DATA_1_LINE;
00749   sCommand.DummyCycles       = 0;
00750   sCommand.NbData            = 1;
00751   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00752   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00753   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00754 
00755   /* Configure the command */
00756   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00757   {
00758     return QSPI_ERROR;
00759   }
00760 
00761   /* Reception of the data */
00762   if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00763   {
00764     return QSPI_ERROR;
00765   }
00766 
00767   /* Enable write operations */
00768   if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
00769   {
00770     return QSPI_ERROR;
00771   }
00772 
00773   /* Update volatile configuration register (with new dummy cycles) */
00774   sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
00775   MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY)));
00776 
00777   /* Configure the write volatile configuration register command */
00778   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00779   {
00780     return QSPI_ERROR;
00781   }
00782 
00783   /* Transmission of the data */
00784   if (HAL_QSPI_Transmit(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00785   {
00786     return QSPI_ERROR;
00787   }
00788 
00789   return QSPI_OK;
00790 }
00791 
00792 /**
00793   * @brief  This function send a Write Enable and wait it is effective.
00794   * @param  hqspi: QSPI handle
00795   * @retval None
00796   */
00797 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi)
00798 {
00799   QSPI_CommandTypeDef     sCommand;
00800   QSPI_AutoPollingTypeDef sConfig;
00801 
00802   /* Enable write operations */
00803   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00804   sCommand.Instruction       = WRITE_ENABLE_CMD;
00805   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00806   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00807   sCommand.DataMode          = QSPI_DATA_NONE;
00808   sCommand.DummyCycles       = 0;
00809   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00810   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00811   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00812 
00813   if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00814   {
00815     return QSPI_ERROR;
00816   }
00817 
00818   /* Configure automatic polling mode to wait for write enabling */
00819   sConfig.Match           = N25Q128A_SR_WREN;
00820   sConfig.Mask            = N25Q128A_SR_WREN;
00821   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00822   sConfig.StatusBytesSize = 1;
00823   sConfig.Interval        = 0x10;
00824   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00825 
00826   sCommand.Instruction    = READ_STATUS_REG_CMD;
00827   sCommand.DataMode       = QSPI_DATA_1_LINE;
00828 
00829   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
00830   {
00831     return QSPI_ERROR;
00832   }
00833 
00834   return QSPI_OK;
00835 }
00836 
00837 /**
00838   * @brief  This function read the SR of the memory and wait the EOP.
00839   * @param  hqspi: QSPI handle
00840   * @param  Timeout: Timeout for auto-polling
00841   * @retval None
00842   */
00843 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
00844 {
00845   QSPI_CommandTypeDef     sCommand;
00846   QSPI_AutoPollingTypeDef sConfig;
00847 
00848   /* Configure automatic polling mode to wait for memory ready */
00849   sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
00850   sCommand.Instruction       = READ_STATUS_REG_CMD;
00851   sCommand.AddressMode       = QSPI_ADDRESS_NONE;
00852   sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
00853   sCommand.DataMode          = QSPI_DATA_1_LINE;
00854   sCommand.DummyCycles       = 0;
00855   sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
00856   sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
00857   sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
00858 
00859   sConfig.Match           = 0;
00860   sConfig.Mask            = N25Q128A_SR_WIP;
00861   sConfig.MatchMode       = QSPI_MATCH_MODE_AND;
00862   sConfig.StatusBytesSize = 1;
00863   sConfig.Interval        = 0x10;
00864   sConfig.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
00865 
00866   if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK)
00867   {
00868     return QSPI_ERROR;
00869   }
00870 
00871   return QSPI_OK;
00872 }
00873 
00874 /**
00875   * @}
00876   */
00877 
00878 /**
00879   * @}
00880   */
00881 
00882 /**
00883   * @}
00884   */
00885 
00886 /**
00887   * @}
00888   */
00889 
00890 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00891