Files
CelloEffects/Middlewares/ST/STM32_ExtMem_Manager/sal/stm32_sal_xspi.c
2026-10-18 14:06:40 +02:00

1246 lines
41 KiB
C

/**
******************************************************************************
* @file stm32_sal_xspi.c
* @author MCD Application Team
* @brief This file implements the software adaptation layer for XSPI.
******************************************************************************
* @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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32_extmem.h"
#include "stm32_extmem_conf.h"
#if EXTMEM_SAL_XSPI_DEBUG_LEVEL != 0 && defined(EXTMEM_MACRO_DEBUG)
#include <stdio.h>
#endif /* EXTMEM_SAL_XSPI_DEBUG_LEVEL != 0 && EXTMEM_MACRO_DEBUG */
#if EXTMEM_SAL_XSPI == 1
#include "stm32_sal_xspi_type.h"
#include "stm32_sal_xspi_api.h"
/** @defgroup SAL_XSPI SAL_XSPI : Software adaptation layer for XSPI
* @ingroup EXTMEM_SAL
* @{
*/
/* Private Macros ------------------------------------------------------------*/
/** @defgroup SAL_XSPI_Private_Macros SAL XSPI Private Macros
* @{
*/
#if EXTMEM_SAL_XSPI_DEBUG_LEVEL == 0 || !defined(EXTMEM_MACRO_DEBUG)
#define DEBUG_PARAM_BEGIN()
#define DEBUG_PARAM_DATA(_STR_)
#define DEBUG_PARAM_INT(_INT_ )
#define DEBUG_PARAM_INTD(_INT_ )
#define DEBUG_PARAM_END()
#define DEBUG_AUTOPOLLING(_DR_,_MVAL_,_MMASK_)
#define STR_PHY_LINK(_PHY_)
#else
/**
* @brief Trace header macro.
*/
#define DEBUG_PARAM_BEGIN() EXTMEM_MACRO_DEBUG("\t\tSALXSPI::");
const uint8_t phylink_string[][17] = {"PHY_LINK_1S1S1S",
"PHY_LINK_1S1S2S",
"PHY_LINK_1S2S2S",
"PHY_LINK_1S1D1D",
"PHY_LINK_4S4S4S",
"PHY_LINK_4S4D4D",
"PHY_LINK_4D4D4D",
"PHY_LINK_1S8S8S",
"PHY_LINK_8S8D8D",
"PHY_LINK_8D8D8D",
"PHY_LINK_RAM8",
#if defined(HAL_XSPI_DATA_16_LINES)
"PHY_LINK_RAM16",
#endif /* HAL_XSPI_DATA_16_LINES */
};
#define STR_PHY_LINK(_PHY_) phylink_string[_PHY_]
/**
* @brief Trace data string macro.
*/
#define DEBUG_PARAM_DATA(_STR_) EXTMEM_MACRO_DEBUG(_STR_);
/**
* @brief Trace data integer macro.
*/
#define DEBUG_PARAM_INT(_INT_) \
{ \
char str[10]; \
(void)snprintf(str, sizeof(str), "0x%x", _INT_); \
EXTMEM_MACRO_DEBUG(str); \
}
#define DEBUG_PARAM_INTD(_INT_) \
{ \
char str[15]; \
(void)snprintf(str, sizeof(str), "%zu", _INT_); \
EXTMEM_MACRO_DEBUG(str); \
}
/**
* @brief Trace close macro
*/
#define DEBUG_PARAM_END() EXTMEM_MACRO_DEBUG("\n");
#if EXTMEM_SAL_XSPI_DEBUG_LEVEL == 2
#define DEBUG_AUTOPOLLING(_DR_,_MVAL_,_MMASK_) \
{ \
char str[50]; \
(void)snprintf(str, sizeof(str),"DR:0x%x::MVal:0x%x::MMask:0x%x\n\r", _DR_, _MVAL_, _MMASK_); \
DEBUG_PARAM_BEGIN() \
DEBUG_PARAM_DATA(str) \
DEBUG_PARAM_END() \
}
#else
#define DEBUG_AUTOPOLLING(_DR_,_MVAL_,_MMASK_)
#endif /* EXTMEM_SAL_XSPI_DEBUG_LEVEL == 2 */
#endif /* EXTMEM_SAL_XSPI_DEBUG_LEVEL == 0 || !EXTMEM_MACRO_DEBUG */
/**
* @brief Default SAL timeout (100 ms)
*/
#define SAL_XSPI_TIMEOUT_DEFAULT_VALUE (100U)
/**
* @}
*/
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
/** @defgroup SAL_XSPI_Private_Transfer SAL XSPI Dma transfer management definition
* @{
*/
/**
* @brief State of the transfer status
*/
typedef enum
{
SALXSPI_TRANSFER_NONE, /*!< */
SALXSPI_TRANSFER_OK,
SALXSPI_TRANSFER_ERROR
} SAL_XSPI_TRANSFER_STATUS;
/**
* @brief Variable of the transfer status
*/
volatile SAL_XSPI_TRANSFER_STATUS salXSPI_status = SALXSPI_TRANSFER_NONE;
/**
* @}
*/
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
/* Private typedefs ---------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup SAL_XSPI_Private_Functions SAL XSP Private Functions
* @{
*/
uint16_t XSPI_FormatCommand(uint8_t CommandExtension, uint32_t InstructionWidth, uint8_t Command);
HAL_StatusTypeDef XSPI_Transmit(SAL_XSPI_ObjectTypeDef *SalXspi, const uint8_t *Data);
HAL_StatusTypeDef XSPI_Receive(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t *Data);
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
void SAL_XSPI_ErrorCallback(struct __XSPI_HandleTypeDef *hxspi);
void SAL_XSPI_CompleteCallback(struct __XSPI_HandleTypeDef *hxspi);
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
/**
* @}
*/
/* Exported variables ---------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup SAL_XSPI_Exported_Functions SAL XSP Exported Functions
* @{
*/
/**
* @brief This function sets the clock according the clock in and the expected clock
* @param SalXspi SAL XSPI handle
* @param ClockIn Clock in input
* @param ClockRequested Clock requested
* @param ClockReal Pointer on the value of the real clock used
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_SetClock(SAL_XSPI_ObjectTypeDef *SalXspi, uint32_t ClockIn, uint32_t ClockRequested,
uint32_t *ClockReal)
{
HAL_StatusTypeDef retr = HAL_OK;
uint32_t divider;
if (ClockRequested == 0u)
{
retr = HAL_ERROR;
}
else
{
divider = (ClockIn / ClockRequested);
if (divider >= 1u)
{
*ClockReal = ClockIn / divider;
if (*ClockReal <= ClockRequested)
{
divider--;
}
}
/* Real clock calculation */
*ClockReal = ClockIn / (divider + 1u);
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::CLOCKDIV::");
DEBUG_PARAM_INT(divider + 1);
DEBUG_PARAM_END();
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::CLKFREQ::");
DEBUG_PARAM_INTD(*ClockReal);
DEBUG_PARAM_END();
MODIFY_REG(SalXspi->hxspi->Instance->DCR2, XSPI_DCR2_PRESCALER, (uint32_t)divider << XSPI_DCR2_PRESCALER_Pos);
}
return retr;
}
/**
* @brief This function is used to configure the way to discuss with the memory
* @param SalXspi SAL XSPI handle
* @param HALHandle HAl XSPI handle used for memory access
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_Init(SAL_XSPI_ObjectTypeDef *SalXspi, void *HALHandle)
{
XSPI_RegularCmdTypeDef s_commandbase =
{
.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG,
.IOSelect = HAL_XSPI_SELECT_IO_7_0,
.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE,
.Instruction = EXTMEM_READ_SFDP_COMMAND,
.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS,
.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE,
.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE,
.AddressMode = HAL_XSPI_ADDRESS_1_LINE,
.AddressWidth = HAL_XSPI_ADDRESS_24_BITS,
.Address = 0x0,
.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE,
.DataMode = HAL_XSPI_DATA_1_LINE,
.DataLength = 0x0,
.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE,
.DummyCycles = EXTMEM_READ_SFDP_NB_DUMMY_CYCLES_DEFAULT,
.DQSMode = HAL_XSPI_DQS_DISABLE,
#if defined(XSPI_CCR_SIOO)
.SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD,
#endif /* XSPI_CCR_SIOO */
};
SalXspi->hxspi = (XSPI_HandleTypeDef *)HALHandle;
SalXspi->Commandbase = s_commandbase;
SalXspi->CommandExtension = 0;
SalXspi->PhyLink = PHY_LINK_1S1S1S;
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
/* Set completion call back */
HAL_XSPI_RegisterCallback(SalXspi->hxspi, HAL_XSPI_RX_CPLT_CB_ID, SAL_XSPI_CompleteCallback);
HAL_XSPI_RegisterCallback(SalXspi->hxspi, HAL_XSPI_TX_CPLT_CB_ID, SAL_XSPI_CompleteCallback);
/* Set the error callback */
HAL_XSPI_RegisterCallback(SalXspi->hxspi, HAL_XSPI_ERROR_CB_ID, SAL_XSPI_ErrorCallback);
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
return HAL_OK;
}
/**
* @brief This function sets a configuration parameter
* @param SalXspi SAL XSPI handle
* @param ParametersType @ref SAL_XSPI_MemParamTypeTypeDef
* @param ParamVal Pointer on the parameter value
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_MemoryConfig(SAL_XSPI_ObjectTypeDef *SalXspi, SAL_XSPI_MemParamTypeTypeDef ParametersType,
void *ParamVal)
{
HAL_StatusTypeDef retr = HAL_OK;
XSPI_RegularCmdTypeDef s_commandbase = SalXspi->Commandbase;
switch (ParametersType)
{
case PARAM_PHY_LINK:
{
SalXspi->PhyLink = *((SAL_XSPI_PhysicalLinkTypeDef *)ParamVal);
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::PARAM_PHY_LINK::");
DEBUG_PARAM_DATA(STR_PHY_LINK(SalXspi->PhyLink));
switch (SalXspi->PhyLink)
{
case PHY_LINK_1S1D1D:
case PHY_LINK_1S2S2S:
case PHY_LINK_1S1S2S:
case PHY_LINK_1S1S1S:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_1_LINE;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
s_commandbase.DataMode = HAL_XSPI_DATA_1_LINE;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
s_commandbase.DummyCycles = 8;
s_commandbase.DQSMode = HAL_XSPI_DQS_DISABLE;
break;
}
case PHY_LINK_4S4D4D:
case PHY_LINK_4S4S4S:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_4_LINES;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
s_commandbase.DataMode = HAL_XSPI_DATA_4_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
s_commandbase.DummyCycles = 6;
s_commandbase.DQSMode = HAL_XSPI_DQS_DISABLE;
break;
}
case PHY_LINK_4D4D4D:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_ENABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_4_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_commandbase.DataMode = HAL_XSPI_DATA_4_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_commandbase.DummyCycles = 6;
s_commandbase.DQSMode = HAL_XSPI_DQS_DISABLE;
break;
}
case PHY_LINK_1S8S8S:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
s_commandbase.DataMode = HAL_XSPI_DATA_8_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
s_commandbase.DummyCycles = 8;
s_commandbase.DQSMode = HAL_XSPI_DQS_DISABLE;
break;
}
case PHY_LINK_8S8D8D:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_commandbase.DataMode = HAL_XSPI_DATA_8_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_commandbase.DummyCycles = 8;
s_commandbase.DQSMode = HAL_XSPI_DQS_ENABLE;
break;
}
case PHY_LINK_8D8D8D:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_16_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_ENABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_commandbase.DataMode = HAL_XSPI_DATA_8_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_commandbase.DummyCycles = 20;
s_commandbase.DQSMode = HAL_XSPI_DQS_ENABLE;
break;
}
case PHY_LINK_RAM8:
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_commandbase.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
s_commandbase.DataMode = HAL_XSPI_DATA_8_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_commandbase.DummyCycles = 10;
s_commandbase.DQSMode = HAL_XSPI_DQS_ENABLE;
break;
}
#if defined(HAL_XSPI_DATA_16_LINES)
case PHY_LINK_RAM16 :
{
s_commandbase.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
s_commandbase.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
s_commandbase.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
s_commandbase.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_commandbase.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_commandbase.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
s_commandbase.DataMode = HAL_XSPI_DATA_16_LINES;
s_commandbase.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_commandbase.DummyCycles = 10;
s_commandbase.DQSMode = HAL_XSPI_DQS_ENABLE;
break;
}
#endif /* HAL_XSPI_DATA_16_LINES */
default:
retr = HAL_ERROR;
break;
}
DEBUG_PARAM_END();
break;
}
case PARAM_ADDRESS_4BYTES:
{
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::PARAM_ADDRESS_4BYTES");
DEBUG_PARAM_END();
s_commandbase.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
break;
}
case PARAM_FLASHSIZE:
{
uint8_t valParam = *((uint8_t *)ParamVal);
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::PARAM_FLASHSIZE::");
DEBUG_PARAM_INT(valParam);
DEBUG_PARAM_END();
MODIFY_REG(SalXspi->hxspi->Instance->DCR1, XSPI_DCR1_DEVSIZE, ((uint32_t)valParam) << XSPI_DCR1_DEVSIZE_Pos);
break;
}
case PARAM_DUMMY_CYCLES:
{
uint8_t valParam = *((uint8_t *)ParamVal);
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::PARAM_DUMMY_CYCLES::");
DEBUG_PARAM_INT(valParam);
DEBUG_PARAM_END();
s_commandbase.DummyCycles = valParam;
break;
}
default:
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::SAL_XSPI_MemoryConfig::ERROR");
DEBUG_PARAM_END();
retr = HAL_ERROR;
break;
}
SalXspi->Commandbase = s_commandbase;
return retr;
}
/**
* @brief This function gets SFDP data
* @param SalXspi SAL XSPI handle
* @param Address Address to read the data
* @param Data Data pointer
* @param DataSize Size of the data to read
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_GetSFDP(SAL_XSPI_ObjectTypeDef *SalXspi, uint32_t Address, uint8_t *Data, uint32_t DataSize)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the read ID command */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth,
EXTMEM_READ_SFDP_COMMAND);
s_command.Address = Address;
s_command.DataLength = DataSize;
s_command.DummyCycles = SalXspi->SFDPDummyCycle;
if ((s_command.AddressMode == HAL_XSPI_ADDRESS_1_LINE) || (s_command.AddressMode == HAL_XSPI_ADDRESS_4_LINES))
{
s_command.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
}
if (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE)
{
s_command.DQSMode = HAL_XSPI_DQS_ENABLE;
}
else
{
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
}
/* Configure the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
/* Reception of the data */
retr = HAL_XSPI_Receive(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function reads the flash ID
* @param SalXspi SAL XSPI handle
* @param Data Data pointer where read ID should be stored
* @param DataSize Number of data to read
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_GetId(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t *Data, uint32_t DataSize)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the Read ID command */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth,
EXTMEM_READ_JEDEC_ID_SPI_COMMAND);
s_command.DataLength = DataSize;
if (s_command.InstructionMode == HAL_XSPI_INSTRUCTION_1_LINE)
{
s_command.AddressMode = HAL_XSPI_ADDRESS_NONE;
s_command.DummyCycles = 0;
/* This behavior is linked with micron memory to read ID in 1S8S8S */
s_command.DataMode = HAL_XSPI_DATA_1_LINE;
}
else if (s_command.InstructionMode == HAL_XSPI_INSTRUCTION_4_LINES)
{
s_command.AddressMode = HAL_XSPI_ADDRESS_NONE;
s_command.DummyCycles = 0;
/* This behavior is linked with ISSI memory to read ID in 4S4S4S */
s_command.DataMode = HAL_XSPI_DATA_4_LINES;
}
else if (s_command.InstructionMode == HAL_XSPI_INSTRUCTION_8_LINES)
{
s_command.Address = 0;
/* Specific case for Macronix memories : RDID is not Data DTR */
if ((Data[0] == 0xC2) && (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE))
{
s_command.DummyCycles = 4;
s_command.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
}
/* Specific case for GigaDevice memories : RDID has no address even in Octal mode */
else if ((Data[0] == 0xC8) && (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE))
{
s_command.DummyCycles = 8;
s_command.AddressMode = HAL_XSPI_ADDRESS_NONE;
}
else
{
s_command.DummyCycles = 8;
}
/* Required behavior to be confirmed on the other memories */
}
else
{
s_command.Address = 0;
s_command.DummyCycles = 8;
}
/* Configure the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
/* Reception of the data */
retr = HAL_XSPI_Receive(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function reads data from the flash
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Address Address to read the data
* @param Data Data pointer
* @param DataSize Size of the data to read
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_Read(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command, uint32_t Address, uint8_t *Data,
uint32_t DataSize)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the read ID command */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.Address = Address;
s_command.DataLength = DataSize;
/* DTR management for single/dual/quad */
switch (SalXspi->PhyLink)
{
case PHY_LINK_4S4D4D :
s_command.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
s_command.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
s_command.DummyCycles = SalXspi->DTRDummyCycle;
break;
case PHY_LINK_1S2S2S :
s_command.AddressMode = HAL_XSPI_ADDRESS_2_LINES;
s_command.DataMode = HAL_XSPI_DATA_2_LINES;
break;
case PHY_LINK_1S1S2S :
s_command.DataMode = HAL_XSPI_DATA_2_LINES;
break;
default :
/* Keep default parameters */
break;
}
/* Configure the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
/* Read data */
retr = XSPI_Receive(SalXspi, Data);
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function writes data at an Address
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Address Address to write the data
* @param Data Data pointer
* @param DataSize Size of the data to write
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_Write(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command, uint32_t Address,
const uint8_t *Data, uint32_t DataSize)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the read ID command */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.Address = Address;
s_command.DataLength = DataSize;
s_command.DummyCycles = 0u;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
/* Configure the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (HAL_OK != retr)
{
goto error;
}
/* Transmit data */
retr = XSPI_Transmit(SalXspi, Data);
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function sends a command and an address
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Address Address to write the data
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_CommandSendAddress(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command,
uint32_t Address)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the writing of status register */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
if (s_command.InstructionMode == HAL_XSPI_INSTRUCTION_1_LINE)
{
s_command.AddressMode = HAL_XSPI_ADDRESS_1_LINE;
}
s_command.Address = Address;
s_command.DummyCycles = 0U;
s_command.DataMode = HAL_XSPI_DATA_NONE;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
/* Send the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function sends a command + data
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Data Data pointer
* @param DataSize Size of the data to write
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_CommandSendData(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command,
uint8_t *Data, uint16_t DataSize)
{
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
HAL_StatusTypeDef retr;
/* Initialize the writing of status register */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.AddressMode = HAL_XSPI_ADDRESS_NONE;
s_command.DummyCycles = 0U;
s_command.DataLength = DataSize;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
if (DataSize == 0u)
{
s_command.DataMode = HAL_XSPI_DATA_NONE;
}
/* Send the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if ((retr == HAL_OK) && (DataSize != 0u))
{
retr = HAL_XSPI_Transmit(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function sends a command to read the data
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Data Data pointer
* @param DataSize Size of the data to receive
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_SendReadCommand(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command,
uint8_t *Data, uint16_t DataSize)
{
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
HAL_StatusTypeDef retr;
/* Initialize the reading of status register */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.AddressMode = HAL_XSPI_ADDRESS_NONE;
s_command.DummyCycles = 0u;
s_command.DataLength = DataSize;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
if (DataSize == 0u)
{
s_command.DataMode = HAL_XSPI_DATA_NONE;
}
/* Send the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if ((retr == HAL_OK) && (DataSize != 0u))
{
/* Receive data */
retr = HAL_XSPI_Receive(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function sends a command with address and read the data
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Address Address value
* @param Data Data pointer
* @param DataSize Size of the data to read
* @param ManuId Manufacturer Identifier
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_CommandSendReadAddress(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command,
uint32_t Address, uint8_t *Data, uint16_t DataSize,
uint8_t ManuId)
{
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
HAL_StatusTypeDef retr;
/* Initialize the reading of status register */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.Address = Address;
s_command.DummyCycles = SalXspi->SFDPDummyCycle;
s_command.DataLength = DataSize;
/* Specific case for Macronix memories : RDID and RDCR are not Data DTR */
if ((ManuId == EXTMEM_MANUFACTURER_MACRONIX) && (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE))
{
s_command.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
}
/* Specific case for GigaDevice memories : Read Configuration Register are not Data DTR */
else if ((ManuId == 0xC8) && (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE))
{
s_command.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
}
else
{
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
}
/* Send the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr == HAL_OK)
{
/* Retrieve data */
retr = HAL_XSPI_Receive(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function controls the status register
* @param SalXspi SAL XSPI handle
* @param Command Command to execute
* @param Address Specify the address
* @param MatchValue Expected value
* @param MatchMask Mask used to control the expected value
* @param ManuId Manufacturer Identifier
* @param Timeout Timeout parameter
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_CheckStatusRegister(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t Command, uint32_t Address,
uint8_t MatchValue, uint8_t MatchMask, uint8_t ManuId,
uint32_t Timeout)
{
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
XSPI_AutoPollingTypeDef s_config =
{
.MatchValue = MatchValue,
.MatchMask = MatchMask,
.MatchMode = HAL_XSPI_MATCH_MODE_AND,
.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE,
.IntervalTime = 0x10
};
HAL_StatusTypeDef retr;
/* Initialize the reading of status register */
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, Command);
s_command.DataLength = 1u;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
if (s_command.InstructionMode == HAL_XSPI_INSTRUCTION_1_LINE)
{
/* Specific behavior for Cypress to force 1 line on status read */
s_command.DataMode = HAL_XSPI_DATA_1_LINE;
s_command.AddressMode = HAL_XSPI_DATA_NONE;
s_command.DummyCycles = 0u;
}
/* Address is used only in 8 LINES format */
if (s_command.DataMode == HAL_XSPI_DATA_8_LINES)
{
/* Specific case for Macronix memories : RDID and RDCR are not Data DTR */
if ((ManuId == EXTMEM_MANUFACTURER_MACRONIX) && (s_command.DataDTRMode == HAL_XSPI_DATA_DTR_ENABLE))
{
s_command.DQSMode = HAL_XSPI_DQS_ENABLE;
s_command.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
}
s_command.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
s_command.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
s_command.Address = Address;
}
/* Send the command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr == HAL_OK)
{
retr = HAL_XSPI_AutoPolling(SalXspi->hxspi, &s_config, Timeout);
DEBUG_AUTOPOLLING(SalXspi->hxspi->Instance->DR, s_config.MatchValue, s_config.MatchMask)
}
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function enables the memory mapped mode
* @param SalXspi SAL XSPI handle
* @param WrapCommand Wrap command to execute in case of write operation
* @param WrapDummy Number of dummy cycle for the read operation
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_ConfigureWrappMode(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t WrapCommand, uint8_t WrapDummy)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
/* Initialize the read ID command */
s_command.OperationType = HAL_XSPI_OPTYPE_WRAP_CFG;
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, WrapCommand);
s_command.DummyCycles = WrapDummy;
/* Configure the read command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function enables the memory mapped mode
* @param SalXspi SAL XSPI handle
* @param CommandRead command to execute in case of read operation
* @param DummyRead number of dummy cycle for the read operation
* @param CommandWrite command to execute in case of write operation
* @param DummyWrite number of dummy cycle for the read operation
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_EnableMapMode(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t CommandRead, uint8_t DummyRead,
uint8_t CommandWrite, uint8_t DummyWrite)
{
HAL_StatusTypeDef retr;
XSPI_RegularCmdTypeDef s_command = SalXspi->Commandbase;
XSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
/* Initialize the read ID command */
s_command.OperationType = HAL_XSPI_OPTYPE_READ_CFG;
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, CommandRead);
s_command.DummyCycles = DummyRead;
/* Configure the read command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
/* Initialize the read ID command */
s_command.OperationType = HAL_XSPI_OPTYPE_WRITE_CFG;
s_command.Instruction = XSPI_FormatCommand(SalXspi->CommandExtension, s_command.InstructionWidth, CommandWrite);
s_command.DummyCycles = DummyWrite;
/* Configure the read command */
retr = HAL_XSPI_Command(SalXspi->hxspi, &s_command, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
if (retr != HAL_OK)
{
goto error;
}
/* Activation of memory-mapped mode */
sMemMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE;
sMemMappedCfg.TimeoutPeriodClock = 0x50;
retr = HAL_XSPI_MemoryMapped(SalXspi->hxspi, &sMemMappedCfg);
error:
if (retr != HAL_OK)
{
/* Abort any ongoing transaction for the next action */
(void)HAL_XSPI_Abort(SalXspi->hxspi);
}
return retr;
}
/**
* @brief This function disables the memory mapped mode
* @param SalXspi SAL XSPI handle
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_DisableMapMode(SAL_XSPI_ObjectTypeDef *SalXspi)
{
__DSB();
return HAL_XSPI_Abort(SalXspi->hxspi);
}
/**
* @brief This function updates the memory according the SFDP signature value
* @param SalXspi SAL XSPI handle
* @param DataOrder Selected data order
* @return @ref HAL_StatusTypeDef
**/
HAL_StatusTypeDef SAL_XSPI_UpdateMemoryType(SAL_XSPI_ObjectTypeDef *SalXspi, SAL_XSPI_DataOrderTypeDef DataOrder)
{
HAL_StatusTypeDef retr = HAL_OK;
/* Read the memory type value */
uint32_t memorytype = READ_REG(SalXspi->hxspi->Instance->DCR1) & XSPI_DCR1_MTYP;
switch (DataOrder)
{
case SAL_XSPI_ORDERINVERTED :
if (memorytype == HAL_XSPI_MEMTYPE_MICRON)
{
memorytype = HAL_XSPI_MEMTYPE_MACRONIX;
}
else if (memorytype == HAL_XSPI_MEMTYPE_MACRONIX)
{
memorytype = HAL_XSPI_MEMTYPE_MICRON;
}
else
{
retr = HAL_ERROR;
}
MODIFY_REG(SalXspi->hxspi->Instance->DCR1, XSPI_DCR1_MTYP, memorytype);
break;
default :
return HAL_ERROR;
break;
}
DEBUG_PARAM_BEGIN();
DEBUG_PARAM_DATA("::SAL_XSPI_UpdateMemoryType::");
DEBUG_PARAM_INT(memorytype);
DEBUG_PARAM_END();
return retr;
}
HAL_StatusTypeDef SAL_XSPI_Abort(SAL_XSPI_ObjectTypeDef *SalXspi)
{
return HAL_XSPI_Abort(SalXspi->hxspi);
}
/**
* @}
*/
/** @defgroup SAL_XSPI_Private_Functions SAL XSP Private Functions
* @{
*/
/**
* @brief This function return a formatted command
*
* @param CommandExtension Type of the command extension 0: the complement 1 : the same
* @param InstructionWidth Instruction width
* @param Command Command
* @return Formatted command
*/
uint16_t XSPI_FormatCommand(uint8_t CommandExtension, uint32_t InstructionWidth, uint8_t Command)
{
uint16_t retr;
if (InstructionWidth == HAL_XSPI_INSTRUCTION_16_BITS)
{
/* 0b00 Command Extension is the same as the Command.
(Command / Command Extension has the same value for the whole clock period. */
/* 0b01 Command Extension is the inverse of the Command.
Command Extension acts as a confirmation of the Command */
/* 0b11 Command and Command Extension forms a 16 bit command word :: Not yet handled */
retr = ((uint16_t)Command << 8u);
if (CommandExtension == 1u)
{
retr |= (uint8_t)(~Command & 0xFFu);
}
else
{
retr |= (uint8_t)(Command & 0xFFu);
}
}
else
{
retr = Command;
}
return retr;
}
/**
* @brief This function transmits the data
*
* @param SalXspi SAL XSPI Handle
* @param Data Data pointer
* @return Status of the command execution
*/
HAL_StatusTypeDef XSPI_Transmit(SAL_XSPI_ObjectTypeDef *SalXspi, const uint8_t *Data)
{
HAL_StatusTypeDef retr;
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
if (SalXspi->hxspi->hdmatx == NULL)
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
{
/* Transmit data */
retr = HAL_XSPI_Transmit(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
else
{
/* Set completion call back */
salXSPI_status = SALXSPI_TRANSFER_NONE;
/* Reception of the data */
retr = HAL_XSPI_Transmit_DMA(SalXspi->hxspi, (uint8_t *)Data);
if (retr == HAL_OK)
{
/* Wait data reception completion */
while (salXSPI_status == SALXSPI_TRANSFER_NONE);
if (salXSPI_status == SALXSPI_TRANSFER_ERROR)
{
retr = HAL_ERROR;
}
}
}
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
return retr;
}
/**
* @brief Start data reception in polling mode or DMA
*
* @param SalXspi SAL XSPI Handle
* @param Data Data pointer
* @return Status of the command execution
*/
HAL_StatusTypeDef XSPI_Receive(SAL_XSPI_ObjectTypeDef *SalXspi, uint8_t *Data)
{
HAL_StatusTypeDef retr;
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
if (SalXspi->hxspi->hdmarx == NULL)
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
{
/* Reception of the data */
retr = HAL_XSPI_Receive(SalXspi->hxspi, Data, SAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
else
{
/* Set completion call back */
salXSPI_status = SALXSPI_TRANSFER_NONE;
/* Reception of the data */
retr = HAL_XSPI_Receive_DMA(SalXspi->hxspi, Data);
if (retr == HAL_OK)
{
/* Wait data completion */
while (salXSPI_status == SALXSPI_TRANSFER_NONE);
if (salXSPI_status == SALXSPI_TRANSFER_ERROR)
{
retr = HAL_ERROR;
}
}
}
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
return retr;
}
#if defined (USE_HAL_XSPI_REGISTER_CALLBACKS) && (USE_HAL_XSPI_REGISTER_CALLBACKS == 1U)
/**
* @brief This callback is executed when a DMA transfer error occurs
*
* @param hxspi Handle on the XSPI peripheral
* @return none
*/
void SAL_XSPI_ErrorCallback(struct __XSPI_HandleTypeDef *hxspi)
{
salXSPI_status = SALXSPI_TRANSFER_ERROR;
}
/**
* @brief this callback is executed when a DMA transfer is complete
*
* @param hxspi Handle on the XSPI peripheral
* @return none
*/
void SAL_XSPI_CompleteCallback(struct __XSPI_HandleTypeDef *hxspi)
{
salXSPI_status = SALXSPI_TRANSFER_OK;
}
#endif /* USE_HAL_XSPI_REGISTER_CALLBACKS */
/**
* @}
*/
/**
* @}
*/
#endif /* EXTMEM_SAL_XSPI == 1 */