/** ****************************************************************************** * @file stm32_extmem.c * @author MCD Application Team * @brief This file includes a driver for external memory support ****************************************************************************** * @attention * * Copyright (c) 2022 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. * ****************************************************************************** */ /** * @brief Macro to get memory table definition */ #define EXTMEM_C /* Includes ------------------------------------------------------------------*/ #include "stm32_extmem.h" #include "stm32_extmem_conf.h" #if EXTMEM_DRIVER_NOR_SFDP == 1 #include "nor_sfdp/stm32_sfdp_driver_api.h" #endif /* EXTMEM_DRIVER_NOR_SFDP */ #if EXTMEM_DRIVER_PSRAM == 1 #include "psram/stm32_psram_driver_api.h" #endif /* EXTMEM_DRIVER_PSRAM */ #if EXTMEM_DRIVER_SDCARD == 1 #include "sdcard/stm32_sdcard_driver_api.h" #endif /* EXTMEM_DRIVER_SDCARD */ #if EXTMEM_DRIVER_CUSTOM == 1 #include "custom/stm32_custom_driver_api.h" #endif /* EXTMEM_DRIVER_CUSTOM */ #if EXTMEM_DRIVER_USER == 1 #include "user/stm32_user_driver_api.h" #endif /* EXTMEM_DRIVER_USER */ /** * @defgroup EXTMEM_DRIVER * @{ */ /** * @} */ /** * @defgroup EXTMEM_SAL * @{ */ /** * @} */ /** * @defgroup EXTMEM * @{ */ /* Private Macros ------------------------------------------------------------*/ /** * @defgroup EXTMEM_Private_Macros External Memory Private Macros * @{ */ /** * @brief EXTMEM debug function */ /** * @brief Macro used to trace EXTMEM function calls */ #if defined(EXTMEM_DEBUG_LEVEL) && defined(EXTMEM_MACRO_DEBUG) #if EXTMEM_DEBUG_LEVEL > 0 #define EXTMEM_DEBUG(_MSG_) EXTMEM_MACRO_DEBUG(_MSG_) #if EXTMEM_DEBUG_LEVEL > 1 #define EXTMEM_FUNC_CALL() \ do \ { \ EXTMEM_DEBUG(__func__); \ EXTMEM_DEBUG("\n"); \ } while (0); #else #define EXTMEM_FUNC_CALL() #endif /* EXTMEM_DEBUG_LEVEL > 1 */ #else #define EXTMEM_DEBUG(_MSG_) #define EXTMEM_FUNC_CALL() #endif /* EXTMEM_DEBUG_LEVEL > 0 */ #else #define EXTMEM_DEBUG(_MSG_) #define EXTMEM_FUNC_CALL() #endif /* defined(EXTMEM_DEBUG_LEVEL) && defined(EXTMEM_MACRO_DEBUG) */ /** * @brief Macro used to trace EXTMEM debug information */ #define EXTMEM_DEBUG_ENDL(_STRING_) \ do \ { \ EXTMEM_DEBUG(_STRING_); \ EXTMEM_DEBUG("\n"); \ } while (0); /** * @} */ /* Private typedefs ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /* Exported variables ---------------------------------------------------------*/ /** @defgroup EXTMEM_Exported_Functions External Memory Exported Functions * @{ */ /** * @brief Initializes the external memory. * @param MemId Memory identifier. * @param ClockInput Clock input value for the memory. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_Init(uint32_t MemId, uint32_t ClockInput) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL(); /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Initialize the memory using NOR SFDP driver */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_Init(extmem_list_config[MemId].Handle, extmem_list_config[MemId].ConfigType, ClockInput, &extmem_list_config[MemId].NorSfdpObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Initialize the memory using SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_Init(extmem_list_config[MemId].Handle, &extmem_list_config[MemId].SdCardObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { /* Initialize the memory using PSRAM driver */ if (EXTMEM_DRIVER_PSRAM_OK != EXTMEM_DRIVER_PSRAM_Init(extmem_list_config[MemId].Handle, extmem_list_config[MemId].ConfigType, ClockInput, &extmem_list_config[MemId].PsramObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Initialize the memory using CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_Init(extmem_list_config[MemId].Handle, ClockInput, &extmem_list_config[MemId].CustomObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Initialize the memory using USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status; status = EXTMEM_DRIVER_USER_Init(MemId, &extmem_list_config[MemId].UserObject); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: { retr = EXTMEM_ERROR_NOTSUPPORTED; break; } case EXTMEM_DRIVER_USER_OK: { /* Nothing to do */ retr = EXTMEM_OK; break; } default: { retr = EXTMEM_ERROR_DRIVER; break; } } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Deinitializes the external memory. * @param MemId Memory identifier. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_DeInit(uint32_t MemId) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL(); /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Uninitialize the memory using NOR SFDP driver */ /* Return is always OK no need to test the returned value */ (void)EXTMEM_DRIVER_NOR_SFDP_DeInit(&extmem_list_config[MemId].NorSfdpObject); break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Uninitialize the memory using SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_DeInit(&extmem_list_config[MemId].SdCardObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { /* Uninitialize the memory using PSRAM driver */ /* Return is always OK no need to test the returned value */ (void)EXTMEM_DRIVER_PSRAM_DeInit(&extmem_list_config[MemId].PsramObject); break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Uninitialize the memory using CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_DeInit(&extmem_list_config[MemId].CustomObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Uninitialize the memory using USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status = EXTMEM_DRIVER_USER_DeInit(&extmem_list_config[MemId].UserObject); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: /* Nothing to do, the returned status is already set to EXTMEM_OK */ break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Reads data from the external memory. * @param MemId Memory identifier. * @param Address Address in memory to read from. * @param Data Pointer to buffer where read data will be stored. * @param Size Number of bytes to read. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_Read(uint32_t MemId, uint32_t Address, uint8_t *Data, uint32_t Size) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the Read operation using the NOR SFDP driver */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_Read(&extmem_list_config[MemId].NorSfdpObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Perform the Read operation using the SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_Read(&extmem_list_config[MemId].SdCardObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { retr = EXTMEM_ERROR_NOTSUPPORTED; break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the Read operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_Read(&extmem_list_config[MemId].CustomObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the Read operation using the USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status = EXTMEM_DRIVER_USER_Read(&extmem_list_config[MemId].UserObject, Address, Data, Size); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: /* Nothing to do, the returned status is already set to EXTMEM_OK */ break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Writes data to the external memory. * @param MemId Memory identifier. * @param Address Address in memory to write to. * @param Data Pointer to buffer containing data to be written. * @param Size Number of bytes to write. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_Write(uint32_t MemId, uint32_t Address, const uint8_t *Data, uint32_t Size) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the Write operation using the NOR SFDP driver */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_Write(&extmem_list_config[MemId].NorSfdpObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Perform the Write operation using the SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_Write(&extmem_list_config[MemId].SdCardObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { retr = EXTMEM_ERROR_NOTSUPPORTED; break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the Write operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_Write(&extmem_list_config[MemId].CustomObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the Write operation using the USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status = EXTMEM_DRIVER_USER_Write(&extmem_list_config[MemId].UserObject, Address, Data, Size); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Writes data to the external memory in mapped mode. * @param MemId Memory identifier. * @param Address Address in memory to write to. * @param Data Pointer to buffer (must be 32-bit aligned) containing data to be written. * @param Size Number of bytes to write. * @retval EXTMEM_StatusTypeDef Status of the operation. * * @note This function performs write operations in mapped mode and requires specific processing due * to write enable management when the memory is mapped. The operation splits the write into packets * of page size, and for each packet, performs a write before entering mapped mode. * * @note To avoid issues during this process, it is mandatory that the targeted memory area has the following * characteristics: the write region must be non-bufferable, non-shareable, and non-cacheable. */ EXTMEM_StatusTypeDef EXTMEM_WriteInMappedMode(uint32_t MemId, uint32_t Address, const uint8_t *const Data, uint32_t Size) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 /* Perform the Write in mapped mode operation using the NOR SFDP driver */ case EXTMEM_NOR_SFDP: { if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_WriteInMappedMode(&extmem_list_config[MemId].NorSfdpObject, Address, Data, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Erases a number of sectors in the external memory. * @param MemId Memory identifier. * @param Address Address in memory to start erase operation. * @param Size Number of bytes to erase. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_EraseSector(uint32_t MemId, uint32_t Address, uint32_t Size) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the Sector Erase operation using the NOR SFDP driver */ const EXTMEM_DRIVER_NOR_SFDP_ObjectTypeDef *const object = &extmem_list_config[MemId].NorSfdpObject; EXTMEM_DRIVER_NOR_SFDP_SectorTypeTypeDef sector_type = EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE1; uint32_t local_address = Address; uint32_t local_size = Size; uint32_t sector_size = (uint32_t)1u << object->sfdp_private.DriverInfo.EraseType4Size; while (local_size != 0u) { /* if address is a modulo a sector size if sector */ if ((object->sfdp_private.DriverInfo.EraseType4Size != 0u) && (local_size >= sector_size) && ((local_address % sector_size) == 0u)) { sector_type = EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE4; } else { sector_size = (uint32_t)1u << object->sfdp_private.DriverInfo.EraseType3Size; if ((object->sfdp_private.DriverInfo.EraseType3Size != 0u) && (local_size >= sector_size) && ((local_address % sector_size) == 0u)) { sector_type = EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE3; } else { sector_size = (uint32_t)1u << object->sfdp_private.DriverInfo.EraseType2Size; if ((object->sfdp_private.DriverInfo.EraseType2Size != 0u) && (local_size >= sector_size) && ((local_address % sector_size) == 0u)) { sector_type = EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE2; } else { sector_size = (uint32_t)1u << object->sfdp_private.DriverInfo.EraseType1Size; if ((object->sfdp_private.DriverInfo.EraseType1Size != 0u) && ((local_address % sector_size) == 0u)) { sector_type = EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE1; } else { retr = EXTMEM_ERROR_SECTOR_SIZE; } } } } if (retr == EXTMEM_OK) { if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_SectorErase(&extmem_list_config[MemId].NorSfdpObject, local_address, sector_type)) { retr = EXTMEM_ERROR_DRIVER; } } if (retr != EXTMEM_OK) { local_size = 0u; } else { local_address = local_address + sector_size; if (sector_size > local_size) { local_size = 0u; } else { local_size = local_size - sector_size; } } } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Perform the Sector Erase operation using the SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_EraseBlock(&extmem_list_config[MemId].SdCardObject, Address, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the Sector Erase operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_EraseSector(&extmem_list_config[MemId].CustomObject, Address, Size)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the Sector Erase operation using the USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status = EXTMEM_DRIVER_USER_EraseSector(&extmem_list_config[MemId].UserObject, Address, Size); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Erases all sectors in the external memory. * @param MemId Memory identifier. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_EraseAll(uint32_t MemId) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the Mass Erase operation using the NOR SFDP driver */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_MassErase(&extmem_list_config[MemId].NorSfdpObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD: { /* Perform the Mass Erase operation using the SD CARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_Erase(&extmem_list_config[MemId].SdCardObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM: { retr = EXTMEM_ERROR_NOTSUPPORTED; break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the Mass Erase operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_MassErase(&extmem_list_config[MemId].CustomObject)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the Mass Erase operation using the USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status = EXTMEM_DRIVER_USER_MassErase(&extmem_list_config[MemId].UserObject); switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Returns information about the external memory. * @param MemId Memory identifier. * @param Info Pointer to structure to receive memory information. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_GetInfo(uint32_t MemId, void *Info) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL() /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the Get Information operation using the NOR SFDP driver */ EXTMEM_DRIVER_NOR_SFDP_GetFlashInfo(&extmem_list_config[MemId].NorSfdpObject, (EXTMEM_NOR_SFDP_FlashInfoTypeDef *)Info); break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD : { /* Perform the Get Information operation using the SDCARD driver */ if (EXTMEM_DRIVER_SDCARD_OK != EXTMEM_DRIVER_SDCARD_GetInfo(&extmem_list_config[MemId].SdCardObject, (EXTMEM_DRIVER_SDCARD_InfoTypeDef *)Info)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the Get Information operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_GetInfo(&extmem_list_config[MemId].CustomObject, (EXTMEM_DRIVER_CUSTOM_MemInfoTypeDef *)Info)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the Get Information operation using the USER driver */ if (EXTMEM_DRIVER_USER_OK != EXTMEM_DRIVER_USER_GetInfo(&extmem_list_config[MemId].UserObject, (EXTMEM_USER_MemInfoTypeDef *)Info)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_PSRAM == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Enables or disables the memory mapped mode. * @param MemId Memory identifier. * @param State Enable or disable state (@ref EXTMEM_StateTypeDef). * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_MemoryMappedMode(uint32_t MemId, EXTMEM_StateTypeDef State) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL(); /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 case EXTMEM_NOR_SFDP: { /* Perform the memory Map operation using the NOR SFDP driver */ if (EXTMEM_ENABLE == State) { /* Start the memory mapped mode */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_Enable_MemoryMappedMode(&extmem_list_config[MemId].NorSfdpObject)) { return EXTMEM_ERROR_DRIVER; } } else { /* Stop the memory mapped mode */ if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_Disable_MemoryMappedMode(&extmem_list_config[MemId].NorSfdpObject)) { return EXTMEM_ERROR_DRIVER; } } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 */ #if EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM : { /* Perform the memory Map operation using the PSRAM driver */ if (EXTMEM_ENABLE == State) { /* Start the memory mapped mode */ if (EXTMEM_DRIVER_PSRAM_OK != EXTMEM_DRIVER_PSRAM_Enable_MemoryMappedMode(&extmem_list_config[MemId].PsramObject)) { return EXTMEM_ERROR_DRIVER; } } else { /* Stop the memory mapped mode */ if (EXTMEM_DRIVER_PSRAM_OK != EXTMEM_DRIVER_PSRAM_Disable_MemoryMappedMode(&extmem_list_config[MemId].PsramObject)) { return EXTMEM_ERROR_DRIVER; } } break; } #endif /* EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM : { /* Perform the memory Map operation using the CUSTOM driver */ if (EXTMEM_ENABLE == State) { /* Start the memory mapped mode */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_Enable_MemoryMappedMode(&extmem_list_config[MemId].CustomObject)) { return EXTMEM_ERROR_DRIVER; } } else { /* Stop the memory mapped mode */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_Disable_MemoryMappedMode(&extmem_list_config[MemId].CustomObject)) { return EXTMEM_ERROR_DRIVER; } } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER : { /* Perform the memory Map operation using the USER driver */ EXTMEM_DRIVER_USER_StatusTypeDef status; if (EXTMEM_ENABLE == State) { /* Start the memory mapped mode */ status = EXTMEM_DRIVER_USER_Enable_MemoryMappedMode(&extmem_list_config[MemId].UserObject); } else { /* Stop the memory mapped mode */ status = EXTMEM_DRIVER_USER_Disable_MemoryMappedMode(&extmem_list_config[MemId].UserObject); } switch (status) { case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; case EXTMEM_DRIVER_USER_OK: break; default: retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD : /* Functionality not supported in this driver */ retr = EXTMEM_ERROR_NOTSUPPORTED; break; #endif /* EXTMEM_DRIVER_SDCARD == 1 */ /* Unknown type of EXTMEM driver */ default: { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @brief Gets the base address of the mapped external memory. * @param MemId Memory identifier. * @param BaseAddress Pointer to variable to receive the base address. * @retval EXTMEM_StatusTypeDef Status of the operation. */ EXTMEM_StatusTypeDef EXTMEM_GetMapAddress(uint32_t MemId, uint32_t *BaseAddress) { EXTMEM_StatusTypeDef retr = EXTMEM_ERROR_INVALID_ID; EXTMEM_FUNC_CALL(); /* Check the memory ID */ if (MemId < (sizeof(extmem_list_config) / sizeof(EXTMEM_DefinitionTypeDef))) { retr = EXTMEM_OK; /* Check type of EXTMEM driver used to access memory */ switch (extmem_list_config[MemId].MemType) { #if EXTMEM_DRIVER_NOR_SFDP == 1 || EXTMEM_DRIVER_PSRAM == 1 case EXTMEM_PSRAM: case EXTMEM_NOR_SFDP: { /* Define Map address based on Instance used for memory access */ #if defined(XSPI1) if (((XSPI_HandleTypeDef *)extmem_list_config[MemId].Handle)->Instance == XSPI1) { *BaseAddress = XSPI1_BASE; } #if defined(XSPI2) else if (((XSPI_HandleTypeDef *)extmem_list_config[MemId].Handle)->Instance == XSPI2) { *BaseAddress = XSPI2_BASE; } #if defined(XSPI3) else if (((XSPI_HandleTypeDef *)extmem_list_config[MemId].Handle)->Instance == XSPI3) { *BaseAddress = XSPI3_BASE; } #endif /* XSPI3 */ #endif /* XSPI2 */ #else /* XSPI1 */ if (((XSPI_HandleTypeDef *)extmem_list_config[MemId].Handle)->Instance == OCTOSPI1) { *BaseAddress = OCTOSPI1_BASE; } #endif /* XSPI1 */ else { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_NOR_SFDP == 1 || EXTMEM_DRIVER_PSRAM == 1 */ #if EXTMEM_DRIVER_SDCARD == 1 case EXTMEM_SDCARD : { retr = EXTMEM_ERROR_NOTSUPPORTED; break; } #endif /* EXTMEM_DRIVER_SDCARD == 1 */ #if EXTMEM_DRIVER_CUSTOM == 1 case EXTMEM_CUSTOM: { /* Perform the Get Map Address operation using the CUSTOM driver */ if (EXTMEM_DRV_CUSTOM_OK != EXTMEM_DRIVER_CUSTOM_GetMapAddress(&extmem_list_config[MemId].CustomObject, BaseAddress)) { retr = EXTMEM_ERROR_DRIVER; } break; } #endif /* EXTMEM_DRIVER_CUSTOM == 1 */ #if EXTMEM_DRIVER_USER == 1 case EXTMEM_USER: { /* Perform the Get Map Address operation using the USER driver */ switch (EXTMEM_DRIVER_USER_GetMapAddress(&extmem_list_config[MemId].UserObject, BaseAddress)) { case EXTMEM_DRIVER_USER_OK: break; case EXTMEM_DRIVER_USER_NOTSUPPORTED: retr = EXTMEM_ERROR_NOTSUPPORTED; break; default : retr = EXTMEM_ERROR_DRIVER; break; } break; } #endif /* EXTMEM_DRIVER_USER == 1 */ /* Unknown type of EXTMEM driver */ default : { EXTMEM_DEBUG("\terror : unknown memory type\n"); retr = EXTMEM_ERROR_UNKNOWNMEMORY; break; } } } return retr; } /** * @} */ /** * @} */