You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1133 lines
34 KiB
1133 lines
34 KiB
/** |
|
****************************************************************************** |
|
* @file stm32l496g_discovery_qspi.c |
|
* @author MCD Application Team |
|
* @brief This file includes a standard driver for the MX25R6435F QSPI |
|
* memory mounted on STM32L496G-Discovery board. |
|
@verbatim |
|
============================================================================== |
|
##### How to use this driver ##### |
|
============================================================================== |
|
[..] |
|
(#) This driver is used to drive the MX25R6435F QSPI external |
|
memory mounted on STM32L496G-DISCO evaluation board. |
|
|
|
(#) This driver need a specific component driver (MX25R6435F) to be included with. |
|
|
|
(#) Initialization steps: |
|
(++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This |
|
function includes the MSP layer hardware resources initialization and the |
|
QSPI interface with the external memory. The BSP_QSPI_DeInit() can be used |
|
to deactivate the QSPI interface. |
|
|
|
(#) QSPI memory operations |
|
(++) QSPI memory can be accessed with read/write operations once it is |
|
initialized. |
|
Read/write operation can be performed with AHB access using the functions |
|
BSP_QSPI_Read()/BSP_QSPI_Write(). |
|
(++) The function to the QSPI memory in memory-mapped mode is possible after |
|
the call of the function BSP_QSPI_EnableMemoryMappedMode(). |
|
(++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory. |
|
(see the QSPI memory data sheet) |
|
(++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by |
|
specifying the block address. You can perform an erase operation of the whole |
|
chip by calling the function BSP_QSPI_Erase_Chip(). |
|
(++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. |
|
(see the QSPI memory data sheet) |
|
(++) Perform erase sector operation using the function BSP_QSPI_Erase_Sector() |
|
which is not blocking. So the function BSP_QSPI_GetStatus() should be used |
|
to check if the memory is busy, and the functions BSP_QSPI_SuspendErase()/ |
|
BSP_QSPI_ResumeErase() can be used to perform other operations during the |
|
sector erase. |
|
(++) Deep power down of the QSPI memory is managed with the call of the functions |
|
BSP_QSPI_EnterDeepPowerDown()/BSP_QSPI_LeaveDeepPowerDown() |
|
@endverbatim |
|
****************************************************************************** |
|
* @attention |
|
* |
|
* <h2><center>© Copyright (c) 2017 STMicroelectronics. |
|
* All rights reserved.</center></h2> |
|
* |
|
* This software component is licensed by ST under BSD 3-Clause license, |
|
* the "License"; You may not use this file except in compliance with the |
|
* License. You may obtain a copy of the License at: |
|
* opensource.org/licenses/BSD-3-Clause |
|
* |
|
****************************************************************************** |
|
*/ |
|
|
|
/* Includes ------------------------------------------------------------------*/ |
|
#include "stm32l496g_discovery_qspi.h" |
|
|
|
/** @addtogroup BSP |
|
* @{ |
|
*/ |
|
|
|
/** @addtogroup STM32L496G_DISCOVERY |
|
* @{ |
|
*/ |
|
|
|
/** @defgroup STM32L496G_DISCOVERY_QSPI STM32L496G-DISCOVERY QSPI |
|
* @{ |
|
*/ |
|
|
|
/* Private constants --------------------------------------------------------*/ |
|
/** @defgroup STM32L496G_DISCOVERY_QSPI_Private_Constants Private Constants |
|
* @{ |
|
*/ |
|
#define QSPI_QUAD_DISABLE 0x0 |
|
#define QSPI_QUAD_ENABLE 0x1 |
|
|
|
#define QSPI_HIGH_PERF_DISABLE 0x0 |
|
#define QSPI_HIGH_PERF_ENABLE 0x1 |
|
/** |
|
* @} |
|
*/ |
|
/* Private variables ---------------------------------------------------------*/ |
|
|
|
/** @defgroup STM32L496G_DISCOVERY_QSPI_Private_Variables Private Variables |
|
* @{ |
|
*/ |
|
QSPI_HandleTypeDef QSPIHandle; |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
|
|
/* Private functions ---------------------------------------------------------*/ |
|
|
|
/** @defgroup STM32L496G_DISCOVERY_QSPI_Private_Functions Private Functions |
|
* @{ |
|
*/ |
|
static void QSPI_MspInit(void); |
|
static void QSPI_MspDeInit(void); |
|
static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi); |
|
static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi); |
|
static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout); |
|
static uint8_t QSPI_QuadMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation); |
|
static uint8_t QSPI_HighPerfMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation); |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/* Exported functions ---------------------------------------------------------*/ |
|
|
|
/** @addtogroup STM32L496G_DISCOVERY_QSPI_Exported_Functions |
|
* @{ |
|
*/ |
|
|
|
/** |
|
* @brief Initializes the QSPI interface. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_Init(void) |
|
{ |
|
QSPIHandle.Instance = QUADSPI; |
|
|
|
/* Call the DeInit function to reset the driver */ |
|
if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* System level initialization */ |
|
QSPI_MspInit(); |
|
|
|
/* QSPI initialization */ |
|
QSPIHandle.Init.ClockPrescaler = 2; /* QSPI clock = 80MHz / (ClockPrescaler+1) = 26.67MHz */ |
|
QSPIHandle.Init.FifoThreshold = 4; |
|
QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; |
|
QSPIHandle.Init.FlashSize = POSITION_VAL(MX25R6435F_FLASH_SIZE) - 1; |
|
QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; |
|
QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; |
|
|
|
if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* QSPI memory reset */ |
|
if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_NOT_SUPPORTED; |
|
} |
|
|
|
/* QSPI quad enable */ |
|
if (QSPI_QuadMode(&QSPIHandle, QSPI_QUAD_ENABLE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* High performance mode enable */ |
|
if (QSPI_HighPerfMode(&QSPIHandle, QSPI_HIGH_PERF_ENABLE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Re-configure the clock for the high performance mode */ |
|
QSPIHandle.Init.ClockPrescaler = 1; /* QSPI clock = 80MHz / (ClockPrescaler+1) = 40MHz */ |
|
|
|
if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief De-Initializes the QSPI interface. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_DeInit(void) |
|
{ |
|
QSPIHandle.Instance = QUADSPI; |
|
|
|
/* Call the DeInit function to reset the driver */ |
|
if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* System level De-initialization */ |
|
QSPI_MspDeInit(); |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Reads an amount of data from the QSPI memory. |
|
* @param pData : Pointer to data to be read |
|
* @param ReadAddr : Read start address |
|
* @param Size : Size of data to read |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the read command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = QUAD_INOUT_READ_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_4_LINES; |
|
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; |
|
sCommand.Address = ReadAddr; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
|
sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; |
|
sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; |
|
sCommand.DataMode = QSPI_DATA_4_LINES; |
|
sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; |
|
sCommand.NbData = Size; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Configure the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Reception of the data */ |
|
if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Writes an amount of data to the QSPI memory. |
|
* @param pData : Pointer to data to be written |
|
* @param WriteAddr : Write start address |
|
* @param Size : Size of data to write |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_Write(uint8_t *pData, uint32_t WriteAddr, uint32_t Size) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
uint32_t end_addr, current_size, current_addr; |
|
|
|
/* Calculation of the size between the write address and the end of the page */ |
|
current_size = MX25R6435F_PAGE_SIZE - (WriteAddr % MX25R6435F_PAGE_SIZE); |
|
|
|
/* Check if the size of the data is less than the remaining place in the page */ |
|
if (current_size > Size) |
|
{ |
|
current_size = Size; |
|
} |
|
|
|
/* Initialize the address variables */ |
|
current_addr = WriteAddr; |
|
end_addr = WriteAddr + Size; |
|
|
|
/* Initialize the program command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = QUAD_PAGE_PROG_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_4_LINES; |
|
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_4_LINES; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Perform the write page by page */ |
|
do |
|
{ |
|
sCommand.Address = current_addr; |
|
sCommand.NbData = current_size; |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Transmission of the data */ |
|
if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure automatic polling mode to wait for end of program */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Update the address and size variables for next page programming */ |
|
current_addr += current_size; |
|
pData += current_size; |
|
current_size = ((current_addr + MX25R6435F_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25R6435F_PAGE_SIZE; |
|
} |
|
while (current_addr < end_addr); |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Erases the specified block of the QSPI memory. |
|
* @param BlockAddress : Block address to erase |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = BLOCK_ERASE_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_1_LINE; |
|
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; |
|
sCommand.Address = BlockAddress; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure automatic polling mode to wait for end of erase */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25R6435F_BLOCK_ERASE_MAX_TIME) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Erases the specified sector of the QSPI memory. |
|
* @param Sector : Sector address to erase (0 to 255) |
|
* @retval QSPI memory status |
|
* @note This function is non blocking meaning that sector erase |
|
* operation is started but not completed when the function |
|
* returns. Application has to call BSP_QSPI_GetStatus() |
|
* to know when the device is available again (i.e. erase operation |
|
* completed). |
|
*/ |
|
uint8_t BSP_QSPI_Erase_Sector(uint32_t Sector) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
if (Sector >= (uint32_t)(MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE)) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = SECTOR_ERASE_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_1_LINE; |
|
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; |
|
sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Erases the entire QSPI memory. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_Erase_Chip(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = CHIP_ERASE_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure automatic polling mode to wait for end of erase */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25R6435F_CHIP_ERASE_MAX_TIME) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Reads current status of the QSPI memory. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_GetStatus(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
uint8_t reg; |
|
|
|
/* Initialize the read security register command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = READ_SEC_REG_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_1_LINE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.NbData = 1; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Configure the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Reception of the data */ |
|
if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Check the value of the register */ |
|
if ((reg & (MX25R6435F_SECR_P_FAIL | MX25R6435F_SECR_E_FAIL)) != 0) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
else if ((reg & (MX25R6435F_SECR_PSB | MX25R6435F_SECR_ESB)) != 0) |
|
{ |
|
return QSPI_SUSPENDED; |
|
} |
|
|
|
/* Initialize the read status register command */ |
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
|
|
/* Configure the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Reception of the data */ |
|
if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Check the value of the register */ |
|
if ((reg & MX25R6435F_SR_WIP) != 0) |
|
{ |
|
return QSPI_BUSY; |
|
} |
|
else |
|
{ |
|
return QSPI_OK; |
|
} |
|
} |
|
|
|
/** |
|
* @brief Return the configuration of the QSPI memory. |
|
* @param pInfo : pointer on the configuration structure |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo) |
|
{ |
|
/* Configure the structure with the memory configuration */ |
|
pInfo->FlashSize = MX25R6435F_FLASH_SIZE; |
|
pInfo->EraseSectorSize = MX25R6435F_SECTOR_SIZE; |
|
pInfo->EraseSectorsNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE); |
|
pInfo->ProgPageSize = MX25R6435F_PAGE_SIZE; |
|
pInfo->ProgPagesNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_PAGE_SIZE); |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief Configure the QSPI in memory-mapped mode |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_EnableMemoryMappedMode(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
QSPI_MemoryMappedTypeDef sMemMappedCfg; |
|
|
|
/* Configure the command for the read instruction */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = QUAD_INOUT_READ_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_4_LINES; |
|
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
|
sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; |
|
sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; |
|
sCommand.DataMode = QSPI_DATA_4_LINES; |
|
sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Configure the memory mapped mode */ |
|
sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; |
|
|
|
if (HAL_QSPI_MemoryMapped(&QSPIHandle, &sCommand, &sMemMappedCfg) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function suspends an ongoing erase command. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_SuspendErase(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Check whether the device is busy (erase operation is |
|
in progress). |
|
*/ |
|
if (BSP_QSPI_GetStatus() == QSPI_BUSY) |
|
{ |
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) |
|
{ |
|
return QSPI_OK; |
|
} |
|
|
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function resumes a paused erase command. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_ResumeErase(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Check whether the device is in suspended state */ |
|
if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) |
|
{ |
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = PROG_ERASE_RESUME_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* |
|
When this command is executed, the status register write in progress bit is set to 1, and |
|
the flag status register program erase controller bit is set to 0. This command is ignored |
|
if the device is not in a suspended state. |
|
*/ |
|
|
|
if (BSP_QSPI_GetStatus() == QSPI_BUSY) |
|
{ |
|
return QSPI_OK; |
|
} |
|
|
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function enter the QSPI memory in deep power down mode. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_EnterDeepPowerDown(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the deep power down command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = DEEP_POWER_DOWN_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* --- Memory takes 10us max to enter deep power down --- */ |
|
/* --- At least 30us should be respected before leaving deep power down --- */ |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function leave the QSPI memory from deep power down mode. |
|
* @retval QSPI memory status |
|
*/ |
|
uint8_t BSP_QSPI_LeaveDeepPowerDown(void) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the erase command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = NO_OPERATION_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* --- A NOP command is sent to the memory, as the nCS should be low for at least 20 ns --- */ |
|
/* --- Memory takes 35us min to leave deep power down --- */ |
|
|
|
return QSPI_OK; |
|
} |
|
/** |
|
* @} |
|
*/ |
|
|
|
/** @addtogroup STM32L496G_DISCOVERY_QSPI_Private_Functions |
|
* @{ |
|
*/ |
|
|
|
/** |
|
* @brief Initializes the QSPI MSP. |
|
* @retval None |
|
*/ |
|
static void QSPI_MspInit(void) |
|
{ |
|
GPIO_InitTypeDef GPIO_InitStruct; |
|
|
|
/* Enable the QuadSPI memory interface clock */ |
|
__HAL_RCC_QSPI_CLK_ENABLE(); |
|
|
|
/* Reset the QuadSPI memory interface */ |
|
__HAL_RCC_QSPI_FORCE_RESET(); |
|
__HAL_RCC_QSPI_RELEASE_RESET(); |
|
|
|
/* Enable GPIO clocks */ |
|
__HAL_RCC_GPIOA_CLK_ENABLE(); |
|
__HAL_RCC_GPIOB_CLK_ENABLE(); |
|
|
|
/* QSPI CS GPIO pin configuration */ |
|
GPIO_InitStruct.Pin = GPIO_PIN_11; |
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; |
|
GPIO_InitStruct.Pull = GPIO_PULLUP; |
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; |
|
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; |
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); |
|
|
|
/* QSPI CLK, D0, D1, D2 and D3 GPIO pins configuration */ |
|
GPIO_InitStruct.Pin = (GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7); |
|
GPIO_InitStruct.Pull = GPIO_NOPULL; |
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); |
|
|
|
GPIO_InitStruct.Pin = (GPIO_PIN_0 | GPIO_PIN_1); |
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); |
|
} |
|
|
|
/** |
|
* @brief De-Initializes the QSPI MSP. |
|
* @retval None |
|
*/ |
|
static void QSPI_MspDeInit(void) |
|
{ |
|
GPIO_InitTypeDef GPIO_InitStruct; |
|
|
|
/* QSPI CLK, CS, D0-D3 GPIO pins de-configuration */ |
|
|
|
__HAL_RCC_GPIOA_CLK_ENABLE(); |
|
__HAL_RCC_GPIOB_CLK_ENABLE(); |
|
|
|
HAL_GPIO_DeInit(GPIOA, (GPIO_PIN_6 | GPIO_PIN_7)); |
|
HAL_GPIO_DeInit(GPIOB, (GPIO_PIN_0 | GPIO_PIN_1)); |
|
|
|
/* Set GPIOB pin 11 in pull up mode (optimum default setting) */ |
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; |
|
GPIO_InitStruct.Pin = GPIO_PIN_11; |
|
GPIO_InitStruct.Pull = GPIO_NOPULL; |
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; |
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); |
|
|
|
/* Set GPIOA pin 3 in no pull, low state (optimum default setting) */ |
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP ; |
|
GPIO_InitStruct.Pull = GPIO_NOPULL; |
|
GPIO_InitStruct.Pin = GPIO_PIN_3; |
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); |
|
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); |
|
|
|
/* Reset the QuadSPI memory interface */ |
|
__HAL_RCC_QSPI_FORCE_RESET(); |
|
__HAL_RCC_QSPI_RELEASE_RESET(); |
|
|
|
/* Disable the QuadSPI memory interface clock */ |
|
__HAL_RCC_QSPI_CLK_DISABLE(); |
|
} |
|
|
|
/** |
|
* @brief This function reset the QSPI memory. |
|
* @param hqspi : QSPI handle |
|
* @retval None |
|
*/ |
|
static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
|
|
/* Initialize the reset enable command */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = RESET_ENABLE_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
/* Send the command */ |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Send the reset memory command */ |
|
sCommand.Instruction = RESET_MEMORY_CMD; |
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure automatic polling mode to wait the memory is ready */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function send a Write Enable and wait it is effective. |
|
* @param hqspi : QSPI handle |
|
* @retval None |
|
*/ |
|
static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
QSPI_AutoPollingTypeDef sConfig; |
|
|
|
/* Enable write operations */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = WRITE_ENABLE_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_NONE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Configure automatic polling mode to wait for write enabling */ |
|
sConfig.Match = MX25R6435F_SR_WEL; |
|
sConfig.Mask = MX25R6435F_SR_WEL; |
|
sConfig.MatchMode = QSPI_MATCH_MODE_AND; |
|
sConfig.StatusBytesSize = 1; |
|
sConfig.Interval = 0x10; |
|
sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; |
|
|
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
sCommand.DataMode = QSPI_DATA_1_LINE; |
|
|
|
if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function read the SR of the memory and wait the EOP. |
|
* @param hqspi : QSPI handle |
|
* @param Timeout : Timeout for auto-polling |
|
* @retval None |
|
*/ |
|
static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
QSPI_AutoPollingTypeDef sConfig; |
|
|
|
/* Configure automatic polling mode to wait for memory ready */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_1_LINE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
sConfig.Match = 0; |
|
sConfig.Mask = MX25R6435F_SR_WIP; |
|
sConfig.MatchMode = QSPI_MATCH_MODE_AND; |
|
sConfig.StatusBytesSize = 1; |
|
sConfig.Interval = 0x10; |
|
sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; |
|
|
|
if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, Timeout) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function enables/disables the Quad mode of the memory. |
|
* @param hqspi : QSPI handle |
|
* @param Operation : QSPI_QUAD_ENABLE or QSPI_QUAD_DISABLE mode |
|
* @retval None |
|
*/ |
|
static uint8_t QSPI_QuadMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
uint8_t reg; |
|
|
|
/* Read status register */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_1_LINE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.NbData = 1; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Activate/deactivate the Quad mode */ |
|
if (Operation == QSPI_QUAD_ENABLE) |
|
{ |
|
SET_BIT(reg, MX25R6435F_SR_QE); |
|
} |
|
else |
|
{ |
|
CLEAR_BIT(reg, MX25R6435F_SR_QE); |
|
} |
|
|
|
sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Transmit(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Wait that memory is ready */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Check the configuration has been correctly done */ |
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if ((((reg & MX25R6435F_SR_QE) == 0) && (Operation == QSPI_QUAD_ENABLE)) || |
|
(((reg & MX25R6435F_SR_QE) != 0) && (Operation == QSPI_QUAD_DISABLE))) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @brief This function enables/disables the high performance mode of the memory. |
|
* @param hqspi : QSPI handle |
|
* @param Operation : QSPI_HIGH_PERF_ENABLE or QSPI_HIGH_PERF_DISABLE high performance mode |
|
* @retval None |
|
*/ |
|
static uint8_t QSPI_HighPerfMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation) |
|
{ |
|
QSPI_CommandTypeDef sCommand; |
|
uint8_t reg[3]; |
|
|
|
/* Read status register */ |
|
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
|
sCommand.Instruction = READ_STATUS_REG_CMD; |
|
sCommand.AddressMode = QSPI_ADDRESS_NONE; |
|
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
|
sCommand.DataMode = QSPI_DATA_1_LINE; |
|
sCommand.DummyCycles = 0; |
|
sCommand.NbData = 1; |
|
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; |
|
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
|
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Receive(&QSPIHandle, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Read configuration registers */ |
|
sCommand.Instruction = READ_CFG_REG_CMD; |
|
sCommand.NbData = 2; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Receive(&QSPIHandle, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Enable write operations */ |
|
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Activate/deactivate the Quad mode */ |
|
if (Operation == QSPI_HIGH_PERF_ENABLE) |
|
{ |
|
SET_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); |
|
} |
|
else |
|
{ |
|
CLEAR_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); |
|
} |
|
|
|
sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; |
|
sCommand.NbData = 3; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Transmit(&QSPIHandle, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Wait that memory is ready */ |
|
if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
/* Check the configuration has been correctly done */ |
|
sCommand.Instruction = READ_CFG_REG_CMD; |
|
sCommand.NbData = 2; |
|
|
|
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if (HAL_QSPI_Receive(&QSPIHandle, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
if ((((reg[1] & MX25R6435F_CR2_LH_SWITCH) == 0) && (Operation == QSPI_HIGH_PERF_ENABLE)) || |
|
(((reg[1] & MX25R6435F_CR2_LH_SWITCH) != 0) && (Operation == QSPI_HIGH_PERF_DISABLE))) |
|
{ |
|
return QSPI_ERROR; |
|
} |
|
|
|
return QSPI_OK; |
|
} |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
|
|
|
|