diff options
Diffstat (limited to 'bsps/arm/stm32h7/boards/stm/stm32h757i-eval/stm32h747i_eval_qspi.c')
-rw-r--r-- | bsps/arm/stm32h7/boards/stm/stm32h757i-eval/stm32h747i_eval_qspi.c | 1088 |
1 files changed, 1088 insertions, 0 deletions
diff --git a/bsps/arm/stm32h7/boards/stm/stm32h757i-eval/stm32h747i_eval_qspi.c b/bsps/arm/stm32h7/boards/stm/stm32h757i-eval/stm32h747i_eval_qspi.c new file mode 100644 index 0000000000..6614200509 --- /dev/null +++ b/bsps/arm/stm32h7/boards/stm/stm32h757i-eval/stm32h747i_eval_qspi.c @@ -0,0 +1,1088 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/** + ****************************************************************************** + * @file stm32h747i_eval_qspi.c + * @author MCD Application Team + * @brief This file includes a standard driver for the MT25TL01G QSPI + * memory mounted on STM32H747I-EVAL board. + ****************************************************************************** + @verbatim + How To use this driver: + ----------------------- + - This driver is used to drive the MT25TL01G QSPI external + memory mounted on STM32H747I-EVAL evaluation board. + + - This driver need a specific component driver (MT25TL01G) to be included with. + + Driver description: + ------------------- + - 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. + STR and DTR transfer rates are supported. + SPI, SPI 2-IO, SPI-4IO and QPI modes are supported + + - 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 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_EraseBlock() and by + specifying the block address. You can perform an erase operation of the whole + chip by calling the function BSP_QSPI_EraseChip(). + + The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. + (see the QSPI memory data sheet) + + The function BSP_QSPI_EnableMemoryMappedMode enables the QSPI memory mapped mode + + The function BSP_QSPI_DisableMemoryMappedMode disables the QSPI memory mapped mode + + The function BSP_QSPI_ConfigFlash() allow to configure the QSPI mode and transfer rate + + Note: + -------- + Regarding the "Instance" parameter, needed for all functions, it is used to select + an QSPI instance. On the STM32H747I_EVAL board, there's one instance. Then, this + parameter should be 0. + + @endverbatim + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* + * RTEMS committer clarification comment on license above: + * + * This file comes from STM32CubeH7 project and is located here: + * https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Drivers/BSP/STM32H747I-EVAL/stm32h747i_eval_qspi.c + * + * The file root directory is: + * https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Drivers/BSP/STM32H747I-EVAL + * + * This directory contains LICENSE.md file with a following license text: + * + * Copyright 2019 STMicroelectronics. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h747i_eval_qspi.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup STM32H747I_EVAL + * @{ + */ + +/** @defgroup STM32H747I_EVAL_QSPI QSPI + * @{ + */ + +/** @defgroup STM32H747I_EVAL_QSPI_Exported_Variables Exported Variables + * @{ + */ +QSPI_HandleTypeDef hqspi; +BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER]; +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup STM32H747I_EVAL_QSPI_Private_Functions Private Functions + * @{ + */ +static void QSPI_MspInit(QSPI_HandleTypeDef *hQspi); +static void QSPI_MspDeInit(QSPI_HandleTypeDef *hSspi); +static int32_t QSPI_ResetMemory(uint32_t Instance); +static int32_t QSPI_DummyCyclesCfg(uint32_t Instance); + +/** + * @} + */ + +/** @defgroup STM32H747I_EVAL_QSPI_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief Initializes the QSPI interface. + * @param Instance QSPI Instance + * @param Init QSPI Init structure + * @retval BSP status + */ +int32_t BSP_QSPI_Init(uint32_t Instance, BSP_QSPI_Init_t *Init) +{ + int32_t ret = BSP_ERROR_NONE; + BSP_QSPI_Info_t pInfo; + MX_QSPI_Init_t qspi_init; + /* Table to handle clock prescalers: + 1: For STR mode to reach max 100Mhz + 3: For DTR mode to reach max 50Mhz + */ + static const uint32_t PrescalerTab[2] = {1, 3}; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Check if instance is already initialized */ + if(QSPI_Ctx[Instance].IsInitialized == QSPI_ACCESS_NONE) + { +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + /* Register the QSPI MSP Callbacks */ + if(QSPI_Ctx[Instance].IsMspCallbacksValid == 0UL) + { + if(BSP_QSPI_RegisterDefaultMspCallbacks(Instance) != BSP_ERROR_NONE) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + } +#else + /* Msp QSPI initialization */ + QSPI_MspInit(&hqspi); +#endif /* USE_HAL_QSPI_REGISTER_CALLBACKS */ + + if(ret == BSP_ERROR_NONE) + { + /* STM32 QSPI interface initialization */ + (void)MT25TL01G_GetFlashInfo(&pInfo); + qspi_init.ClockPrescaler = PrescalerTab[Init->TransferRate]; + qspi_init.DualFlashMode = QSPI_DUALFLASH_ENABLE; + qspi_init.FlashSize = (uint32_t)POSITION_VAL((uint32_t)pInfo.FlashSize) - 1U; + qspi_init.SampleShifting = (Init->TransferRate == BSP_QSPI_STR_TRANSFER) ? QSPI_SAMPLE_SHIFTING_HALFCYCLE : QSPI_SAMPLE_SHIFTING_NONE; + + if(MX_QSPI_Init(&hqspi, &qspi_init) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + }/* QSPI memory reset */ + else if(QSPI_ResetMemory(Instance) != BSP_ERROR_NONE) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Force Flash enter 4 Byte address mode */ + else if(MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else if(MT25TL01G_Enter4BytesAddressMode(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Configuration of the dummy cycles on QSPI memory side */ + else if(QSPI_DummyCyclesCfg(Instance) != BSP_ERROR_NONE) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + /* Configure Flash to desired mode */ + if(BSP_QSPI_ConfigFlash(Instance, Init->InterfaceMode, Init->TransferRate) != BSP_ERROR_NONE) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief De-Initializes the QSPI interface. + * @param Instance QSPI Instance + * @retval BSP status + */ +int32_t BSP_QSPI_DeInit(uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(QSPI_Ctx[Instance].IsInitialized == QSPI_ACCESS_MMP) + { + if(BSP_QSPI_DisableMemoryMappedMode(Instance) != BSP_ERROR_NONE) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + + if(ret == BSP_ERROR_NONE) + { + /* Set default QSPI_Ctx values */ + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_NONE; + QSPI_Ctx[Instance].InterfaceMode = BSP_QSPI_SPI_MODE; + QSPI_Ctx[Instance].TransferRate = BSP_QSPI_STR_TRANSFER; + QSPI_Ctx[Instance].DualFlashMode = QSPI_DUALFLASH_ENABLE; + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 0) + QSPI_MspDeInit(&hqspi); +#endif /* (USE_HAL_QSPI_REGISTER_CALLBACKS == 0) */ + + /* Call the DeInit function to reset the driver */ + if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Initializes the QSPI interface. + * @param hQspi QSPI handle + * @param Config QSPI configuration structure + * @retval BSP status + */ +__weak HAL_StatusTypeDef MX_QSPI_Init(QSPI_HandleTypeDef *hQspi, MX_QSPI_Init_t *Config) +{ + /* QSPI initialization */ + /* QSPI freq = HCLK /(1 + ClockPrescaler) Mhz */ + hQspi->Instance = QUADSPI; + hQspi->Init.ClockPrescaler = Config->ClockPrescaler; + hQspi->Init.FifoThreshold = 1; + hQspi->Init.SampleShifting = Config->SampleShifting; + hQspi->Init.FlashSize = Config->FlashSize; + hQspi->Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE; /* Min 50ns for nonRead */ + hQspi->Init.ClockMode = QSPI_CLOCK_MODE_0; + hQspi->Init.FlashID = QSPI_FLASH_ID_1; + hQspi->Init.DualFlash = Config->DualFlashMode; + + return HAL_QSPI_Init(hQspi); +} + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +/** + * @brief Default BSP QSPI Msp Callbacks + * @param Instance QSPI Instance + * @retval BSP status + */ +int32_t BSP_QSPI_RegisterDefaultMspCallbacks (uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Register MspInit/MspDeInit Callbacks */ + if(HAL_QSPI_RegisterCallback(&hqspi, HAL_QSPI_MSPINIT_CB_ID, QSPI_MspInit) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else if(HAL_QSPI_RegisterCallback(&hqspi, HAL_QSPI_MSPDEINIT_CB_ID, QSPI_MspDeInit) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else + { + QSPI_Ctx[Instance].IsMspCallbacksValid = 1U; + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief BSP QSPI Msp Callback registering + * @param Instance QSPI Instance + * @param CallBacks pointer to MspInit/MspDeInit callbacks functions + * @retval BSP status + */ +int32_t BSP_QSPI_RegisterMspCallbacks (uint32_t Instance, BSP_QSPI_Cb_t *CallBacks) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Register MspInit/MspDeInit Callbacks */ + if(HAL_QSPI_RegisterCallback(&hqspi, HAL_QSPI_MSPINIT_CB_ID, CallBacks->pMspInitCb) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else if(HAL_QSPI_RegisterCallback(&hqspi, HAL_QSPI_MSPDEINIT_CB_ID, CallBacks->pMspDeInitCb) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else + { + QSPI_Ctx[Instance].IsMspCallbacksValid = 1U; + } + } + + /* Return BSP status */ + return ret; +} +#endif /* (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) */ + +/** + * @brief Reads an amount of data from the QSPI memory. + * @param Instance QSPI instance + * @param pData Pointer to data to be read + * @param ReadAddr Read start address + * @param Size Size of data to read + * @retval BSP status + */ +int32_t BSP_QSPI_Read(uint32_t Instance, uint8_t *pData, uint32_t ReadAddr, uint32_t Size) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(QSPI_Ctx[Instance].TransferRate == BSP_QSPI_STR_TRANSFER) + { + if(MT25TL01G_ReadSTR(&hqspi, QSPI_Ctx[Instance].InterfaceMode, pData, ReadAddr, Size) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + else + { + if(MT25TL01G_ReadDTR(&hqspi, QSPI_Ctx[Instance].InterfaceMode, pData, ReadAddr, Size) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Writes an amount of data to the QSPI memory. + * @param Instance QSPI instance + * @param pData Pointer to data to be written + * @param WriteAddr Write start address + * @param Size Size of data to write + * @retval BSP status + */ +int32_t BSP_QSPI_Write(uint32_t Instance, uint8_t *pData, uint32_t WriteAddr, uint32_t Size) +{ + int32_t ret = BSP_ERROR_NONE; + uint32_t end_addr, current_size, current_addr; + uint8_t *write_data; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Calculation of the size between the write address and the end of the page */ + current_size = MT25TL01G_PAGE_SIZE - (WriteAddr % MT25TL01G_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; + write_data = pData; + + /* Perform the write page by page */ + do + { + /* Check if Flash busy ? */ + if(MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Enable write operations */ + else if(MT25TL01G_WriteEnable(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Issue page program command */ + else if(MT25TL01G_PageProgram(&hqspi, QSPI_Ctx[Instance].InterfaceMode, write_data, current_addr, current_size) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Configure automatic polling mode to wait for end of program */ + else if (MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + /* Update the address and size variables for next page programming */ + current_addr += current_size; + write_data += current_size; + current_size = ((current_addr + MT25TL01G_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MT25TL01G_PAGE_SIZE; + } + } while ((current_addr < end_addr) && (ret == BSP_ERROR_NONE)); + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Erases the specified block of the QSPI memory. + * MT25TL01G support 4K, 32K, 64K size block erase commands for each Die. + * i.e 8K, 64K, 128K at BSP level (see BSP_QSPI_Erase_t type definition) + * @param Instance QSPI instance + * @param BlockAddress Block address to erase + * @param BlockSize Erase Block size + * @retval BSP status + */ +int32_t BSP_QSPI_EraseBlock(uint32_t Instance, uint32_t BlockAddress, BSP_QSPI_Erase_t BlockSize) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Check Flash busy ? */ + if(MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Enable write operations */ + else if(MT25TL01G_WriteEnable(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + /* Issue Block Erase command */ + if(MT25TL01G_BlockErase(&hqspi, QSPI_Ctx[Instance].InterfaceMode, BlockAddress, (MT25TL01G_Erase_t)BlockSize) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Erases the entire QSPI memory. + * @param Instance QSPI instance + * @retval BSP status + */ +int32_t BSP_QSPI_EraseChip(uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Check Flash busy ? */ + if(MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Enable write operations */ + else if (MT25TL01G_WriteEnable(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + /* Issue Chip erase command */ + if(MT25TL01G_ChipErase(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Reads current status of the QSPI memory. + * If WIP != 0 then return busy. + * @param Instance QSPI instance + * @retval QSPI memory status: whether busy or not + */ +int32_t BSP_QSPI_GetStatus(uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + uint8_t reg; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(MT25TL01G_ReadStatusRegister(&hqspi, QSPI_Ctx[Instance].InterfaceMode, ®) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + /* Check the value of the register */ + if ((reg & MT25TL01G_SR_WIP) != 0U) + { + ret = BSP_ERROR_BUSY; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Return the configuration of the QSPI memory. + * @param Instance QSPI instance + * @param pInfo pointer on the configuration structure + * @retval BSP status + */ +int32_t BSP_QSPI_GetInfo(uint32_t Instance, BSP_QSPI_Info_t *pInfo) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + (void)MT25TL01G_GetFlashInfo(pInfo); + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Configure the QSPI in memory-mapped mode + * Only 1 Instance can running MMP mode. And it will lock system at this mode. + * @param Instance QSPI instance + * @retval BSP status + */ +int32_t BSP_QSPI_EnableMemoryMappedMode(uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(QSPI_Ctx[Instance].TransferRate == BSP_QSPI_STR_TRANSFER) + { + if(MT25TL01G_EnableMemoryMappedModeSTR(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else /* Update QSPI context if all operations are well done */ + { + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_MMP; + } + } + else + { + if(MT25TL01G_EnableMemoryMappedModeDTR(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else /* Update QSPI context if all operations are well done */ + { + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_MMP; + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Exit form memory-mapped mode + * Only 1 Instance can running MMP mode. And it will lock system at this mode. + * @param Instance QSPI instance + * @retval BSP status + */ +int32_t BSP_QSPI_DisableMemoryMappedMode(uint32_t Instance) +{ + uint8_t Dummy; + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(QSPI_Ctx[Instance].IsInitialized != QSPI_ACCESS_MMP) + { + ret = BSP_ERROR_QSPI_MMP_UNLOCK_FAILURE; + }/* Abort MMP back to indirect mode */ + else if(HAL_QSPI_Abort(&hqspi) != HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else + { + /* Force QSPI interface Sampling Shift to half cycle */ + hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + + if(HAL_QSPI_Init(&hqspi)!= HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + /* Dummy read for exit from Performance Enhance mode */ + else if(MT25TL01G_ReadSTR(&hqspi, QSPI_Ctx[Instance].InterfaceMode, &Dummy, 0, 1) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else /* Update QSPI context if all operations are well done */ + { + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_INDIRECT; + } + } + } + /* Return BSP status */ + return ret; +} + +/** + * @brief Get flash ID, 3 Byte + * Manufacturer ID, Memory type, Memory density + * @param Instance QSPI instance + * @param Id QSPI Identifier + * @retval BSP status + */ +int32_t BSP_QSPI_ReadID(uint32_t Instance, uint8_t *Id) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + if(MT25TL01G_ReadID(&hqspi, QSPI_Ctx[Instance].InterfaceMode, Id) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief Set Flash to desired Interface mode. And this instance becomes current instance. + * If current instance running at MMP mode then this function isn't work. + * Indirect -> Indirect + * @param Instance QSPI instance + * @param Mode QSPI mode + * @param Rate QSPI transfer rate + * @retval BSP status + */ +int32_t BSP_QSPI_ConfigFlash(uint32_t Instance, BSP_QSPI_Interface_t Mode, BSP_QSPI_Transfer_t Rate) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Check if the instance is supported */ + if(Instance >= QSPI_INSTANCES_NUMBER) + { + ret = BSP_ERROR_WRONG_PARAM; + } + else + { + /* Check if MMP mode locked ************************************************/ + if(QSPI_Ctx[Instance].IsInitialized == QSPI_ACCESS_MMP) + { + ret = BSP_ERROR_QSPI_MMP_LOCK_FAILURE; + } + else + { + /* Setup MCU transfer rate setting ***************************************************/ + hqspi.Init.SampleShifting = (Rate == BSP_QSPI_STR_TRANSFER) ? QSPI_SAMPLE_SHIFTING_HALFCYCLE : QSPI_SAMPLE_SHIFTING_NONE; + + if(HAL_QSPI_Init(&hqspi)!= HAL_OK) + { + ret = BSP_ERROR_PERIPH_FAILURE; + } + else + { + /* Setup Flash interface ***************************************************/ + switch(QSPI_Ctx[Instance].InterfaceMode) + { + case MT25TL01G_QPI_MODE : /* 4-4-4 commands */ + if(Mode != MT25TL01G_QPI_MODE) + { + if(MT25TL01G_ExitQPIMode(&hqspi) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + break; + + case BSP_QSPI_SPI_MODE : /* 1-1-1 commands, Power on H/W default setting */ + case BSP_QSPI_SPI_2IO_MODE : /* 1-2-2 read commands */ + case BSP_QSPI_SPI_4IO_MODE : /* 1-4-4 read commands */ + default : + if(Mode == MT25TL01G_QPI_MODE) + { + if(MT25TL01G_EnterQPIMode(&hqspi) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + } + break; + } + + /* Update QSPI context if all operations are well done */ + if(ret == BSP_ERROR_NONE) + { + /* Update current status parameter *****************************************/ + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_INDIRECT; + QSPI_Ctx[Instance].InterfaceMode = Mode; + QSPI_Ctx[Instance].TransferRate = Rate; + } + } + } + } + + /* Return BSP status */ + return ret; +} + +/** + * @} + */ + +/** @defgroup STM32H747I_EVAL_QSPI_Private_Functions Private Functions + * @{ + */ + +/** + * @brief QSPI MSP Initialization + * @param hQspi : QSPI handle + * This function configures the hardware resources used in this example: + * - Peripheral's clock enable + * - Peripheral's GPIO Configuration + * - NVIC configuration for QSPI interrupt + * @retval None + */ +static void QSPI_MspInit(QSPI_HandleTypeDef *hQspi) +{ + GPIO_InitTypeDef gpio_init_structure; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(hQspi); + + /*##-1- Enable peripherals and GPIO Clocks #################################*/ + /* Enable the QuadSPI memory interface clock */ + QSPI_CLK_ENABLE(); + /* Reset the QuadSPI memory interface */ + QSPI_FORCE_RESET(); + QSPI_RELEASE_RESET(); + /* Enable GPIO clocks */ + QSPI_CLK_GPIO_CLK_ENABLE(); + QSPI_BK1_CS_GPIO_CLK_ENABLE(); + QSPI_BK1_D0_GPIO_CLK_ENABLE(); + QSPI_BK1_D1_GPIO_CLK_ENABLE(); + QSPI_BK1_D2_GPIO_CLK_ENABLE(); + QSPI_BK1_D3_GPIO_CLK_ENABLE(); + + QSPI_BK2_CS_GPIO_CLK_ENABLE(); + QSPI_BK2_D0_GPIO_CLK_ENABLE(); + QSPI_BK2_D1_GPIO_CLK_ENABLE(); + QSPI_BK2_D2_GPIO_CLK_ENABLE(); + QSPI_BK2_D3_GPIO_CLK_ENABLE(); + + /*##-2- Configure peripheral GPIO ##########################################*/ + /* QSPI CLK GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_CLK_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure); + + /* QSPI CS GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_BK1_CS_PIN; + gpio_init_structure.Pull = GPIO_PULLUP; + gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(QSPI_BK1_CS_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = QSPI_BK2_CS_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Pull = GPIO_PULLUP; + gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(QSPI_BK2_CS_GPIO_PORT, &gpio_init_structure); + + /* QSPI D0 GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_BK1_D0_PIN; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(QSPI_BK1_D0_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = QSPI_BK2_D0_PIN; + gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(QSPI_BK2_D0_GPIO_PORT, &gpio_init_structure); + + /* QSPI D1 GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_BK1_D1_PIN; + gpio_init_structure.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(QSPI_BK1_D1_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = QSPI_BK2_D1_PIN; + gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(QSPI_BK2_D1_GPIO_PORT, &gpio_init_structure); + + /* QSPI D2 GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_BK1_D2_PIN; + gpio_init_structure.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(QSPI_BK1_D2_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = QSPI_BK2_D2_PIN; + HAL_GPIO_Init(QSPI_BK2_D2_GPIO_PORT, &gpio_init_structure); + + /* QSPI D3 GPIO pin configuration */ + gpio_init_structure.Pin = QSPI_BK1_D3_PIN; + HAL_GPIO_Init(QSPI_BK1_D3_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = QSPI_BK2_D3_PIN; + HAL_GPIO_Init(QSPI_BK2_D3_GPIO_PORT, &gpio_init_structure); + + /*##-3- Configure the NVIC for QSPI #########################################*/ + /* NVIC configuration for QSPI interrupt */ + HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0); + HAL_NVIC_EnableIRQ(QUADSPI_IRQn); +} + +/** + * @brief QSPI MSP De-Initialization + * @param hQspi QSPI handle + * This function frees the hardware resources used in this example: + * - Disable the Peripheral's clock + * - Revert GPIO and NVIC configuration to their default state + * @retval None + */ +static void QSPI_MspDeInit(QSPI_HandleTypeDef *hQspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hQspi); + + /*##-2- Disable peripherals and GPIO Clocks ################################*/ + /* De-Configure QSPI pins */ + HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN); + HAL_GPIO_DeInit(QSPI_BK1_CS_GPIO_PORT, QSPI_BK1_CS_PIN); + HAL_GPIO_DeInit(QSPI_BK1_D0_GPIO_PORT, QSPI_BK1_D0_PIN); + HAL_GPIO_DeInit(QSPI_BK1_D1_GPIO_PORT, QSPI_BK1_D1_PIN); + HAL_GPIO_DeInit(QSPI_BK1_D2_GPIO_PORT, QSPI_BK1_D2_PIN); + HAL_GPIO_DeInit(QSPI_BK1_D3_GPIO_PORT, QSPI_BK1_D3_PIN); + + HAL_GPIO_DeInit(QSPI_BK2_CS_GPIO_PORT, QSPI_BK2_CS_PIN); + HAL_GPIO_DeInit(QSPI_BK2_D0_GPIO_PORT, QSPI_BK2_D0_PIN); + HAL_GPIO_DeInit(QSPI_BK2_D1_GPIO_PORT, QSPI_BK2_D1_PIN); + HAL_GPIO_DeInit(QSPI_BK2_D2_GPIO_PORT, QSPI_BK2_D2_PIN); + HAL_GPIO_DeInit(QSPI_BK2_D3_GPIO_PORT, QSPI_BK2_D3_PIN); + + /*##-3- Reset peripherals ##################################################*/ + /* Reset the QuadSPI memory interface */ + QSPI_FORCE_RESET(); + QSPI_RELEASE_RESET(); + + /* Disable the QuadSPI memory interface clock */ + QSPI_CLK_DISABLE(); +} + +/** + * @brief This function reset the QSPI Flash memory. + * Fore QPI+SPI reset to avoid system come from unknown status. + * Flash accept 1-1-1, 1-1-2, 1-2-2 commands after reset. + * @param Instance QSPI instance + * @retval BSP status + */ +static int32_t QSPI_ResetMemory(uint32_t Instance) +{ + int32_t ret = BSP_ERROR_NONE; + + /* Send RESET ENABLE command in QPI mode (QUAD I/Os, 4-4-4) */ + if(MT25TL01G_ResetEnable(&hqspi, MT25TL01G_QPI_MODE) != MT25TL01G_OK) + { + ret =BSP_ERROR_COMPONENT_FAILURE; + }/* Send RESET memory command in QPI mode (QUAD I/Os, 4-4-4) */ + else if(MT25TL01G_ResetMemory(&hqspi, MT25TL01G_QPI_MODE) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Wait Flash ready */ + else if(MT25TL01G_AutoPollingMemReady(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Send RESET ENABLE command in SPI mode (1-1-1) */ + else if(MT25TL01G_ResetEnable(&hqspi, BSP_QSPI_SPI_MODE) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + }/* Send RESET memory command in SPI mode (1-1-1) */ + else if(MT25TL01G_ResetMemory(&hqspi, BSP_QSPI_SPI_MODE) != MT25TL01G_OK) + { + ret = BSP_ERROR_COMPONENT_FAILURE; + } + else + { + QSPI_Ctx[Instance].IsInitialized = QSPI_ACCESS_INDIRECT; /* After reset S/W setting to indirect access */ + QSPI_Ctx[Instance].InterfaceMode = BSP_QSPI_SPI_MODE; /* After reset H/W back to SPI mode by default */ + QSPI_Ctx[Instance].TransferRate = BSP_QSPI_STR_TRANSFER; /* After reset S/W setting to STR mode */ + + } + + /* Return BSP status */ + return ret; +} + +/** + * @brief This function configure the dummy cycles on memory side. + * Dummy cycle bit locate in Configuration Register[7:6] + * @param Instance QSPI instance + * @retval BSP status + */ +static int32_t QSPI_DummyCyclesCfg(uint32_t Instance) +{ + int32_t ret= BSP_ERROR_NONE; + QSPI_CommandTypeDef s_command; + uint16_t reg=0; + + /* Initialize the read volatile configuration register command */ + s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; + s_command.Instruction = MT25TL01G_READ_VOL_CFG_REG_CMD; + s_command.AddressMode = QSPI_ADDRESS_NONE; + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.DummyCycles = 0; + s_command.NbData = 2; + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return BSP_ERROR_COMPONENT_FAILURE; + } + + /* Reception of the data */ + if (HAL_QSPI_Receive(&hqspi, (uint8_t *)(®), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return BSP_ERROR_COMPONENT_FAILURE; + } + + /* Enable write operations */ + if (MT25TL01G_WriteEnable(&hqspi, QSPI_Ctx[Instance].InterfaceMode) != MT25TL01G_OK) + { + return BSP_ERROR_COMPONENT_FAILURE; + } + + /* Update volatile configuration register (with new dummy cycles) */ + s_command.Instruction = MT25TL01G_WRITE_VOL_CFG_REG_CMD; + MODIFY_REG(reg, 0xF0F0, ((MT25TL01G_DUMMY_CYCLES_READ_QUAD << 4) | + (MT25TL01G_DUMMY_CYCLES_READ_QUAD << 12))); + + /* Configure the write volatile configuration register command */ + if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return BSP_ERROR_COMPONENT_FAILURE; + } + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(&hqspi, (uint8_t *)(®), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return BSP_ERROR_COMPONENT_FAILURE; + } + + /* Return BSP status */ + return ret; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ |