1246 lines
41 KiB
C
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 */
|