STM32F723E-Discovery BSP User Manual
|
stm32f723e_discovery_qspi.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f723e_discovery_qspi.c 00004 * @author MCD Application Team 00005 * @brief This file includes a standard driver for the MX25L512 QSPI 00006 * memory mounted on STM32F723E-Discovery board. 00007 @verbatim 00008 ============================================================================== 00009 ##### How to use this driver ##### 00010 ============================================================================== 00011 [..] 00012 (#) This driver is used to drive the MX25L512 QSPI external 00013 memory mounted on STM32F723E-Discovery board. 00014 00015 (#) This driver need a specific component driver (MX25L51245G) to be included with. 00016 00017 (#) Initialization steps: 00018 (++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This 00019 function includes the MSP layer hardware resources initialization and the 00020 QSPI interface with the external memory. 00021 00022 (#) QSPI memory operations 00023 (++) QSPI memory can be accessed with read/write operations once it is 00024 initialized. 00025 Read/write operation can be performed with AHB access using the functions 00026 BSP_QSPI_Read()/BSP_QSPI_Write(). 00027 (++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory. 00028 (see the QSPI memory data sheet) 00029 (++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by 00030 specifying the block address. You can perform an erase operation of the whole 00031 chip by calling the function BSP_QSPI_Erase_Chip(). 00032 (++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. 00033 (see the QSPI memory data sheet) 00034 @endverbatim 00035 ****************************************************************************** 00036 * @attention 00037 * 00038 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00039 * 00040 * Redistribution and use in source and binary forms, with or without modification, 00041 * are permitted provided that the following conditions are met: 00042 * 1. Redistributions of source code must retain the above copyright notice, 00043 * this list of conditions and the following disclaimer. 00044 * 2. Redistributions in binary form must reproduce the above copyright notice, 00045 * this list of conditions and the following disclaimer in the documentation 00046 * and/or other materials provided with the distribution. 00047 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00048 * may be used to endorse or promote products derived from this software 00049 * without specific prior written permission. 00050 * 00051 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00052 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00053 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00054 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00055 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00056 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00057 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00058 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00059 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00060 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00061 * 00062 ****************************************************************************** 00063 */ 00064 00065 /* Dependencies 00066 - stm32f7xx_hal_qspi.c 00067 - stm32f7xx_hal_gpio.c 00068 - stm32f7xx_hal_cortex.c 00069 - stm32f7xx_hal_rcc_ex.h 00070 - mx25l512.h 00071 EndDependencies */ 00072 00073 /* Includes ------------------------------------------------------------------*/ 00074 #include "stm32f723e_discovery_qspi.h" 00075 00076 /** @addtogroup BSP 00077 * @{ 00078 */ 00079 00080 /** @addtogroup STM32F723E_DISCOVERY 00081 * @{ 00082 */ 00083 00084 /** @defgroup STM32F723E_DISCOVERY_QSPI STM32F723E-DISCOVERY QSPI 00085 * @{ 00086 */ 00087 00088 00089 /* Private variables ---------------------------------------------------------*/ 00090 00091 /** @defgroup STM32F723E_DISCOVERY_QSPI_Private_Variables STM32F723E_DISCOVERY QSPI Private Variables 00092 * @{ 00093 */ 00094 QSPI_HandleTypeDef QSPIHandle; 00095 00096 /** 00097 * @} 00098 */ 00099 00100 00101 00102 /* Private functions ---------------------------------------------------------*/ 00103 00104 /** @defgroup STM32F723E_DISCOVERY_QSPI_Private_Functions STM32F723E_DISCOVERY QSPI Private Functions 00105 * @{ 00106 */ 00107 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi); 00108 static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi); 00109 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi); 00110 static uint8_t QSPI_EnterMemory_QPI(QSPI_HandleTypeDef *hqspi); 00111 static uint8_t QSPI_ExitMemory_QPI(QSPI_HandleTypeDef *hqspi); 00112 static uint8_t QSPI_OutDrvStrengthCfg(QSPI_HandleTypeDef *hqspi); 00113 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi); 00114 static uint8_t QSPI_AutoPollingMemReady (QSPI_HandleTypeDef *hqspi, uint32_t Timeout); 00115 00116 /** 00117 * @} 00118 */ 00119 00120 /** @defgroup STM32F723E_DISCOVERY_QSPI_Exported_Functions STM32F723E_DISCOVERY QSPI Exported Functions 00121 * @{ 00122 */ 00123 00124 /** 00125 * @brief Initializes the QSPI interface. 00126 * @retval QSPI memory status 00127 */ 00128 uint8_t BSP_QSPI_Init(void) 00129 { 00130 QSPIHandle.Instance = QUADSPI; 00131 00132 /* Call the DeInit function to reset the driver */ 00133 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00134 { 00135 return QSPI_ERROR; 00136 } 00137 00138 /* System level initialization */ 00139 BSP_QSPI_MspInit(&QSPIHandle, NULL); 00140 00141 /* QSPI initialization */ 00142 /* QSPI freq = SYSCLK /(1 + ClockPrescaler) = 216 MHz/(1+1) = 108 Mhz */ 00143 QSPIHandle.Init.ClockPrescaler = 1; /* QSPI freq = 216 MHz/(1+1) = 108 Mhz */ 00144 QSPIHandle.Init.FifoThreshold = 16; 00145 QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; 00146 QSPIHandle.Init.FlashSize = POSITION_VAL(MX25L512_FLASH_SIZE) - 1; 00147 QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE; /* Min 30ns for nonRead */ 00148 QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; 00149 QSPIHandle.Init.FlashID = QSPI_FLASH_ID_1; 00150 QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_DISABLE; 00151 00152 if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) 00153 { 00154 return QSPI_ERROR; 00155 } 00156 00157 /* QSPI memory reset */ 00158 if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) 00159 { 00160 return QSPI_NOT_SUPPORTED; 00161 } 00162 00163 /* Put QSPI memory in QPI mode */ 00164 if( QSPI_EnterMemory_QPI( &QSPIHandle )!=QSPI_OK ) 00165 { 00166 return QSPI_NOT_SUPPORTED; 00167 } 00168 00169 /* Set the QSPI memory in 4-bytes address mode */ 00170 if (QSPI_EnterFourBytesAddress(&QSPIHandle) != QSPI_OK) 00171 { 00172 return QSPI_NOT_SUPPORTED; 00173 } 00174 00175 /* Configuration of the dummy cycles on QSPI memory side */ 00176 if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK) 00177 { 00178 return QSPI_NOT_SUPPORTED; 00179 } 00180 00181 /* Configuration of the Output driver strength on memory side */ 00182 if( QSPI_OutDrvStrengthCfg( &QSPIHandle ) != QSPI_OK ) 00183 { 00184 return QSPI_NOT_SUPPORTED; 00185 } 00186 00187 return QSPI_OK; 00188 } 00189 00190 /** 00191 * @brief De-Initializes the QSPI interface. 00192 * @retval QSPI memory status 00193 */ 00194 uint8_t BSP_QSPI_DeInit(void) 00195 { 00196 QSPIHandle.Instance = QUADSPI; 00197 00198 /* Put QSPI memory in SPI mode */ 00199 if( QSPI_ExitMemory_QPI(&QSPIHandle )!=QSPI_OK ) 00200 { 00201 return QSPI_NOT_SUPPORTED; 00202 } 00203 00204 /* Call the DeInit function to reset the driver */ 00205 if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) 00206 { 00207 return QSPI_ERROR; 00208 } 00209 00210 /* System level De-initialization */ 00211 BSP_QSPI_MspDeInit(&QSPIHandle, NULL); 00212 00213 return QSPI_OK; 00214 } 00215 00216 /** 00217 * @brief Reads an amount of data from the QSPI memory. 00218 * @param pData: Pointer to data to be read 00219 * @param ReadAddr: Read start address 00220 * @param Size: Size of data to read 00221 * @retval QSPI memory status 00222 */ 00223 uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) 00224 { 00225 QSPI_CommandTypeDef s_command; 00226 00227 /* Initialize the read command */ 00228 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00229 s_command.Instruction = QSPI_READ_4_BYTE_ADDR_CMD; 00230 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00231 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00232 s_command.Address = ReadAddr; 00233 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00234 s_command.DataMode = QSPI_DATA_4_LINES; 00235 s_command.DummyCycles = MX25L512_DUMMY_CYCLES_READ_QUAD_IO; 00236 s_command.NbData = Size; 00237 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00238 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00239 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00240 00241 /* Configure the command */ 00242 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00243 { 00244 return QSPI_ERROR; 00245 } 00246 00247 /* Set S# timing for Read command */ 00248 MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_1_CYCLE); 00249 00250 /* Reception of the data */ 00251 if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00252 { 00253 return QSPI_ERROR; 00254 } 00255 00256 /* Restore S# timing for nonRead commands */ 00257 MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_4_CYCLE); 00258 00259 return QSPI_OK; 00260 } 00261 00262 /** 00263 * @brief Writes an amount of data to the QSPI memory. 00264 * @param pData: Pointer to data to be written 00265 * @param WriteAddr: Write start address 00266 * @param Size: Size of data to write 00267 * @retval QSPI memory status 00268 */ 00269 uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) 00270 { 00271 QSPI_CommandTypeDef s_command; 00272 uint32_t end_addr, current_size, current_addr; 00273 00274 /* Calculation of the size between the write address and the end of the page */ 00275 current_size = MX25L512_PAGE_SIZE - (WriteAddr % MX25L512_PAGE_SIZE); 00276 00277 /* Check if the size of the data is less than the remaining place in the page */ 00278 if (current_size > Size) 00279 { 00280 current_size = Size; 00281 } 00282 00283 /* Initialize the address variables */ 00284 current_addr = WriteAddr; 00285 end_addr = WriteAddr + Size; 00286 00287 /* Initialize the program command */ 00288 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00289 s_command.Instruction = QSPI_PAGE_PROG_4_BYTE_ADDR_CMD; 00290 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00291 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00292 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00293 s_command.DataMode = QSPI_DATA_4_LINES; 00294 s_command.DummyCycles = 0; 00295 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00296 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00297 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00298 00299 /* Perform the write page by page */ 00300 do 00301 { 00302 s_command.Address = current_addr; 00303 s_command.NbData = current_size; 00304 00305 /* Enable write operations */ 00306 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00307 { 00308 return QSPI_ERROR; 00309 } 00310 00311 /* Configure the command */ 00312 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00313 { 00314 return QSPI_ERROR; 00315 } 00316 00317 /* Transmission of the data */ 00318 if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00319 { 00320 return QSPI_ERROR; 00321 } 00322 00323 /* Configure automatic polling mode to wait for end of program */ 00324 if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00325 { 00326 return QSPI_ERROR; 00327 } 00328 00329 /* Update the address and size variables for next page programming */ 00330 current_addr += current_size; 00331 pData += current_size; 00332 current_size = ((current_addr + MX25L512_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25L512_PAGE_SIZE; 00333 } while (current_addr < end_addr); 00334 00335 return QSPI_OK; 00336 } 00337 00338 /** 00339 * @brief Erases the specified block of the QSPI memory. 00340 * @param BlockAddress: Block address to erase 00341 * @retval QSPI memory status 00342 */ 00343 uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) 00344 { 00345 QSPI_CommandTypeDef s_command; 00346 00347 /* Initialize the erase command */ 00348 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00349 s_command.Instruction = SUBSECTOR_ERASE_4_BYTE_ADDR_CMD; 00350 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00351 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00352 s_command.Address = BlockAddress; 00353 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00354 s_command.DataMode = QSPI_DATA_NONE; 00355 s_command.DummyCycles = 0; 00356 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00357 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00358 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00359 00360 /* Enable write operations */ 00361 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00362 { 00363 return QSPI_ERROR; 00364 } 00365 00366 /* Send the command */ 00367 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00368 { 00369 return QSPI_ERROR; 00370 } 00371 00372 /* Configure automatic polling mode to wait for end of erase */ 00373 if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25L512_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK) 00374 { 00375 return QSPI_ERROR; 00376 } 00377 00378 return QSPI_OK; 00379 } 00380 00381 /** 00382 * @brief Erases the entire QSPI memory. 00383 * @retval QSPI memory status 00384 */ 00385 uint8_t BSP_QSPI_Erase_Chip(void) 00386 { 00387 QSPI_CommandTypeDef s_command; 00388 00389 /* Initialize the erase command */ 00390 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00391 s_command.Instruction = BULK_ERASE_CMD; 00392 s_command.AddressMode = QSPI_ADDRESS_NONE; 00393 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00394 s_command.DataMode = QSPI_DATA_NONE; 00395 s_command.DummyCycles = 0; 00396 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00397 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00398 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00399 00400 /* Enable write operations */ 00401 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 00402 { 00403 return QSPI_ERROR; 00404 } 00405 00406 /* Send the command */ 00407 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00408 { 00409 return QSPI_ERROR; 00410 } 00411 00412 /* Configure automatic polling mode to wait for end of erase */ 00413 if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25L512_BULK_ERASE_MAX_TIME) != QSPI_OK) 00414 { 00415 return QSPI_ERROR; 00416 } 00417 00418 return QSPI_OK; 00419 } 00420 00421 /** 00422 * @brief Reads current status of the QSPI memory. 00423 * @retval QSPI memory status 00424 */ 00425 uint8_t BSP_QSPI_GetStatus(void) 00426 { 00427 QSPI_CommandTypeDef s_command; 00428 uint8_t reg; 00429 00430 /* Initialize the read flag status register command */ 00431 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00432 s_command.Instruction = READ_STATUS_REG_CMD; 00433 s_command.AddressMode = QSPI_ADDRESS_NONE; 00434 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00435 s_command.DataMode = QSPI_DATA_4_LINES; 00436 s_command.DummyCycles = 0; 00437 s_command.NbData = 1; 00438 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00439 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00440 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00441 00442 /* Configure the command */ 00443 if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00444 { 00445 return QSPI_ERROR; 00446 } 00447 00448 /* Reception of the data */ 00449 if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00450 { 00451 return QSPI_ERROR; 00452 } 00453 00454 /* Check the value of the register*/ 00455 if ((reg & MX25L512_SR_WIP) == 0) 00456 { 00457 return QSPI_OK; 00458 } 00459 else 00460 { 00461 return QSPI_BUSY; 00462 } 00463 } 00464 00465 /** 00466 * @brief Return the configuration of the QSPI memory. 00467 * @param pInfo: pointer on the configuration structure 00468 * @retval QSPI memory status 00469 */ 00470 uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo) 00471 { 00472 /* Configure the structure with the memory configuration */ 00473 pInfo->FlashSize = MX25L512_FLASH_SIZE; 00474 pInfo->EraseSectorSize = MX25L512_SUBSECTOR_SIZE; 00475 pInfo->EraseSectorsNumber = (MX25L512_FLASH_SIZE/MX25L512_SUBSECTOR_SIZE); 00476 pInfo->ProgPageSize = MX25L512_PAGE_SIZE; 00477 pInfo->ProgPagesNumber = (MX25L512_FLASH_SIZE/MX25L512_PAGE_SIZE); 00478 00479 return QSPI_OK; 00480 } 00481 00482 /** 00483 * @brief Configure the QSPI in memory-mapped mode 00484 * @retval QSPI memory status 00485 */ 00486 uint8_t BSP_QSPI_EnableMemoryMappedMode(void) 00487 { 00488 QSPI_CommandTypeDef s_command; 00489 QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; 00490 00491 /* Configure the command for the read instruction */ 00492 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00493 s_command.Instruction = QSPI_READ_4_BYTE_ADDR_CMD; 00494 s_command.AddressMode = QSPI_ADDRESS_4_LINES; 00495 s_command.AddressSize = QSPI_ADDRESS_32_BITS; 00496 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00497 s_command.DataMode = QSPI_DATA_4_LINES; 00498 s_command.DummyCycles = MX25L512_DUMMY_CYCLES_READ_QUAD_IO; 00499 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00500 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00501 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00502 00503 /* Configure the memory mapped mode */ 00504 s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; 00505 s_mem_mapped_cfg.TimeOutPeriod = 0; 00506 00507 if (HAL_QSPI_MemoryMapped(&QSPIHandle, &s_command, &s_mem_mapped_cfg) != HAL_OK) 00508 { 00509 return QSPI_ERROR; 00510 } 00511 00512 return QSPI_OK; 00513 } 00514 00515 /** 00516 * @} 00517 */ 00518 00519 /** @addtogroup STM32F723E_DISCOVERY_QSPI_Private_Functions 00520 * @{ 00521 */ 00522 00523 /** 00524 * @brief QSPI MSP Initialization 00525 * This function configures the hardware resources used in this example: 00526 * - Peripheral's clock enable 00527 * - Peripheral's GPIO Configuration 00528 * - NVIC configuration for QSPI interrupt 00529 * @retval None 00530 */ 00531 __weak void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params) 00532 { 00533 GPIO_InitTypeDef gpio_init_structure; 00534 00535 /*##-1- Enable peripherals and GPIO Clocks #################################*/ 00536 /* Enable the QuadSPI memory interface clock */ 00537 QSPI_CLK_ENABLE(); 00538 /* Reset the QuadSPI memory interface */ 00539 QSPI_FORCE_RESET(); 00540 QSPI_RELEASE_RESET(); 00541 /* Enable GPIO clocks */ 00542 QSPI_CS_GPIO_CLK_ENABLE(); 00543 QSPI_CLK_GPIO_CLK_ENABLE(); 00544 QSPI_D0_GPIO_CLK_ENABLE(); 00545 QSPI_D1_GPIO_CLK_ENABLE(); 00546 QSPI_D2_GPIO_CLK_ENABLE(); 00547 QSPI_D3_GPIO_CLK_ENABLE(); 00548 00549 /*##-2- Configure peripheral GPIO ##########################################*/ 00550 /* QSPI CS GPIO pin configuration */ 00551 gpio_init_structure.Pin = QSPI_CS_PIN; 00552 gpio_init_structure.Alternate = QSPI_CS_PIN_AF; 00553 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00554 gpio_init_structure.Pull = GPIO_PULLUP; 00555 gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; 00556 HAL_GPIO_Init(QSPI_CS_GPIO_PORT, &gpio_init_structure); 00557 /* QSPI CLK GPIO pin configuration */ 00558 gpio_init_structure.Pin = QSPI_CLK_PIN; 00559 gpio_init_structure.Alternate = QSPI_CLK_PIN_AF; 00560 gpio_init_structure.Pull = GPIO_NOPULL; 00561 HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure); 00562 /* QSPI D0 GPIO pin configuration */ 00563 gpio_init_structure.Pin = QSPI_D0_PIN; 00564 gpio_init_structure.Alternate = QSPI_D0_PIN_AF; 00565 HAL_GPIO_Init(QSPI_D0_GPIO_PORT, &gpio_init_structure); 00566 /* QSPI D1 GPIO pin configuration */ 00567 gpio_init_structure.Pin = QSPI_D1_PIN; 00568 gpio_init_structure.Alternate = QSPI_D1_PIN_AF; 00569 HAL_GPIO_Init(QSPI_D1_GPIO_PORT, &gpio_init_structure); 00570 /* QSPI D2 GPIO pin configuration */ 00571 gpio_init_structure.Pin = QSPI_D2_PIN; 00572 gpio_init_structure.Alternate = QSPI_D2_PIN_AF; 00573 HAL_GPIO_Init(QSPI_D2_GPIO_PORT, &gpio_init_structure); 00574 /* QSPI D3 GPIO pin configuration */ 00575 gpio_init_structure.Pin = QSPI_D3_PIN; 00576 gpio_init_structure.Alternate = QSPI_D3_PIN_AF; 00577 HAL_GPIO_Init(QSPI_D3_GPIO_PORT, &gpio_init_structure); 00578 00579 /*##-3- Configure the NVIC for QSPI #########################################*/ 00580 /* NVIC configuration for QSPI interrupt */ 00581 HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0); 00582 HAL_NVIC_EnableIRQ(QUADSPI_IRQn); 00583 } 00584 00585 /** 00586 * @brief QSPI MSP De-Initialization 00587 * This function frees the hardware resources used in this example: 00588 * - Disable the Peripheral's clock 00589 * - Revert GPIO and NVIC configuration to their default state 00590 * @retval None 00591 */ 00592 __weak void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params) 00593 { 00594 /*##-1- Disable the NVIC for QSPI ###########################################*/ 00595 HAL_NVIC_DisableIRQ(QUADSPI_IRQn); 00596 00597 /*##-2- Disable peripherals and GPIO Clocks ################################*/ 00598 /* De-Configure QSPI pins */ 00599 HAL_GPIO_DeInit(QSPI_CS_GPIO_PORT, QSPI_CS_PIN); 00600 HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN); 00601 HAL_GPIO_DeInit(QSPI_D0_GPIO_PORT, QSPI_D0_PIN); 00602 HAL_GPIO_DeInit(QSPI_D1_GPIO_PORT, QSPI_D1_PIN); 00603 HAL_GPIO_DeInit(QSPI_D2_GPIO_PORT, QSPI_D2_PIN); 00604 HAL_GPIO_DeInit(QSPI_D3_GPIO_PORT, QSPI_D3_PIN); 00605 00606 /*##-3- Reset peripherals ##################################################*/ 00607 /* Reset the QuadSPI memory interface */ 00608 QSPI_FORCE_RESET(); 00609 QSPI_RELEASE_RESET(); 00610 00611 /* Disable the QuadSPI memory interface clock */ 00612 QSPI_CLK_DISABLE(); 00613 } 00614 00615 /** 00616 * @brief This function reset the QSPI memory. 00617 * @param hqspi: QSPI handle 00618 * @retval None 00619 */ 00620 static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) 00621 { 00622 QSPI_CommandTypeDef s_command; 00623 QSPI_AutoPollingTypeDef s_config; 00624 uint8_t reg; 00625 00626 /* Send command RESET command in QPI mode (QUAD I/Os) */ 00627 /* Initialize the reset enable command */ 00628 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00629 s_command.Instruction = RESET_ENABLE_CMD; 00630 s_command.AddressMode = QSPI_ADDRESS_NONE; 00631 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00632 s_command.DataMode = QSPI_DATA_NONE; 00633 s_command.DummyCycles = 0; 00634 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00635 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00636 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00637 /* Send the command */ 00638 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00639 { 00640 return QSPI_ERROR; 00641 } 00642 /* Send the reset memory command */ 00643 s_command.Instruction = RESET_MEMORY_CMD; 00644 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00645 { 00646 return QSPI_ERROR; 00647 } 00648 00649 /* Send command RESET command in SPI mode */ 00650 /* Initialize the reset enable command */ 00651 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00652 s_command.Instruction = RESET_ENABLE_CMD; 00653 /* Send the command */ 00654 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00655 { 00656 return QSPI_ERROR; 00657 } 00658 /* Send the reset memory command */ 00659 s_command.Instruction = RESET_MEMORY_CMD; 00660 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00661 { 00662 return QSPI_ERROR; 00663 } 00664 00665 /* After reset CMD, 1000ms requested if QSPI memory SWReset occured during full chip erase operation */ 00666 HAL_Delay( 1000 ); 00667 00668 /* Configure automatic polling mode to wait the WIP bit=0 */ 00669 s_config.Match = 0; 00670 s_config.Mask = MX25L512_SR_WIP; 00671 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00672 s_config.StatusBytesSize = 1; 00673 s_config.Interval = 0x10; 00674 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00675 00676 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00677 s_command.Instruction = READ_STATUS_REG_CMD; 00678 s_command.DataMode = QSPI_DATA_1_LINE; 00679 00680 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00681 { 00682 return QSPI_ERROR; 00683 } 00684 00685 /* Initialize the reading of status register */ 00686 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00687 s_command.Instruction = READ_STATUS_REG_CMD; 00688 s_command.AddressMode = QSPI_ADDRESS_NONE; 00689 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00690 s_command.DataMode = QSPI_DATA_1_LINE; 00691 s_command.DummyCycles = 0; 00692 s_command.NbData = 1; 00693 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00694 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00695 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00696 00697 /* Configure the command */ 00698 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00699 { 00700 return QSPI_ERROR; 00701 } 00702 00703 /* Reception of the data */ 00704 if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00705 { 00706 return QSPI_ERROR; 00707 } 00708 00709 /* Enable write operations, command in 1 bit */ 00710 /* Enable write operations */ 00711 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00712 s_command.Instruction = WRITE_ENABLE_CMD; 00713 s_command.AddressMode = QSPI_ADDRESS_NONE; 00714 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00715 s_command.DataMode = QSPI_DATA_NONE; 00716 s_command.DummyCycles = 0; 00717 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00718 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00719 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00720 00721 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00722 { 00723 return QSPI_ERROR; 00724 } 00725 00726 /* Configure automatic polling mode to wait for write enabling */ 00727 s_config.Match = MX25L512_SR_WREN; 00728 s_config.Mask = MX25L512_SR_WREN; 00729 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00730 s_config.StatusBytesSize = 1; 00731 s_config.Interval = 0x10; 00732 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00733 00734 s_command.Instruction = READ_STATUS_REG_CMD; 00735 s_command.DataMode = QSPI_DATA_1_LINE; 00736 00737 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00738 { 00739 return QSPI_ERROR; 00740 } 00741 00742 /* Update the configuration register with new dummy cycles */ 00743 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00744 s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; 00745 s_command.AddressMode = QSPI_ADDRESS_NONE; 00746 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00747 s_command.DataMode = QSPI_DATA_1_LINE; 00748 s_command.DummyCycles = 0; 00749 s_command.NbData = 1; 00750 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00751 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00752 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00753 00754 /* Enable the Quad IO on the QSPI memory (Non-volatile bit) */ 00755 reg |= MX25L512_SR_QUADEN; 00756 00757 /* Configure the command */ 00758 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00759 { 00760 return QSPI_ERROR; 00761 } 00762 00763 /* Transmission of the data */ 00764 if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00765 { 00766 return QSPI_ERROR; 00767 } 00768 00769 /* 40ms Write Status/Configuration Register Cycle Time */ 00770 HAL_Delay( 40 ); 00771 00772 return QSPI_OK; 00773 } 00774 00775 /** 00776 * @brief This function set the QSPI memory in 4-byte address mode 00777 * @param hqspi: QSPI handle 00778 * @retval None 00779 */ 00780 static uint8_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi) 00781 { 00782 QSPI_CommandTypeDef s_command; 00783 00784 /* Initialize the command */ 00785 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00786 s_command.Instruction = ENTER_4_BYTE_ADDR_MODE_CMD; 00787 s_command.AddressMode = QSPI_ADDRESS_NONE; 00788 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00789 s_command.DataMode = QSPI_DATA_NONE; 00790 s_command.DummyCycles = 0; 00791 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00792 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00793 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00794 00795 /* Enable write operations */ 00796 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00797 { 00798 return QSPI_ERROR; 00799 } 00800 00801 /* Send the command */ 00802 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00803 { 00804 return QSPI_ERROR; 00805 } 00806 00807 /* Configure automatic polling mode to wait the memory is ready */ 00808 if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) 00809 { 00810 return QSPI_ERROR; 00811 } 00812 00813 return QSPI_OK; 00814 } 00815 00816 /** 00817 * @brief This function configure the dummy cycles on memory side. 00818 * @param hqspi: QSPI handle 00819 * @retval None 00820 */ 00821 static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi) 00822 { 00823 QSPI_CommandTypeDef s_command; 00824 uint8_t reg[2]; 00825 00826 /* Initialize the reading of status register */ 00827 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00828 s_command.Instruction = READ_STATUS_REG_CMD; 00829 s_command.AddressMode = QSPI_ADDRESS_NONE; 00830 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00831 s_command.DataMode = QSPI_DATA_4_LINES; 00832 s_command.DummyCycles = 0; 00833 s_command.NbData = 1; 00834 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00835 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00836 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00837 00838 /* Configure the command */ 00839 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00840 { 00841 return QSPI_ERROR; 00842 } 00843 00844 /* Reception of the data */ 00845 if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00846 { 00847 return QSPI_ERROR; 00848 } 00849 00850 /* Initialize the reading of configuration register */ 00851 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00852 s_command.Instruction = READ_CFG_REG_CMD; 00853 s_command.AddressMode = QSPI_ADDRESS_NONE; 00854 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00855 s_command.DataMode = QSPI_DATA_4_LINES; 00856 s_command.DummyCycles = 0; 00857 s_command.NbData = 1; 00858 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00859 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00860 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00861 00862 /* Configure the command */ 00863 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00864 { 00865 return QSPI_ERROR; 00866 } 00867 00868 /* Reception of the data */ 00869 if (HAL_QSPI_Receive(hqspi, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00870 { 00871 return QSPI_ERROR; 00872 } 00873 00874 /* Enable write operations */ 00875 if (QSPI_WriteEnable(hqspi) != QSPI_OK) 00876 { 00877 return QSPI_ERROR; 00878 } 00879 00880 /* Update the configuration register with new dummy cycles */ 00881 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00882 s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; 00883 s_command.AddressMode = QSPI_ADDRESS_NONE; 00884 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00885 s_command.DataMode = QSPI_DATA_4_LINES; 00886 s_command.DummyCycles = 0; 00887 s_command.NbData = 2; 00888 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00889 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00890 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00891 00892 /* MX25L512_DUMMY_CYCLES_READ_QUAD = 3 for 10 cycles in QPI mode */ 00893 MODIFY_REG( reg[1], MX25L512_CR_NB_DUMMY, (MX25L512_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(MX25L512_CR_NB_DUMMY))); 00894 00895 /* Configure the write volatile configuration register command */ 00896 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00897 { 00898 return QSPI_ERROR; 00899 } 00900 00901 /* Transmission of the data */ 00902 if (HAL_QSPI_Transmit(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00903 { 00904 return QSPI_ERROR; 00905 } 00906 00907 /* 40ms Write Status/Configuration Register Cycle Time */ 00908 HAL_Delay( 40 ); 00909 00910 return QSPI_OK; 00911 } 00912 00913 /** 00914 * @brief This function put QSPI memory in QPI mode (quad I/O). 00915 * @param hqspi: QSPI handle 00916 * @retval None 00917 */ 00918 static uint8_t QSPI_EnterMemory_QPI( QSPI_HandleTypeDef *hqspi ) 00919 { 00920 QSPI_CommandTypeDef s_command; 00921 QSPI_AutoPollingTypeDef s_config; 00922 00923 /* Initialize the QPI enable command */ 00924 /* QSPI memory is supported to be in SPI mode, so CMD on 1 LINE */ 00925 s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 00926 s_command.Instruction = ENTER_QUAD_CMD; 00927 s_command.AddressMode = QSPI_ADDRESS_NONE; 00928 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00929 s_command.DataMode = QSPI_DATA_NONE; 00930 s_command.DummyCycles = 0; 00931 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00932 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00933 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00934 00935 /* Send the command */ 00936 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00937 { 00938 return QSPI_ERROR; 00939 } 00940 00941 /* Configure automatic polling mode to wait the QUADEN bit=1 and WIP bit=0 */ 00942 s_config.Match = MX25L512_SR_QUADEN; 00943 s_config.Mask = MX25L512_SR_QUADEN|MX25L512_SR_WIP; 00944 s_config.MatchMode = QSPI_MATCH_MODE_AND; 00945 s_config.StatusBytesSize = 1; 00946 s_config.Interval = 0x10; 00947 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 00948 00949 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00950 s_command.Instruction = READ_STATUS_REG_CMD; 00951 s_command.DataMode = QSPI_DATA_4_LINES; 00952 00953 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00954 { 00955 return QSPI_ERROR; 00956 } 00957 00958 return QSPI_OK; 00959 } 00960 00961 /** 00962 * @brief This function put QSPI memory in SPI mode. 00963 * @param hqspi: QSPI handle 00964 * @retval None 00965 */ 00966 static uint8_t QSPI_ExitMemory_QPI( QSPI_HandleTypeDef *hqspi) 00967 { 00968 QSPI_CommandTypeDef s_command; 00969 00970 /* Initialize the QPI enable command */ 00971 /* QSPI memory is supported to be in QPI mode, so CMD on 4 LINES */ 00972 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 00973 s_command.Instruction = EXIT_QUAD_CMD; 00974 s_command.AddressMode = QSPI_ADDRESS_NONE; 00975 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 00976 s_command.DataMode = QSPI_DATA_NONE; 00977 s_command.DummyCycles = 0; 00978 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 00979 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 00980 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 00981 00982 /* Send the command */ 00983 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 00984 { 00985 return QSPI_ERROR; 00986 } 00987 00988 return QSPI_OK; 00989 } 00990 00991 /** 00992 * @brief This function configure the Output driver strength on memory side. 00993 * @param hqspi: QSPI handle 00994 * @retval None 00995 */ 00996 static uint8_t QSPI_OutDrvStrengthCfg( QSPI_HandleTypeDef *hqspi ) 00997 { 00998 QSPI_CommandTypeDef s_command; 00999 uint8_t reg[2]; 01000 01001 /* Initialize the reading of status register */ 01002 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 01003 s_command.Instruction = READ_STATUS_REG_CMD; 01004 s_command.AddressMode = QSPI_ADDRESS_NONE; 01005 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 01006 s_command.DataMode = QSPI_DATA_4_LINES; 01007 s_command.DummyCycles = 0; 01008 s_command.NbData = 1; 01009 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 01010 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 01011 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 01012 01013 /* Configure the command */ 01014 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01015 { 01016 return QSPI_ERROR; 01017 } 01018 01019 /* Reception of the data */ 01020 if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01021 { 01022 return QSPI_ERROR; 01023 } 01024 01025 /* Initialize the reading of configuration register */ 01026 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 01027 s_command.Instruction = READ_CFG_REG_CMD; 01028 s_command.AddressMode = QSPI_ADDRESS_NONE; 01029 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 01030 s_command.DataMode = QSPI_DATA_4_LINES; 01031 s_command.DummyCycles = 0; 01032 s_command.NbData = 1; 01033 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 01034 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 01035 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 01036 01037 /* Configure the command */ 01038 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01039 { 01040 return QSPI_ERROR; 01041 } 01042 01043 /* Reception of the data */ 01044 if (HAL_QSPI_Receive(hqspi, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01045 { 01046 return QSPI_ERROR; 01047 } 01048 01049 /* Enable write operations */ 01050 if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) 01051 { 01052 return QSPI_ERROR; 01053 } 01054 01055 /* Update the configuration register with new output driver strength */ 01056 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 01057 s_command.Instruction = WRITE_STATUS_CFG_REG_CMD; 01058 s_command.AddressMode = QSPI_ADDRESS_NONE; 01059 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 01060 s_command.DataMode = QSPI_DATA_4_LINES; 01061 s_command.DummyCycles = 0; 01062 s_command.NbData = 2; 01063 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 01064 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 01065 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 01066 01067 /* Set Output Strength of the QSPI memory 15 ohms */ 01068 MODIFY_REG( reg[1], MX25L512_CR_ODS, (MX25L512_CR_ODS_15 << POSITION_VAL(MX25L512_CR_ODS))); 01069 01070 /* Configure the write volatile configuration register command */ 01071 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01072 { 01073 return QSPI_ERROR; 01074 } 01075 01076 /* Transmission of the data */ 01077 if (HAL_QSPI_Transmit(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01078 { 01079 return QSPI_ERROR; 01080 } 01081 01082 return QSPI_OK; 01083 } 01084 01085 /** 01086 * @brief This function send a Write Enable and wait it is effective. 01087 * @param hqspi: QSPI handle 01088 * @retval None 01089 */ 01090 static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) 01091 { 01092 QSPI_CommandTypeDef s_command; 01093 QSPI_AutoPollingTypeDef s_config; 01094 01095 /* Enable write operations */ 01096 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 01097 s_command.Instruction = WRITE_ENABLE_CMD; 01098 s_command.AddressMode = QSPI_ADDRESS_NONE; 01099 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 01100 s_command.DataMode = QSPI_DATA_NONE; 01101 s_command.DummyCycles = 0; 01102 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 01103 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 01104 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 01105 01106 if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01107 { 01108 return QSPI_ERROR; 01109 } 01110 01111 /* Configure automatic polling mode to wait for write enabling */ 01112 s_config.Match = MX25L512_SR_WREN; 01113 s_config.Mask = MX25L512_SR_WREN; 01114 s_config.MatchMode = QSPI_MATCH_MODE_AND; 01115 s_config.StatusBytesSize = 1; 01116 s_config.Interval = 0x10; 01117 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 01118 01119 s_command.Instruction = READ_STATUS_REG_CMD; 01120 s_command.DataMode = QSPI_DATA_4_LINES; 01121 01122 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 01123 { 01124 return QSPI_ERROR; 01125 } 01126 01127 return QSPI_OK; 01128 } 01129 01130 /** 01131 * @brief This function read the SR of the memory and wait the EOP. 01132 * @param hqspi: QSPI handle 01133 * @param Timeout 01134 * @retval None 01135 */ 01136 static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) 01137 { 01138 QSPI_CommandTypeDef s_command; 01139 QSPI_AutoPollingTypeDef s_config; 01140 01141 /* Configure automatic polling mode to wait for memory ready */ 01142 s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 01143 s_command.Instruction = READ_STATUS_REG_CMD; 01144 s_command.AddressMode = QSPI_ADDRESS_NONE; 01145 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 01146 s_command.DataMode = QSPI_DATA_4_LINES; 01147 s_command.DummyCycles = 0; 01148 s_command.DdrMode = QSPI_DDR_MODE_DISABLE; 01149 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 01150 s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 01151 01152 s_config.Match = 0; 01153 s_config.Mask = MX25L512_SR_WIP; 01154 s_config.MatchMode = QSPI_MATCH_MODE_AND; 01155 s_config.StatusBytesSize = 1; 01156 s_config.Interval = 0x10; 01157 s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 01158 01159 if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK) 01160 { 01161 return QSPI_ERROR; 01162 } 01163 01164 return QSPI_OK; 01165 } 01166 /** 01167 * @} 01168 */ 01169 01170 /** 01171 * @} 01172 */ 01173 01174 /** 01175 * @} 01176 */ 01177 01178 /** 01179 * @} 01180 */ 01181 01182 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue May 30 2017 13:59:12 for STM32F723E-Discovery BSP User Manual by 1.7.6.1