|
@@ -0,0 +1,3020 @@
|
|
|
+
|
|
|
+* Project : RTD AUTOSAR 4.4
|
|
|
+* Platform : CORTEXM
|
|
|
+* Peripheral : LPSPI
|
|
|
+* Dependencies :
|
|
|
+*
|
|
|
+* Autosar Version : 4.4.0
|
|
|
+* Autosar Revision : ASR_REL_4_4_REV_0000
|
|
|
+* Autosar Conf.Variant :
|
|
|
+* SW Version : 1.0.0
|
|
|
+* Build Version : S32K1_RTD_1_0_0_HF01_D2109_ASR_REL_4_4_REV_0000_20210907
|
|
|
+*
|
|
|
+* (c) Copyright 2020-2021 NXP Semiconductors
|
|
|
+* All Rights Reserved.
|
|
|
+*
|
|
|
+* NXP Confidential. This software is owned or controlled by NXP and may only be
|
|
|
+* used strictly in accordance with the applicable license terms. By expressly
|
|
|
+* accepting such terms or by downloading, installing, activating and/or otherwise
|
|
|
+* using the software, you are agreeing that you have read, and that you agree to
|
|
|
+* comply with and are bound by, such license terms. If you do not agree to be
|
|
|
+* bound by the applicable license terms, then you may not retain, install,
|
|
|
+* activate or otherwise use the software.
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+
|
|
|
+* @file Lpspi_Ip.c
|
|
|
+*
|
|
|
+*
|
|
|
+* @brief LPSPI low-level driver implementations.
|
|
|
+* @details LPSPI low-level driver implementations.
|
|
|
+*
|
|
|
+* @addtogroup LPSPI_DRIVER Lpspi Driver
|
|
|
+* @{
|
|
|
+*/
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+extern "C"
|
|
|
+{
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+* INCLUDE FILES
|
|
|
+* 1) system and project includes
|
|
|
+* 2) needed interfaces from external units
|
|
|
+* 3) internal and external interfaces from this unit
|
|
|
+==================================================================================================*/
|
|
|
+#include "Mcal.h"
|
|
|
+#include "Lpspi_Ip.h"
|
|
|
+#include "Lpspi_Ip_Cfg.h"
|
|
|
+#include "OsIf.h"
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ #include "Dma_Ip.h"
|
|
|
+#endif
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_USER_MODE_SUPPORT)
|
|
|
+ #define USER_MODE_REG_PROT_ENABLED (LPSPI_IP_ENABLE_USER_MODE_SUPPORT)
|
|
|
+ #include "RegLockMacros.h"
|
|
|
+#endif
|
|
|
+#include "SchM_Spi.h"
|
|
|
+#if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ #include "Devassert.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+* SOURCE FILE VERSION INFORMATION
|
|
|
+==================================================================================================*/
|
|
|
+#define LPSPI_IP_VENDOR_ID_C 43
|
|
|
+#define LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C 4
|
|
|
+#define LPSPI_IP_AR_RELEASE_MINOR_VERSION_C 4
|
|
|
+#define LPSPI_IP_AR_RELEASE_REVISION_VERSION_C 0
|
|
|
+#define LPSPI_IP_SW_MAJOR_VERSION_C 1
|
|
|
+#define LPSPI_IP_SW_MINOR_VERSION_C 0
|
|
|
+#define LPSPI_IP_SW_PATCH_VERSION_C 0
|
|
|
+
|
|
|
+* FILE VERSION CHECKS
|
|
|
+==================================================================================================*/
|
|
|
+#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
|
|
|
+
|
|
|
+ #if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION))
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and Mcal.h are different"
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+
|
|
|
+ #if ((DMA_IP_AR_RELEASE_MAJOR_VERSION_H != LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C) || \
|
|
|
+ (DMA_IP_AR_RELEASE_MINOR_VERSION_H != LPSPI_IP_AR_RELEASE_MINOR_VERSION_C))
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and Dma_Ip.h are different"
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_ENABLE_USER_MODE_SUPPORT)
|
|
|
+ #if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C != REGLOCKMACROS_AR_RELEASE_MAJOR_VERSION) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_C != REGLOCKMACROS_AR_RELEASE_MINOR_VERSION))
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and RegLockMacros.h are different"
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+
|
|
|
+
|
|
|
+ #if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C != SCHM_SPI_AR_RELEASE_MAJOR_VERSION) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_C != SCHM_SPI_AR_RELEASE_MINOR_VERSION) \
|
|
|
+ )
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and SchM_Spi.h are different"
|
|
|
+ #endif
|
|
|
+
|
|
|
+
|
|
|
+ #if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION) \
|
|
|
+ )
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and OsIf.h are different"
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+
|
|
|
+ #if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C != DEVASSERT_AR_RELEASE_MAJOR_VERSION) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_C != DEVASSERT_AR_RELEASE_MINOR_VERSION) \
|
|
|
+ )
|
|
|
+ #error "AutoSar Version Numbers of Lpspi_Ip.c and Devassert.h are different"
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+#if (LPSPI_IP_VENDOR_ID != LPSPI_IP_VENDOR_ID_C)
|
|
|
+ #error "Lpspi_Ip.h and Lpspi_Ip.c have different vendor ids"
|
|
|
+#endif
|
|
|
+
|
|
|
+#if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION != LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION != LPSPI_IP_AR_RELEASE_MINOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_REVISION_VERSION != LPSPI_IP_AR_RELEASE_REVISION_VERSION_C))
|
|
|
+#error "AutoSar Version Numbers of Lpspi_Ip.h and Lpspi_Ip.c are different"
|
|
|
+#endif
|
|
|
+#if ((LPSPI_IP_SW_MAJOR_VERSION != LPSPI_IP_SW_MAJOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_SW_MINOR_VERSION != LPSPI_IP_SW_MINOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_SW_PATCH_VERSION != LPSPI_IP_SW_PATCH_VERSION_C))
|
|
|
+#error "Software Version Numbers of Lpspi_Ip.h and Lpspi_Ip.c are different"
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+#if (LPSPI_IP_VENDOR_ID_CFG != LPSPI_IP_VENDOR_ID_C)
|
|
|
+ #error "Lpspi_Ip_Cfg.h and Lpspi_Ip.c have different vendor ids"
|
|
|
+#endif
|
|
|
+
|
|
|
+#if ((LPSPI_IP_AR_RELEASE_MAJOR_VERSION_CFG != LPSPI_IP_AR_RELEASE_MAJOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_MINOR_VERSION_CFG != LPSPI_IP_AR_RELEASE_MINOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_AR_RELEASE_REVISION_VERSION_CFG != LPSPI_IP_AR_RELEASE_REVISION_VERSION_C))
|
|
|
+#error "AutoSar Version Numbers of Lpspi_Ip_Cfg.h and Lpspi_Ip.c are different"
|
|
|
+#endif
|
|
|
+#if ((LPSPI_IP_SW_MAJOR_VERSION_CFG != LPSPI_IP_SW_MAJOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_SW_MINOR_VERSION_CFG != LPSPI_IP_SW_MINOR_VERSION_C) || \
|
|
|
+ (LPSPI_IP_SW_PATCH_VERSION_CFG != LPSPI_IP_SW_PATCH_VERSION_C))
|
|
|
+#error "Software Version Numbers of Lpspi_Ip_Cfg.h and Lpspi_Ip.c are different"
|
|
|
+#endif
|
|
|
+
|
|
|
+* LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+* LOCAL MACROS
|
|
|
+==================================================================================================*/
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+
|
|
|
+ #define LPSPI_IP_DMA_MAX_ITER_CNT_U16 ((uint16)0x7FFFu)
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+* @brief SR mask
|
|
|
+*/
|
|
|
+#define LPSPI_IP_SR_W1C_MASK_U32 (uint32)((uint32)LPSPI_SR_WCF_MASK | (uint32)LPSPI_SR_FCF_MASK | (uint32)LPSPI_SR_TCF_MASK | \
|
|
|
+ (uint32)LPSPI_SR_TEF_MASK | (uint32)LPSPI_SR_REF_MASK | (uint32)LPSPI_SR_DMF_MASK)
|
|
|
+
|
|
|
+
|
|
|
+* LOCAL CONSTANTS
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+* LOCAL VARIABLES
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+* GLOBAL CONSTANTS
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+ GLOBAL VARIABLES
|
|
|
+==================================================================================================*/
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ #define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
|
|
|
+#else
|
|
|
+ #define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED
|
|
|
+#endif
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+static Lpspi_Ip_StateStructureType Lpspi_Ip_axStateStructure[LPSPI_IP_NUMBER_OF_INSTANCES];
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ #define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
|
|
|
+#else
|
|
|
+ #define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED
|
|
|
+#endif
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ #define SPI_START_SEC_VAR_CLEARED_32_NO_CACHEABLE
|
|
|
+ #include "Spi_MemMap.h"
|
|
|
+static uint32 Lpspi_Ip_u32DiscardData;
|
|
|
+ #define SPI_STOP_SEC_VAR_CLEARED_32_NO_CACHEABLE
|
|
|
+ #include "Spi_MemMap.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+#define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+Lpspi_Ip_StateStructureType* Lpspi_Ip_apxStateStructureArray[LPSPI_INSTANCE_COUNT];
|
|
|
+
|
|
|
+#define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+#define SPI_START_SEC_CONST_UNSPECIFIED
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+static LPSPI_Type* const Lpspi_Ip_apxBases[LPSPI_INSTANCE_COUNT] = IP_LPSPI_BASE_PTRS;
|
|
|
+
|
|
|
+#define SPI_STOP_SEC_CONST_UNSPECIFIED
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+* LOCAL FUNCTION PROTOTYPES
|
|
|
+==================================================================================================*/
|
|
|
+#define SPI_START_SEC_CODE
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+LOCAL_INLINE void Lpspi_Ip_ReadDataFromFifo(uint8 Instance, uint8 NumberOfReads);
|
|
|
+LOCAL_INLINE void Lpspi_Ip_PushDataToFifo(uint8 Instance, uint8 NumberOfWrites);
|
|
|
+static void Lpspi_Ip_ChannelFinished(uint8 Instance, boolean ErrorFlag);
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+static void Lpspi_Ip_TransferProcessHalfDuplex(uint8 Instance);
|
|
|
+static boolean Lpspi_Ip_HalfDupleTransmitChannelComplete(uint8 Instance);
|
|
|
+LOCAL_INLINE boolean Lpspi_Ip_HalfDuplexTransmitProcess(uint8 Instance, uint8 NumberOfWrites);
|
|
|
+LOCAL_INLINE void Lpspi_Ip_HalfDuplexPushDataToFifo(uint8 Instance, uint8 NumberOfWrites);
|
|
|
+static void Lpspi_Ip_HalfDuplexPrepare(uint8 Instance, uint8* Buffer);
|
|
|
+#endif
|
|
|
+static void Lpspi_Ip_TransferProcess(uint8 Instance);
|
|
|
+static void Lpspi_TransmitTxInit(uint8 Instance,
|
|
|
+ uint8* TxBuffer,
|
|
|
+ uint8 TxFrameSize,
|
|
|
+ boolean TxLsb,
|
|
|
+ uint16 NumberOfFrames
|
|
|
+ );
|
|
|
+static void Lpspi_TransmitRxInit(uint8 Instance,
|
|
|
+ uint8* RxBuffer,
|
|
|
+ uint8 RxFrameSize,
|
|
|
+ uint16 NumberOfFrames
|
|
|
+ );
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+static void Lpspi_Ip_TxDmaConfig(uint8 Instance);
|
|
|
+static void Lpspi_Ip_RxDmaConfig(uint8 Instance);
|
|
|
+static void Lpspi_Ip_TxDmaContinueTransfer(uint8 Instance);
|
|
|
+static void Lpspi_Ip_RxDmaContinueTransfer(uint8 Instance);
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT)
|
|
|
+static void Lpspi_Ip_DmaFastConfig(uint8 Instance, const Lpspi_Ip_FastTransferType *FastTransferCfg, uint8 NumberOfTransfer);
|
|
|
+static void Lpspi_Ip_RxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint8 DisHwReq);
|
|
|
+static void Lpspi_Ip_RxDmaTcdSGInit(uint8 Instance);
|
|
|
+static void Lpspi_Ip_TxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint8 DisHwReq, const uint32 *DefaultDataAddress);
|
|
|
+static void Lpspi_Ip_TxDmaTcdSGInit(uint8 Instance);
|
|
|
+static void Lpspi_Ip_CmdTxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint32 CmdAdd, uint8 DisHwReq);
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_USER_MODE_SUPPORT)
|
|
|
+static void Lpspi_Ip_SetUserAccess(uint8 Instance);
|
|
|
+static void Lpspi_Ip_SetUserAccessAllowed(uint8 Instance);
|
|
|
+#endif
|
|
|
+#if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+static void Lpspi_Ip_CheckValidParameters
|
|
|
+(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint16 Length
|
|
|
+);
|
|
|
+#endif
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+static void Lpspi_Ip_TxDmaFinishTransfer
|
|
|
+(
|
|
|
+ const uint8 Instance
|
|
|
+);
|
|
|
+#endif
|
|
|
+
|
|
|
+* LOCAL FUNCTIONS
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+* @brief This function will read Data from RX FIFO.
|
|
|
+* @details This function will read Data from RX FIFO.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @param[in] NumberOfReads Number of Data can be read from RX FIFO.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+LOCAL_INLINE void Lpspi_Ip_ReadDataFromFifo(uint8 Instance, uint8 NumberOfReads)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 Data = 0u;
|
|
|
+ uint8 Index = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ if (NULL_PTR != State->RxBuffer)
|
|
|
+ {
|
|
|
+ if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfReads; Index++)
|
|
|
+ {
|
|
|
+ Data = Base->RDR;
|
|
|
+ *((uint8*)(&State->RxBuffer[State->RxIndex + Index])) = (uint8)Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfReads; Index++)
|
|
|
+ {
|
|
|
+ Data = Base->RDR;
|
|
|
+ *((uint16*)(&State->RxBuffer[2u * (State->RxIndex + Index)])) = (uint16)Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfReads; Index++)
|
|
|
+ {
|
|
|
+ Data = Base->RDR;
|
|
|
+ *((uint32*)(&State->RxBuffer[4u * (State->RxIndex + Index)])) = (uint32)Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfReads; Index++)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Base->RDR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ State->RxIndex += NumberOfReads;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will push Data into TX FIFO.
|
|
|
+* @details This function will push Data into TX FIFO.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @param[in] NumberOfWrites Number of Data can be pushed to TX FIFO.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+LOCAL_INLINE void Lpspi_Ip_PushDataToFifo(uint8 Instance, uint8 NumberOfWrites)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 Data = 0u;
|
|
|
+ uint8 Index = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ Data = State->ExternalDevice->DeviceParams->DefaultData;
|
|
|
+
|
|
|
+ if (NULL_PTR != State->TxBuffer)
|
|
|
+ {
|
|
|
+ if (State->TxFrameSize < 9u)
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfWrites; Index++)
|
|
|
+ {
|
|
|
+ Data = *((uint8*)(&State->TxBuffer[State->TxIndex + Index]));
|
|
|
+ Base->TDR = Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (State->TxFrameSize < 17u)
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfWrites; Index++)
|
|
|
+ {
|
|
|
+ Data = *((uint16*)(&State->TxBuffer[2u * (State->TxIndex + Index)]));
|
|
|
+ Base->TDR = Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfWrites; Index++)
|
|
|
+ {
|
|
|
+ Data = *((uint32*)(&State->TxBuffer[4u * (State->TxIndex + Index)]));
|
|
|
+ Base->TDR = Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (Index = 0; Index < NumberOfWrites; Index++)
|
|
|
+ {
|
|
|
+ Base->TDR = Data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ State->TxIndex += NumberOfWrites;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will finish transfer of a channel.
|
|
|
+* @details This function will finish transfer of a channel.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @param[in] ErrorFlag Save the status of transfer error flags
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_ChannelFinished(uint8 Instance, boolean ErrorFlag)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+
|
|
|
+ if(TRUE == ErrorFlag)
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ }
|
|
|
+ if (State->Callback != NULL_PTR)
|
|
|
+ {
|
|
|
+ if(TRUE == ErrorFlag)
|
|
|
+ {
|
|
|
+ State->Callback(Instance, LPSPI_IP_EVENT_FAULT);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Callback(Instance, LPSPI_IP_EVENT_END_TRANSFER);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+* @brief This function is called by Lpspi_Ip_IrqHandler or Lpspi_Ip_ManageBuffers. It will process transfer in interrupt mode or polling mode.
|
|
|
+* @details This function will fill Data into TX FIFO and read Data in RX FIFO fill to Rx Buffers.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_TransferProcessHalfDuplex(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 SrStatusRegister;
|
|
|
+ uint8 NumberOfWrites = 0u;
|
|
|
+ uint8 NumberOfReads = 0u;
|
|
|
+ boolean ErrorFlag = FALSE;
|
|
|
+ Lpspi_Ip_HalfDuplexType TransferType;
|
|
|
+ boolean TransferCompleted = FALSE;
|
|
|
+ uint8 NumberOfFramesTxFifo;
|
|
|
+
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+
|
|
|
+ SrStatusRegister = Base->SR;
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+ TransferType = State->ExternalDevice->DeviceParams->TransferType;
|
|
|
+
|
|
|
+ if ((SrStatusRegister & (LPSPI_SR_REF_MASK | LPSPI_SR_TEF_MASK)) != 0u)
|
|
|
+ {
|
|
|
+
|
|
|
+ ErrorFlag = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ if((State->ExpectedFifoWrites == State->TxIndex) && (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType))
|
|
|
+ {
|
|
|
+ ErrorFlag = Lpspi_Ip_HalfDupleTransmitChannelComplete(Instance);
|
|
|
+
|
|
|
+ TransferCompleted = TRUE;
|
|
|
+ }
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ NumberOfReads = (uint8)(((Base->FSR) & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT);
|
|
|
+ if (NumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
|
|
|
+ {
|
|
|
+ NumberOfReads = (uint8)(State->ExpectedFifoReads - State->RxIndex);
|
|
|
+ }
|
|
|
+ if (0u != NumberOfReads)
|
|
|
+ {
|
|
|
+ Lpspi_Ip_ReadDataFromFifo(Instance, NumberOfReads);
|
|
|
+ }
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if (FALSE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ if ((0u == ((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK)) && (State->ExpectedFifoWrites != State->TxIndex))
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR = State->HalfDuplexTcrCommand;
|
|
|
+ State->TxIndex++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ NumberOfFramesTxFifo = (uint8)(((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK) >> LPSPI_FSR_TXCOUNT_SHIFT);
|
|
|
+ NumberOfWrites = LPSPI_IP_FIFO_SIZE_U8 - NumberOfFramesTxFifo;
|
|
|
+ if((0u != NumberOfWrites) && (State->ExpectedFifoWrites != State->TxIndex))
|
|
|
+ {
|
|
|
+ Lpspi_Ip_HalfDuplexPushDataToFifo(Instance, NumberOfWrites);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if(
|
|
|
+ ((LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType) && (TRUE == TransferCompleted)) ||
|
|
|
+ ((State->RxIndex == State->ExpectedFifoReads) && (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)) ||
|
|
|
+ (TRUE == ErrorFlag)
|
|
|
+ )
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+ Lpspi_Ip_ChannelFinished(Instance, ErrorFlag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function to complete TX channel in HD mode.
|
|
|
+* @details This function to complete TX channel in HD mode.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static boolean Lpspi_Ip_HalfDupleTransmitChannelComplete(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ const Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 TimeoutTicks = OsIf_MicrosToTicks(LPSPI_IP_HALF_DUPLEX_TIMEOUT_COUNTER, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ uint32 CurrentTicks = 0u;
|
|
|
+ uint32 ElapsedTicks = 0u;
|
|
|
+ boolean TimeOutError = FALSE;
|
|
|
+
|
|
|
+
|
|
|
+ if (FALSE == State->KeepCs)
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if (TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ((TRUE == State->NextChannelIsRX) || (FALSE == State->KeepCs))
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ while ((((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK) != 0u) && (ElapsedTicks < TimeoutTicks))
|
|
|
+ {
|
|
|
+ CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ }
|
|
|
+ if(ElapsedTicks >= TimeoutTicks)
|
|
|
+ {
|
|
|
+
|
|
|
+ TimeOutError = TRUE;
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return TimeOutError;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will process to transmit data.
|
|
|
+* @details This function will process to transmit data.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+LOCAL_INLINE boolean Lpspi_Ip_HalfDuplexTransmitProcess(uint8 Instance, uint8 NumberOfWrites)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ boolean TransferCompleted = FALSE;
|
|
|
+
|
|
|
+ if(State->ExpectedFifoWrites != State->TxIndex)
|
|
|
+ {
|
|
|
+ Lpspi_Ip_HalfDuplexPushDataToFifo(Instance, NumberOfWrites);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ if((FALSE == State->KeepCs))
|
|
|
+ {
|
|
|
+
|
|
|
+ if(0u != (Base->TCR & LPSPI_TCR_CONT_MASK))
|
|
|
+ {
|
|
|
+ Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ TransferCompleted = TRUE;
|
|
|
+ }
|
|
|
+ return TransferCompleted;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will perform Transmit data in half duplex mode.
|
|
|
+* @details This function will perform Transmit data in half duplex mode.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+LOCAL_INLINE void Lpspi_Ip_HalfDuplexPushDataToFifo(uint8 Instance, uint8 NumberOfWrites)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint8 WriteToFifoTime = NumberOfWrites;
|
|
|
+
|
|
|
+
|
|
|
+ if (NumberOfWrites > (State->ExpectedFifoWrites - State->TxIndex))
|
|
|
+ {
|
|
|
+ WriteToFifoTime = (uint8)(State->ExpectedFifoWrites - State->TxIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_Ip_PushDataToFifo(Instance, WriteToFifoTime);
|
|
|
+}
|
|
|
+
|
|
|
+* @brief This function will prepare to transfer in half duplex mode.
|
|
|
+* @details This function will prepare to transfer in half duplex mode.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @param[in] Buffer Transfer buffer.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_HalfDuplexPrepare(uint8 Instance, uint8* Buffer)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ uint8 LsbWriteValue = State->TxLsb ? 1U : 0U;
|
|
|
+
|
|
|
+
|
|
|
+ Base->CFGR1 &= ~(LPSPI_CFGR1_PCSCFG_MASK | LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK);
|
|
|
+ Base->CFGR1 |= State->ExternalDevice->HalfDuplexCfgr1;
|
|
|
+
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot = 1u;
|
|
|
+ if(LPSPI_IP_HALF_DUPLEX_TRANSMIT == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ {
|
|
|
+ State->TxBuffer = Buffer;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->RxBuffer = Buffer;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ State->HalfDuplexTcrCommand = State->ExternalDevice->Tcr[State->ClockMode] | LPSPI_TCR_FRAMESZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) | LPSPI_TCR_LSBF(LsbWriteValue);
|
|
|
+ #else
|
|
|
+ State->HalfDuplexTcrCommand = State->ExternalDevice->Tcr | LPSPI_TCR_FRAMESZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) | LPSPI_TCR_LSBF(LsbWriteValue);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+ State->HalfDuplexTcrCommand &= ~LPSPI_TCR_CONT_MASK;
|
|
|
+
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot = 0u;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+
|
|
|
+ State->HalfDuplexTcrCommand |= LPSPI_TCR_TXMSK_MASK;
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function is called by Lpspi_Ip_IrqHandler or Lpspi_Ip_ManageBuffers. It will process transfer in interrupt mode or polling mode.
|
|
|
+* @details This function will fill Data into TX FIFO and read Data in RX FIFO fill to Rx Buffers.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_TransferProcess(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 SrStatusRegister;
|
|
|
+ uint8 NumberOfWrites = 0u;
|
|
|
+ uint8 NumberOfReads = 0u;
|
|
|
+ boolean ErrorFlag = FALSE;
|
|
|
+
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+
|
|
|
+ SrStatusRegister = Base->SR;
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+
|
|
|
+ if ((SrStatusRegister & (LPSPI_SR_REF_MASK | LPSPI_SR_TEF_MASK)) != 0u)
|
|
|
+ {
|
|
|
+
|
|
|
+ ErrorFlag = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ NumberOfReads = (uint8)(((Base->FSR) & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT);
|
|
|
+ if (NumberOfReads != 0u)
|
|
|
+ {
|
|
|
+ if (NumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
|
|
|
+ {
|
|
|
+ NumberOfReads = (uint8)(State->ExpectedFifoReads - State->RxIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ CurrentTxFifoSlot was minus 1 when prepare TX channel */
|
|
|
+ if (0u == State->RxIndex)
|
|
|
+ {
|
|
|
+ State->CurrentTxFifoSlot += 1u;
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_Ip_ReadDataFromFifo(Instance, NumberOfReads);
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot += NumberOfReads;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ to fill TX FIFO. At that time, another interrupt occurred and preemptive current interrupt, and the time to process that interrupt is longer than the time to transfer all frames
|
|
|
+ in TX FIFO. So TX FIFO will be empty and some frames received in RX FIFO, then the program is returned from that interrupt and fill TX FIFO until full and exist SPI interrupt function.
|
|
|
+ And if there is a interrupt occurred with higher priority of SPI interrupt and the time to process that interrupt is longer than the time to transfer all frames in TX FIFO.
|
|
|
+ So, RX FIFO can be overflow due to SPI interrupt function is not serviced to read RX FIFO.
|
|
|
+ State->CurrentTxFifoSlot variable is used to hanlde number of frames are "on bus transfer". They are always less than FIFO size */
|
|
|
+ if((State->CurrentTxFifoSlot != 0u) && (State->TxDoneFlag != TRUE))
|
|
|
+ {
|
|
|
+ if(State->ExpectedFifoWrites != State->TxIndex)
|
|
|
+ {
|
|
|
+ NumberOfWrites = State->CurrentTxFifoSlot;
|
|
|
+
|
|
|
+ if (NumberOfWrites > (State->ExpectedFifoWrites - State->TxIndex))
|
|
|
+ {
|
|
|
+ NumberOfWrites = (uint8)(State->ExpectedFifoWrites - State->TxIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_Ip_PushDataToFifo(Instance, NumberOfWrites);
|
|
|
+ State->CurrentTxFifoSlot -= NumberOfWrites;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(TRUE == State->NextTransferConfigAvailable)
|
|
|
+ {
|
|
|
+
|
|
|
+ State->ExternalDevice->DeviceParams->DefaultData = State->DefaultDataNext;
|
|
|
+ State->FirstCmd = FALSE;
|
|
|
+ Lpspi_TransmitTxInit(Instance, State->TxBufferNext, State->FrameSizeNext, State->LsbNext, State->LengthNext);
|
|
|
+ State->NextTransferConfigAvailable = FALSE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->TxDoneFlag = TRUE;
|
|
|
+
|
|
|
+ Base->IER &= ~LPSPI_IER_TDIE_MASK;
|
|
|
+ if((FALSE == State->KeepCs) && (0u != (Base->TCR & LPSPI_TCR_CONT_MASK)))
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if((State->RxIndex == State->ExpectedFifoReads) || (TRUE == ErrorFlag))
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if ( ((FALSE == State->KeepCs) || (TRUE == ErrorFlag)) && (TRUE == State->PhyUnitConfig->SlaveMode) )
|
|
|
+ {
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_12();
|
|
|
+
|
|
|
+ Base->TCR |= LPSPI_TCR_RXMSK(1);
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_12();
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+ Lpspi_Ip_ChannelFinished(Instance, ErrorFlag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+
|
|
|
+* @brief This function will verify the validation of some input parameters of transmision functions.
|
|
|
+* @details This function will verify the validation of some input parameters of transmision functions.
|
|
|
+*
|
|
|
+* @param[in] ExternalDevice Pointer to the external device where data is transmitted.
|
|
|
+* @param[in] Length Number of bytes to be sent.
|
|
|
+* @return LPSPI_IP_STATUS_SUCCESS: Don't have any errors was found.
|
|
|
+* LPSPI_IP_STATUS_FAIL: Transmission command has not been accepted.
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_CheckValidParameters(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint16 Length
|
|
|
+ )
|
|
|
+{
|
|
|
+
|
|
|
+ if (ExternalDevice->DeviceParams->FrameSize > 16u)
|
|
|
+ {
|
|
|
+ DevAssert((Length%4) == 0u);
|
|
|
+ }
|
|
|
+ else if (ExternalDevice->DeviceParams->FrameSize > 8u)
|
|
|
+ {
|
|
|
+ DevAssert((Length%2) == 0u);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT)
|
|
|
+static void Lpspi_Ip_TxDmaTcdSGInit(uint8 Instance)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State = (const Lpspi_Ip_StateStructureType*)Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[9u];
|
|
|
+ uint8 TcdSgIndex = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+
|
|
|
+ DmaTcdList[1u].Value = 0u;
|
|
|
+ DmaTcdList[2u].Value = 1u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 1u;
|
|
|
+ DmaTcdList[6u].Value = 0u;
|
|
|
+ DmaTcdList[7u].Value = 0u;
|
|
|
+ DmaTcdList[8u].Value = 1u;
|
|
|
+ DmaTcdList[0u].Value = 0u;
|
|
|
+
|
|
|
+ for(TcdSgIndex = 0u; TcdSgIndex < State->PhyUnitConfig->MaxNumOfFastTransfer; TcdSgIndex++)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TcdSgIndex], DmaTcdList, 9u);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_CmdTxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint32 CmdAdd, uint8 DisHwReq)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = (const LPSPI_Type *)Lpspi_Ip_apxBases[Instance];
|
|
|
+ const Lpspi_Ip_StateStructureType* State = (const Lpspi_Ip_StateStructureType *)Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[9u];
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = CmdAdd;
|
|
|
+ DmaTcdList[1u].Value = (uint32)&Base->TCR;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 4u;
|
|
|
+ DmaTcdList[6u].Value = 1u;
|
|
|
+ DmaTcdList[7u].Value = DisHwReq;
|
|
|
+ DmaTcdList[8u].Value = DisHwReq;
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TcdSgIndex], DmaTcdList, 9u);
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_TxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint8 DisHwReq, const uint32 *DefaultDataAddress)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[9u];
|
|
|
+
|
|
|
+
|
|
|
+ State->TxIndex = State->ExpectedFifoWrites;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+ DmaTcdList[1u].Value = (uint32)&Base->TDR;
|
|
|
+ if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 1u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 1u;
|
|
|
+ }
|
|
|
+ else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 2u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 4u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 4u;
|
|
|
+ }
|
|
|
+ DmaTcdList[6u].Value = State->ExpectedFifoWrites;
|
|
|
+ DmaTcdList[7u].Value = DisHwReq;
|
|
|
+ DmaTcdList[8u].Value = DisHwReq;
|
|
|
+ if (NULL_PTR == State->TxBuffer)
|
|
|
+ {
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = (uint32)DefaultDataAddress;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[0u].Value = (uint32)State->TxBuffer;
|
|
|
+
|
|
|
+ (void)DefaultDataAddress;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TcdSgIndex], DmaTcdList, 9u);
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_RxDmaTcdSGInit(uint8 Instance)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ const Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[9u];
|
|
|
+ uint8 TcdSgIndex = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = (uint32)&Base->RDR;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 1u;
|
|
|
+ DmaTcdList[6u].Value = 1u;
|
|
|
+ DmaTcdList[1u].Value = 0u;
|
|
|
+ DmaTcdList[7u].Value = 0u;
|
|
|
+ DmaTcdList[8u].Value = 1u;
|
|
|
+
|
|
|
+ for(TcdSgIndex = 0u; TcdSgIndex < State->PhyUnitConfig->MaxNumOfFastTransfer; TcdSgIndex++)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[TcdSgIndex], DmaTcdList, 9u);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_RxDmaTcdSGConfig(uint8 Instance, uint8 TcdSgIndex, uint8 DisHwReq)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[8u];
|
|
|
+
|
|
|
+
|
|
|
+ State->RxIndex = State->ExpectedFifoReads;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+
|
|
|
+ if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
|
|
|
+ {
|
|
|
+ DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[3u].Value = 1u;
|
|
|
+ DmaTcdList[4u].Value = 1u;
|
|
|
+ }
|
|
|
+ else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
|
|
|
+ {
|
|
|
+ DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[3u].Value = 2u;
|
|
|
+ DmaTcdList[4u].Value = 2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[3u].Value = 4u;
|
|
|
+ DmaTcdList[4u].Value = 4u;
|
|
|
+ }
|
|
|
+ if (NULL_PTR == State->RxBuffer)
|
|
|
+ {
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = (uint32)&Lpspi_Ip_u32DiscardData;
|
|
|
+ DmaTcdList[4u].Value = 0u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[0u].Value = (uint32)State->RxBuffer;
|
|
|
+ }
|
|
|
+ DmaTcdList[5u].Value = State->ExpectedFifoReads;
|
|
|
+ DmaTcdList[6u].Value = DisHwReq;
|
|
|
+ DmaTcdList[7u].Value = DisHwReq;
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[TcdSgIndex], DmaTcdList, 8u);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will configure hardware TCDs for the channels TX DMA, RX DMA
|
|
|
+* according to current transfer configuration. DMA channels will be started at the end of the function.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_TxDmaConfig(uint8 Instance)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = (const LPSPI_Type*)Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[10u];
|
|
|
+ uint16 NumberDmaIterWrite = State->ExpectedFifoWrites;
|
|
|
+
|
|
|
+
|
|
|
+ if (LPSPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterWrite)
|
|
|
+ {
|
|
|
+ NumberDmaIterWrite = LPSPI_IP_DMA_MAX_ITER_CNT_U16;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ State->TxIndex = NumberDmaIterWrite;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+ DmaTcdList[9u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_LAST_ADDR_ADJ;
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ {
|
|
|
+ DmaTcdList[0u].Value = (uint32)&State->HalfDuplexTcrCommand;
|
|
|
+ DmaTcdList[1u].Value = (uint32)&Base->TCR;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 4u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ DmaTcdList[1u].Value = (uint32)&Base->TDR;
|
|
|
+ if (State->TxFrameSize < 9u)
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 1u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 1u;
|
|
|
+ }
|
|
|
+ else if (State->TxFrameSize < 17u)
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 2u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[2u].Value = 4u;
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 4u;
|
|
|
+ }
|
|
|
+ if (NULL_PTR == State->TxBuffer)
|
|
|
+ {
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = (uint32)&State->ExternalDevice->DeviceParams->DefaultData;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[0u].Value = (uint32)State->TxBuffer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DmaTcdList[6u].Value = 0u;
|
|
|
+ DmaTcdList[7u].Value = NumberDmaIterWrite;
|
|
|
+ DmaTcdList[8u].Value = 1u;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[9u].Value = 0u;
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 10u);
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will configure hardware TCDs for the channels TX DMA, RX DMA
|
|
|
+* according to current transfer configuration. DMA channels will be started at the end of the function.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_RxDmaConfig(uint8 Instance)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[10u];
|
|
|
+ uint16 NumberDmaIterRead = State->ExpectedFifoReads;
|
|
|
+
|
|
|
+
|
|
|
+ if (LPSPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterRead)
|
|
|
+ {
|
|
|
+ NumberDmaIterRead = LPSPI_IP_DMA_MAX_ITER_CNT_U16;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ State->RxIndex = NumberDmaIterRead;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
|
|
|
+ DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
|
|
|
+ DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
|
|
|
+ DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
|
|
|
+ DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
|
|
|
+ DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
|
|
|
+ DmaTcdList[9u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_LAST_ADDR_ADJ;
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = (uint32)&Base->RDR;
|
|
|
+ DmaTcdList[2u].Value = 0u;
|
|
|
+ if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
|
|
|
+ {
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 1u;
|
|
|
+ DmaTcdList[6u].Value = 1u;
|
|
|
+ }
|
|
|
+ else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
|
|
|
+ {
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 2u;
|
|
|
+ DmaTcdList[6u].Value = 2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;
|
|
|
+ DmaTcdList[5u].Value = 4u;
|
|
|
+ DmaTcdList[6u].Value = 4u;
|
|
|
+ }
|
|
|
+ if (NULL_PTR == State->RxBuffer)
|
|
|
+ {
|
|
|
+
|
|
|
+ DmaTcdList[1u].Value = (uint32)&Lpspi_Ip_u32DiscardData;
|
|
|
+ DmaTcdList[6u].Value = 0u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DmaTcdList[1u].Value = (uint32)State->RxBuffer;
|
|
|
+ }
|
|
|
+ DmaTcdList[7u].Value = NumberDmaIterRead;
|
|
|
+ DmaTcdList[8u].Value = 1u;
|
|
|
+
|
|
|
+ DmaTcdList[9u].Value = 0u;
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 10u);
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_TxDmaContinueTransfer(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
|
|
|
+ uint16 NumberDmaIterWrite = State->ExpectedFifoWrites - State->TxIndex;
|
|
|
+
|
|
|
+
|
|
|
+ if (LPSPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterWrite)
|
|
|
+ {
|
|
|
+ NumberDmaIterWrite = LPSPI_IP_DMA_MAX_ITER_CNT_U16;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ State->TxIndex += NumberDmaIterWrite;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[0u].Value = NumberDmaIterWrite;
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 1u);
|
|
|
+
|
|
|
+
|
|
|
+ TX DMA request will be enabled later when RX DMA complete by Lpspi_Ip_RxDmaContinueTransfer. */
|
|
|
+ Base->DER &= ~LPSPI_DER_TDDE_MASK;
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_SOFTWARE_REQUEST);
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_Ip_RxDmaContinueTransfer(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
|
|
|
+ uint16 NumberDmaIterRead = State->ExpectedFifoReads - State->RxIndex;
|
|
|
+
|
|
|
+
|
|
|
+ if (LPSPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterRead)
|
|
|
+ {
|
|
|
+ NumberDmaIterRead = LPSPI_IP_DMA_MAX_ITER_CNT_U16;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ State->RxIndex += NumberDmaIterRead;
|
|
|
+
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
|
|
|
+ DmaTcdList[0u].Value = NumberDmaIterRead;
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 1u);
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+
|
|
|
+ Base->DER |= LPSPI_DER_TDDE_MASK;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will finish channel transmission via DMA.
|
|
|
+* @details This function will finish channel transmission via DMA.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_TxDmaFinishTransfer(const uint8 Instance)
|
|
|
+{
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ Lpspi_Ip_HalfDuplexType TransferType;
|
|
|
+ uint32 CurrentTicks = 0u;
|
|
|
+ uint32 ElapsedTicks = 0u;
|
|
|
+ uint32 TimeoutTicks = OsIf_MicrosToTicks(LPSPI_IP_HALF_DUPLEX_TIMEOUT_COUNTER, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ #endif
|
|
|
+ LPSPI_Type *Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType *State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ TransferType = State->ExternalDevice->DeviceParams->TransferType;
|
|
|
+ if (((TRUE == State->NextChannelIsRX) && (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType)) || (FALSE == State->KeepCs))
|
|
|
+ #else
|
|
|
+ if (FALSE == State->KeepCs)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ if (FALSE == State->KeepCs)
|
|
|
+ {
|
|
|
+
|
|
|
+ if (0u != (Base->TCR & LPSPI_TCR_CONT_MASK))
|
|
|
+ {
|
|
|
+ Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ while ((((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK) != 0u) && (ElapsedTicks < TimeoutTicks))
|
|
|
+ {
|
|
|
+ CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ }
|
|
|
+ if(ElapsedTicks >= TimeoutTicks)
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_FULL_DUPLEX == TransferType)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ if (TRUE == State->NextTransferConfigAvailable)
|
|
|
+ {
|
|
|
+
|
|
|
+ State->ExternalDevice->DeviceParams->DefaultData = State->DefaultDataNext;
|
|
|
+ State->FirstCmd = FALSE;
|
|
|
+ Lpspi_TransmitTxInit(Instance, State->TxBufferNext, State->FrameSizeNext, State->LsbNext, State->LengthNext);
|
|
|
+ State->NextTransferConfigAvailable = FALSE;
|
|
|
+
|
|
|
+ TX DMA request will be enabled later when RX DMA completed and next transfer initialized by Lpspi_Ip_AsyncTransmit. */
|
|
|
+ Base->DER &= ~LPSPI_DER_TDDE_MASK;
|
|
|
+ Lpspi_Ip_TxDmaConfig(Instance);
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_SOFTWARE_REQUEST);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ State->NextTransferDone = TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* GLOBAL FUNCTIONS
|
|
|
+==================================================================================================*/
|
|
|
+
|
|
|
+* @brief This function will process TX DMA transfer complete interrupt.
|
|
|
+* @details This function will process continue transfer or end of transfer via TX DMA.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+* @implements Lpspi_Ip_IrqTxDmaHandler_Activity
|
|
|
+*/
|
|
|
+void Lpspi_Ip_IrqTxDmaHandler(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 SrStatusRegister = 0u;
|
|
|
+ boolean ErrorFlag = FALSE;
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ boolean EndOfTransferFlag = FALSE;
|
|
|
+ Lpspi_Ip_HalfDuplexType TransferType;
|
|
|
+ Lpspi_Ip_EventType EventState = LPSPI_IP_EVENT_FAULT;
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (NULL_PTR != State)
|
|
|
+ {
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ TransferType = State->ExternalDevice->DeviceParams->TransferType;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ SrStatusRegister = Base->SR;
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+
|
|
|
+ if ((SrStatusRegister & (LPSPI_SR_REF_MASK | LPSPI_SR_TEF_MASK)) != 0u)
|
|
|
+ {
|
|
|
+
|
|
|
+ ErrorFlag = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (State->ExpectedFifoWrites != State->TxIndex)
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_TxDmaContinueTransfer(Instance);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ TransferType = State->ExternalDevice->DeviceParams->TransferType;
|
|
|
+
|
|
|
+
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType)
|
|
|
+ {
|
|
|
+ EndOfTransferFlag = TRUE;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ Lpspi_Ip_TxDmaFinishTransfer(Instance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if ((TRUE == ErrorFlag) || (TRUE == EndOfTransferFlag))
|
|
|
+ #else
|
|
|
+ if (TRUE == ErrorFlag)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_13();
|
|
|
+
|
|
|
+ Base->TCR |= LPSPI_TCR_RXMSK(1);
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_13();
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType)
|
|
|
+ {
|
|
|
+ if(TRUE == ErrorFlag)
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+ EventState = LPSPI_IP_EVENT_FAULT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ EventState = LPSPI_IP_EVENT_END_TRANSFER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (NULL_PTR != State->Callback)
|
|
|
+ {
|
|
|
+ State->Callback(Instance, EventState);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+
|
|
|
+ if (State->Callback != NULL_PTR)
|
|
|
+ {
|
|
|
+ State->Callback(Instance, LPSPI_IP_EVENT_FAULT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will process RX DMA transfer complete interrupt.
|
|
|
+* @details This function will process continue transfer or end of transfer via RX DMA.
|
|
|
+*
|
|
|
+* @param[in] Instance Index of the hardware instance.
|
|
|
+* @return void
|
|
|
+* @implements Lpspi_Ip_IrqRxDmaHandler_Activity
|
|
|
+*/
|
|
|
+void Lpspi_Ip_IrqRxDmaHandler(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 SrStatusRegister = 0u;
|
|
|
+ boolean ErrorFlag = FALSE;
|
|
|
+ boolean EndOfTransferFlag = FALSE;
|
|
|
+
|
|
|
+ if (NULL_PTR != State)
|
|
|
+ {
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+
|
|
|
+ SrStatusRegister = Base->SR;
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+
|
|
|
+ if ((SrStatusRegister & (LPSPI_SR_REF_MASK | LPSPI_SR_TEF_MASK)) != 0u)
|
|
|
+ {
|
|
|
+
|
|
|
+ ErrorFlag = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (State->ExpectedFifoReads != State->RxIndex)
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_RxDmaContinueTransfer(Instance);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ EndOfTransferFlag = TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((TRUE == EndOfTransferFlag) || (TRUE == ErrorFlag))
|
|
|
+ {
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_14();
|
|
|
+
|
|
|
+ Base->TCR |= LPSPI_TCR_RXMSK(1);
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_14();
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ if(TRUE == ErrorFlag)
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ }
|
|
|
+ if (State->Callback != NULL_PTR)
|
|
|
+ {
|
|
|
+ if(TRUE == ErrorFlag)
|
|
|
+ {
|
|
|
+ State->Callback(Instance, LPSPI_IP_EVENT_FAULT);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Callback(Instance, LPSPI_IP_EVENT_END_TRANSFER);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_USER_MODE_SUPPORT)
|
|
|
+
|
|
|
+* @brief This function will set UAA bit in REG_PROT for SPI unit
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_SetUserAccess(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+
|
|
|
+ SET_USER_ACCESS_ALLOWED((uint32)Base,LPSPI_IP_PROT_MEM_U32);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will enable writing all SPI registers under protection in User mode by configuring REG_PROT
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_SetUserAccessAllowed(uint8 Instance)
|
|
|
+{
|
|
|
+ OsIf_Trusted_Call1param(Lpspi_Ip_SetUserAccess, Instance);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_Init(const Lpspi_Ip_ConfigType *PhyUnitConfigPtr)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(PhyUnitConfigPtr != NULL_PTR);
|
|
|
+ #endif
|
|
|
+ Instance = PhyUnitConfigPtr->Instance;
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(State == NULL_PTR);
|
|
|
+ #endif
|
|
|
+ Lpspi_Ip_apxStateStructureArray[Instance] = &Lpspi_Ip_axStateStructure[PhyUnitConfigPtr->StateIndex];
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ State->PhyUnitConfig = PhyUnitConfigPtr;
|
|
|
+
|
|
|
+ Base->CR = PhyUnitConfigPtr->Cr | LPSPI_CR_DBGEN_MASK;
|
|
|
+ Base->CFGR1 = PhyUnitConfigPtr->Cfgr1;
|
|
|
+
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER((uint32)LPSPI_IP_FIFO_SIZE_U8 - (uint32)1u);
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ State->ClockMode = LPSPI_IP_NORMAL_CLOCK;
|
|
|
+ #endif
|
|
|
+ State->KeepCs = FALSE;
|
|
|
+ State->FirstCmd = TRUE;
|
|
|
+ #if ((STD_ON == LPSPI_IP_DMA_USED) && (STD_ON == LPSPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT))
|
|
|
+ Lpspi_Ip_TxDmaTcdSGInit(Instance);
|
|
|
+ Lpspi_Ip_RxDmaTcdSGInit(Instance);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ (void)Lpspi_Ip_UpdateTransferMode(Instance, PhyUnitConfigPtr->TransferMode);
|
|
|
+
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_MEN_MASK;
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_DeInit(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RST(1u);
|
|
|
+ Base->CR = 0;
|
|
|
+
|
|
|
+ Lpspi_Ip_apxStateStructureArray[Instance] = NULL_PTR;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_SyncTransmit(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint8 *TxBuffer,
|
|
|
+ uint8 *RxBuffer,
|
|
|
+ uint16 Length,
|
|
|
+ uint32 TimeOut
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type *Base;
|
|
|
+ Lpspi_Ip_StateStructureType *State;
|
|
|
+ uint8 NumberOfWrites, NumberOfReads;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint32 TimeoutTicks = OsIf_MicrosToTicks(TimeOut, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ uint32 CurrentTicks = 0u;
|
|
|
+ uint32 ElapsedTicks = 0u;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+ boolean TxDoneFlag = FALSE;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(ExternalDevice != NULL_PTR);
|
|
|
+ DevAssert(0u != Length);
|
|
|
+ DevAssert(0u != TimeOut);
|
|
|
+ Lpspi_Ip_CheckValidParameters(ExternalDevice, Length);
|
|
|
+ #endif
|
|
|
+ Instance = ExternalDevice->Instance;
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(State != NULL_PTR);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+ Base->CFGR1 &= ~(LPSPI_CFGR1_PCSCFG_MASK | LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK);
|
|
|
+ #endif
|
|
|
+
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_BUSY;
|
|
|
+ State->ExternalDevice = ExternalDevice;
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ Base->IER = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ State->NextTransferConfigAvailable = State->KeepCs;
|
|
|
+
|
|
|
+
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK|LPSPI_CR_RRF_MASK;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ Base->CCR = ExternalDevice->Ccr[State->ClockMode];
|
|
|
+ #else
|
|
|
+ Base->CCR = ExternalDevice->Ccr;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot = LPSPI_IP_FIFO_SIZE_U8;
|
|
|
+ Lpspi_TransmitTxInit(Instance, TxBuffer, State->ExternalDevice->DeviceParams->FrameSize, State->ExternalDevice->DeviceParams->Lsb, Length);
|
|
|
+ }
|
|
|
+ Lpspi_TransmitRxInit(Instance, RxBuffer, State->ExternalDevice->DeviceParams->FrameSize, Length);
|
|
|
+
|
|
|
+ CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ while(State->RxIndex != State->ExpectedFifoReads)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ , it should be read to clear RXFIFO before start a new write to TXFIFO */
|
|
|
+
|
|
|
+ NumberOfReads = (uint8)(((Base->FSR) & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT);
|
|
|
+
|
|
|
+
|
|
|
+ if (NumberOfReads != 0u)
|
|
|
+ {
|
|
|
+ if (NumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
|
|
|
+ {
|
|
|
+ NumberOfReads = (uint8)(State->ExpectedFifoReads - State->RxIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (0u == State->RxIndex)
|
|
|
+ {
|
|
|
+ State->CurrentTxFifoSlot += 1u;
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_Ip_ReadDataFromFifo(Instance, NumberOfReads);
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot += NumberOfReads;
|
|
|
+ ElapsedTicks = 0u;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ to prepare to fill TX FIFO. At that time, interrupt occurred, and the time to process interrupt is longer than the time to transfer all frames in TX FIFO.
|
|
|
+ So TX FIFO will be empty and some frames received in RX FIFO, then the program is returned from interrupt and fill TX FIFO until full.
|
|
|
+ And there is a interrupt occurred after that before read all frames in RX FIFO, and the time to process interrupt is longer than the time to transfer all frames in TX FIFO.
|
|
|
+ State->CurrentTxFifoSlot variable is used to hanlde number of frames are "on bus transfer". They are always less than FIFO size */
|
|
|
+ if((State->CurrentTxFifoSlot != 0u) && (TxDoneFlag != TRUE))
|
|
|
+ {
|
|
|
+ if(State->ExpectedFifoWrites != State->TxIndex)
|
|
|
+ {
|
|
|
+ NumberOfWrites = State->CurrentTxFifoSlot;
|
|
|
+
|
|
|
+ if (NumberOfWrites > (State->ExpectedFifoWrites - State->TxIndex))
|
|
|
+ {
|
|
|
+ NumberOfWrites = (uint8)(State->ExpectedFifoWrites - State->TxIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_Ip_PushDataToFifo(Instance, NumberOfWrites);
|
|
|
+ State->CurrentTxFifoSlot -= NumberOfWrites;
|
|
|
+ ElapsedTicks = 0u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(TRUE == State->NextTransferConfigAvailable)
|
|
|
+ {
|
|
|
+
|
|
|
+ State->ExternalDevice->DeviceParams->DefaultData = State->DefaultDataNext;
|
|
|
+ State->FirstCmd = FALSE;
|
|
|
+ Lpspi_TransmitTxInit(Instance, State->TxBufferNext, State->FrameSizeNext, State->LsbNext, State->LengthNext);
|
|
|
+ State->NextTransferConfigAvailable = FALSE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TxDoneFlag = TRUE;
|
|
|
+ if((FALSE == State->KeepCs) && (0u != (Base->TCR & LPSPI_TCR_CONT_MASK)))
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ if (ElapsedTicks >= TimeoutTicks)
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_TIMEOUT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (LPSPI_IP_STATUS_SUCCESS != Status)
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_SyncTransmitHalfDuplex(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint8 *Buffer,
|
|
|
+ uint16 Length,
|
|
|
+ Lpspi_Ip_HalfDuplexType TransferType,
|
|
|
+ uint32 TimeOut
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type *Base;
|
|
|
+ Lpspi_Ip_StateStructureType *State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint32 TimeoutTicks = OsIf_MicrosToTicks(TimeOut, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ uint32 CurrentTicks = 0u;
|
|
|
+ uint32 ElapsedTicks = 0u;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+ boolean TransferCompleted = FALSE;
|
|
|
+ uint8 NumberOfFramesTxFifo;
|
|
|
+ uint8 NumberOfWrites;
|
|
|
+ uint8 NumberOfReads;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(ExternalDevice != NULL_PTR);
|
|
|
+ DevAssert(0u != Length);
|
|
|
+ Lpspi_Ip_CheckValidParameters(ExternalDevice, Length);
|
|
|
+ #endif
|
|
|
+ Instance = ExternalDevice->Instance;
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(State != NULL_PTR);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_BUSY;
|
|
|
+ State->ExternalDevice = ExternalDevice;
|
|
|
+
|
|
|
+ State->ExternalDevice->DeviceParams->TransferType = TransferType;
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_HalfDuplexPrepare(Instance, Buffer);
|
|
|
+
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ Base->IER = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ State->NextTransferConfigAvailable = State->KeepCs;
|
|
|
+
|
|
|
+
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK|LPSPI_CR_RRF_MASK;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ Base->CCR = ExternalDevice->Ccr[State->ClockMode];
|
|
|
+ #else
|
|
|
+ Base->CCR = ExternalDevice->Ccr;
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_TransmitTxInit(Instance, NULL_PTR, State->ExternalDevice->DeviceParams->FrameSize, State->ExternalDevice->DeviceParams->Lsb, Length);
|
|
|
+
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)
|
|
|
+ {
|
|
|
+ Lpspi_TransmitRxInit(Instance, NULL_PTR, State->ExternalDevice->DeviceParams->FrameSize, Length);
|
|
|
+ }
|
|
|
+
|
|
|
+ CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ while((TRUE != TransferCompleted) && (LPSPI_IP_STATUS_SUCCESS == Status))
|
|
|
+ {
|
|
|
+ if(LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ NumberOfReads = (uint8)(((Base->FSR) & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT);
|
|
|
+ if (NumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
|
|
|
+ {
|
|
|
+ NumberOfReads = (uint8)(State->ExpectedFifoReads - State->RxIndex);
|
|
|
+ }
|
|
|
+ if (0u != NumberOfReads)
|
|
|
+ {
|
|
|
+ Lpspi_Ip_ReadDataFromFifo(Instance, NumberOfReads);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ((0u == ((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK)) && (State->ExpectedFifoWrites != State->TxIndex))
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR = State->HalfDuplexTcrCommand;
|
|
|
+ State->TxIndex++;
|
|
|
+ }
|
|
|
+ ElapsedTicks = 0u;
|
|
|
+ if (State->ExpectedFifoReads == State->RxIndex)
|
|
|
+ {
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ NumberOfFramesTxFifo = (uint8)(((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK) >> LPSPI_FSR_TXCOUNT_SHIFT);
|
|
|
+ NumberOfWrites = LPSPI_IP_FIFO_SIZE_U8 - NumberOfFramesTxFifo;
|
|
|
+ if(0u != NumberOfWrites)
|
|
|
+ {
|
|
|
+ TransferCompleted = Lpspi_Ip_HalfDuplexTransmitProcess(Instance, NumberOfWrites);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ((TRUE == TransferCompleted) && ((TRUE == State->NextChannelIsRX) || (FALSE == State->KeepCs)))
|
|
|
+ {
|
|
|
+ TransferCompleted = FALSE;
|
|
|
+ if (((Base->FSR) & LPSPI_FSR_TXCOUNT_MASK) == 0u)
|
|
|
+ {
|
|
|
+ TransferCompleted = TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ElapsedTicks = 0u;
|
|
|
+ }
|
|
|
+ ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
|
|
|
+ if (ElapsedTicks >= TimeoutTicks)
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_TIMEOUT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (LPSPI_IP_STATUS_SUCCESS != Status)
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_FAULT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static void Lpspi_TransmitTxInit(uint8 Instance,
|
|
|
+ uint8* TxBuffer,
|
|
|
+ uint8 TxFrameSize,
|
|
|
+ boolean TxLsb,
|
|
|
+ uint16 NumberOfFrames
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 TransferCommand = 0u;
|
|
|
+ uint8 LsbWriteValue = TxLsb ? 1U : 0U;
|
|
|
+
|
|
|
+ State->TxFrameSize = TxFrameSize;
|
|
|
+ State->TxLsb = TxLsb;
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ TransferCommand = State->ExternalDevice->Tcr[State->ClockMode] | LPSPI_TCR_FRAMESZ((uint32)TxFrameSize - 1u) | LPSPI_TCR_LSBF(LsbWriteValue);
|
|
|
+#else
|
|
|
+ TransferCommand = State->ExternalDevice->Tcr | LPSPI_TCR_FRAMESZ((uint32)TxFrameSize - 1u) | LPSPI_TCR_LSBF(LsbWriteValue);
|
|
|
+#endif
|
|
|
+#if ((STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT) && (STD_ON == LPSPI_IP_SLAVE_SUPPORT))
|
|
|
+
|
|
|
+ if ((LPSPI_IP_HALF_DUPLEX_RECEIVE == State->ExternalDevice->DeviceParams->TransferType) && (TRUE == State->PhyUnitConfig->SlaveMode))
|
|
|
+ {
|
|
|
+
|
|
|
+ TransferCommand |= LPSPI_TCR_TXMSK_MASK;
|
|
|
+ TransferCommand &= ~LPSPI_TCR_CONT_MASK;
|
|
|
+ Base->TCR = TransferCommand;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE != State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_TRANSMIT == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ {
|
|
|
+
|
|
|
+ TransferCommand |= LPSPI_TCR_RXMSK_MASK;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+ TransferCommand &= ~LPSPI_TCR_CONT_MASK;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR = TransferCommand;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (0u != (TransferCommand & LPSPI_TCR_CONT_MASK))
|
|
|
+ {
|
|
|
+ Base->TCR = TransferCommand | LPSPI_TCR_CONTC_MASK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Base->TCR = TransferCommand;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_FULL_DUPLEX == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot -= 1u;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ State->TxIndex = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_FULL_DUPLEX == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ State->TxBuffer = TxBuffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (TxFrameSize < 9u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = NumberOfFrames;
|
|
|
+ }
|
|
|
+ else if (TxFrameSize < 17u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = NumberOfFrames/2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = NumberOfFrames/4u;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void Lpspi_TransmitRxInit(uint8 Instance,
|
|
|
+ uint8* RxBuffer,
|
|
|
+ uint8 RxFrameSize,
|
|
|
+ uint16 NumberOfFrames
|
|
|
+ )
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+
|
|
|
+
|
|
|
+ State->RxIndex = 0u;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_FULL_DUPLEX != State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ {
|
|
|
+ (void)RxBuffer;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ State->RxBuffer = RxBuffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (RxFrameSize < 9u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoReads = NumberOfFrames;
|
|
|
+ }
|
|
|
+ else if (RxFrameSize < 17u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoReads = NumberOfFrames/2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->ExpectedFifoReads = NumberOfFrames/4u;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_AsyncTransmit(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint8 *TxBuffer,
|
|
|
+ uint8 *RxBuffer,
|
|
|
+ uint16 Length,
|
|
|
+ Lpspi_Ip_CallbackType EndCallback
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(ExternalDevice != NULL_PTR);
|
|
|
+ DevAssert(0u != Length);
|
|
|
+ Lpspi_Ip_CheckValidParameters(ExternalDevice, Length);
|
|
|
+ #endif
|
|
|
+ Instance = ExternalDevice->Instance;
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(State != NULL_PTR);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+ Base->CFGR1 &= ~(LPSPI_CFGR1_PCSCFG_MASK | LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_BUSY;
|
|
|
+ State->ExternalDevice = ExternalDevice;
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+
|
|
|
+
|
|
|
+ State->Callback = EndCallback;
|
|
|
+ State->NextTransferConfigAvailable = State->KeepCs;
|
|
|
+
|
|
|
+
|
|
|
+ State->TxDoneFlag = FALSE;
|
|
|
+
|
|
|
+
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_11();
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK|LPSPI_CR_RRF_MASK;
|
|
|
+
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(FALSE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ Base->CCR = ExternalDevice->Ccr[State->ClockMode];
|
|
|
+ #else
|
|
|
+ Base->CCR = ExternalDevice->Ccr;
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+ State->CurrentTxFifoSlot = LPSPI_IP_FIFO_SIZE_U8;
|
|
|
+
|
|
|
+ Lpspi_TransmitTxInit(Instance, TxBuffer, State->ExternalDevice->DeviceParams->FrameSize, State->ExternalDevice->DeviceParams->Lsb, Length);
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_11();
|
|
|
+ }
|
|
|
+ Lpspi_TransmitRxInit(Instance, RxBuffer, State->ExternalDevice->DeviceParams->FrameSize, Length);
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ if (FALSE == State->PhyUnitConfig->DmaUsed)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if (TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER(0u);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER((uint32)LPSPI_IP_FIFO_SIZE_U8 - (uint32)1u);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ switch (State->TransferMode)
|
|
|
+ {
|
|
|
+ case LPSPI_IP_POLLING:
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+ break;
|
|
|
+ case LPSPI_IP_INTERRUPT:
|
|
|
+ Base->IER = LPSPI_IER_RDIE_MASK | LPSPI_IER_TDIE_MASK | LPSPI_IER_REIE_MASK | LPSPI_IER_TEIE_MASK;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+ switch(State->TransferMode)
|
|
|
+ {
|
|
|
+ case LPSPI_IP_POLLING:
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = 0u;
|
|
|
+ break;
|
|
|
+ case LPSPI_IP_INTERRUPT:
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = 1u;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ fill CMD and the first frame of next channel */
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER((uint32)LPSPI_IP_FIFO_SIZE_U8 - (uint32)3u);
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 1u);
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 1u);
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_RxDmaConfig(Instance);
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_TxDmaConfig(Instance);
|
|
|
+ }
|
|
|
+
|
|
|
+ Base->DER = LPSPI_DER_RDDE_MASK | LPSPI_DER_TDDE_MASK;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_AsyncTransmitHalfDuplex(
|
|
|
+ const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
|
|
|
+ uint8 *Buffer,
|
|
|
+ uint16 Length,
|
|
|
+ Lpspi_Ip_HalfDuplexType TransferType,
|
|
|
+ Lpspi_Ip_CallbackType EndCallback
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+ uint32 InterruptEnable = 0u;
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(ExternalDevice != NULL_PTR);
|
|
|
+ DevAssert(0u != Length);
|
|
|
+ Lpspi_Ip_CheckValidParameters(ExternalDevice, Length);
|
|
|
+ #endif
|
|
|
+ Instance = ExternalDevice->Instance;
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(State != NULL_PTR);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_BUSY;
|
|
|
+ State->ExternalDevice = ExternalDevice;
|
|
|
+
|
|
|
+ State->ExternalDevice->DeviceParams->TransferType = TransferType;
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_HalfDuplexPrepare(Instance, Buffer);
|
|
|
+
|
|
|
+
|
|
|
+ State->Callback = EndCallback;
|
|
|
+ State->NextTransferConfigAvailable = State->KeepCs;
|
|
|
+
|
|
|
+
|
|
|
+ if(TRUE == State->FirstCmd)
|
|
|
+ {
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_11();
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK|LPSPI_CR_RRF_MASK;
|
|
|
+
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if(FALSE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ Base->CCR = ExternalDevice->Ccr[State->ClockMode];
|
|
|
+ #else
|
|
|
+ Base->CCR = ExternalDevice->Ccr;
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_11();
|
|
|
+ }
|
|
|
+
|
|
|
+ Lpspi_TransmitTxInit(Instance, NULL_PTR, State->ExternalDevice->DeviceParams->FrameSize, State->ExternalDevice->DeviceParams->Lsb, Length);
|
|
|
+
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)
|
|
|
+ {
|
|
|
+ Lpspi_TransmitRxInit(Instance, NULL_PTR, State->ExternalDevice->DeviceParams->FrameSize, Length);
|
|
|
+ }
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if ((TRUE == State->PhyUnitConfig->SlaveMode) && (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType))
|
|
|
+ {
|
|
|
+
|
|
|
+ InterruptEnable = LPSPI_IER_RDIE_MASK | LPSPI_IER_REIE_MASK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ InterruptEnable = LPSPI_IER_RDIE_MASK | LPSPI_IER_TDIE_MASK | LPSPI_IER_REIE_MASK | LPSPI_IER_TEIE_MASK;
|
|
|
+ }
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ if (FALSE == State->PhyUnitConfig->DmaUsed)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ On Slave receive mode, do not care about TX WATER because TDIE flag is not set */
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_RECEIVE == TransferType)
|
|
|
+ {
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER(0u);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER((uint32)LPSPI_IP_FIFO_SIZE_U8 - (uint32)1u);
|
|
|
+ }
|
|
|
+
|
|
|
+ Base->DER = 0u;
|
|
|
+ switch (State->TransferMode)
|
|
|
+ {
|
|
|
+ case LPSPI_IP_POLLING:
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+ break;
|
|
|
+ case LPSPI_IP_INTERRUPT:
|
|
|
+ Base->IER = InterruptEnable;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+ switch(State->TransferMode)
|
|
|
+ {
|
|
|
+ case LPSPI_IP_POLLING:
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = 0u;
|
|
|
+ break;
|
|
|
+ case LPSPI_IP_INTERRUPT:
|
|
|
+
|
|
|
+ DmaTcdList[0u].Value = 1u;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (LPSPI_IP_HALF_DUPLEX_TRANSMIT == TransferType)
|
|
|
+ {
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 1u);
|
|
|
+
|
|
|
+
|
|
|
+ fill CMD (in the case clear CONT bit) at latest channel in job */
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER((uint32)LPSPI_IP_FIFO_SIZE_U8 - (uint32)2u);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_TxDmaConfig(Instance);
|
|
|
+
|
|
|
+ Base->DER = LPSPI_DER_TDDE_MASK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 1u);
|
|
|
+ (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 1u);
|
|
|
+
|
|
|
+
|
|
|
+ Base->FCR = LPSPI_FCR_TXWATER(0u);
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_SLAVE_SUPPORT)
|
|
|
+ if (TRUE == State->PhyUnitConfig->SlaveMode)
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_RxDmaConfig(Instance);
|
|
|
+
|
|
|
+ Base->DER = LPSPI_DER_RDDE_MASK;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_RxDmaConfig(Instance);
|
|
|
+ Lpspi_Ip_TxDmaConfig(Instance);
|
|
|
+
|
|
|
+ Base->DER = LPSPI_DER_RDDE_MASK | LPSPI_DER_TDDE_MASK;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+#if (STD_ON == LPSPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT)
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_AsyncTransmitFast(
|
|
|
+ const Lpspi_Ip_FastTransferType *FastTransferCfg,
|
|
|
+ uint8 NumberOfTransfer,
|
|
|
+ Lpspi_Ip_CallbackType EndCallback
|
|
|
+ )
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+ uint8 Instance = 0u;
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ uint8 Count = 0u;
|
|
|
+
|
|
|
+ DevAssert(NULL_PTR != FastTransferCfg);
|
|
|
+ DevAssert(NULL_PTR != FastTransferCfg[0u].ExternalDevice);
|
|
|
+ #endif
|
|
|
+ Instance = FastTransferCfg[0u].ExternalDevice->Instance;
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR == State);
|
|
|
+ DevAssert(State->TransferMode == LPSPI_IP_INTERRUPT);
|
|
|
+ DevAssert(NumberOfTransfer <= State->PhyUnitConfig->MaxNumOfFastTransfer);
|
|
|
+ for(Count = 0u; Count < NumberOfTransfer; Count++)
|
|
|
+ {
|
|
|
+ DevAssert(NULL_PTR != FastTransferCfg[Count].ExternalDevice);
|
|
|
+ DevAssert(0u != FastTransferCfg[Count].Length);
|
|
|
+ DevAssert(FastTransferCfg[0u].ExternalDevice->DeviceParams->FrameSize <= 16u);
|
|
|
+ if (FastTransferCfg[0u].ExternalDevice->DeviceParams->FrameSize > 8u)
|
|
|
+ {
|
|
|
+ DevAssert((FastTransferCfg[Count].Length%2) == 0u);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DevAssert(LPSPI_IP_DMA_MAX_ITER_CNT_U16 >= FastTransferCfg[Count].Length);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_15();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_15();
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+
|
|
|
+ Base->CFGR1 &= ~(LPSPI_CFGR1_PCSCFG_MASK | LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK);
|
|
|
+ #endif
|
|
|
+
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_BUSY;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Some parameters such as Baudrate, Delays timming SpiTimeClk2Cs, SpiTimeCs2Clk, SpiTimeCs2Cs, SpiDataWidth, SpiTransferStart configuration
|
|
|
+ must be the same between transfers. So, make sure they are configured the same in each External Device allocated for Dma Fast Transfers.
|
|
|
+ And all those attributes can be got from first transfer in FastTransferCfg */
|
|
|
+ State->ExternalDevice = FastTransferCfg[0u].ExternalDevice;
|
|
|
+ State->Callback = EndCallback;
|
|
|
+
|
|
|
+
|
|
|
+ Base->CR &= ~LPSPI_CR_MEN_MASK;
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RTF_MASK|LPSPI_CR_RRF_MASK;
|
|
|
+
|
|
|
+
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ Base->CCR = FastTransferCfg[0u].ExternalDevice->Ccr[State->ClockMode];
|
|
|
+ #else
|
|
|
+ Base->CCR = FastTransferCfg[0u].ExternalDevice->Ccr;
|
|
|
+ #endif
|
|
|
+ Base->CR |= LPSPI_CR_MEN_MASK;
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_15();
|
|
|
+
|
|
|
+
|
|
|
+ Base->IER = 0u;
|
|
|
+
|
|
|
+ Base->DER = LPSPI_DER_RDDE_MASK | LPSPI_DER_TDDE_MASK;
|
|
|
+
|
|
|
+ Lpspi_Ip_DmaFastConfig(Instance, FastTransferCfg, NumberOfTransfer);
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+* @brief This function will configure Scatter/Gather TCDs for the channels TX DMA, RX DMA and CMD DMA
|
|
|
+* according to Dma Fast transfers configuration. DMA channels will be started at the end of the function.
|
|
|
+*/
|
|
|
+static void Lpspi_Ip_DmaFastConfig(uint8 Instance, const Lpspi_Ip_FastTransferType *FastTransferCfg, uint8 NumberOfTransfer)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ boolean ClearCS = FALSE;
|
|
|
+ uint8 DisHwRequest = 0u;
|
|
|
+ uint8 Count = 0u;
|
|
|
+ uint8 TxDmaTCDSGIndex = 0u;
|
|
|
+ uint32 TransferCommand = 0u;
|
|
|
+ uint32 LSBBit = 0UL;
|
|
|
+ boolean FirstCmd = TRUE;
|
|
|
+ Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
|
|
|
+
|
|
|
+ DmaTcdList[0u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
|
|
|
+ DmaTcdList[0u].Value = 1u;
|
|
|
+
|
|
|
+ for(Count = 0u; Count < NumberOfTransfer; Count++)
|
|
|
+ {
|
|
|
+
|
|
|
+ State->RxIndex = 0u;
|
|
|
+ State->TxIndex = 0u;
|
|
|
+ State->TxBuffer = FastTransferCfg[Count].TxBuffer;
|
|
|
+ State->RxBuffer = FastTransferCfg[Count].RxBuffer;
|
|
|
+ if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = FastTransferCfg[Count].Length;
|
|
|
+ }
|
|
|
+ else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = FastTransferCfg[Count].Length/2u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ State->ExpectedFifoWrites = FastTransferCfg[Count].Length/4u;
|
|
|
+ }
|
|
|
+ State->ExpectedFifoReads = State->ExpectedFifoWrites;
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DefaultData = FastTransferCfg[Count].DefaultData;
|
|
|
+ LSBBit = State->ExternalDevice->DeviceParams->Lsb ? 1UL : 0UL;
|
|
|
+
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+ TransferCommand = FastTransferCfg[Count].ExternalDevice->Tcr[State->ClockMode] | LPSPI_TCR_FRAMESZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) | LPSPI_TCR_LSBF(LSBBit);
|
|
|
+ #else
|
|
|
+ TransferCommand = FastTransferCfg[Count].ExternalDevice->Tcr | LPSPI_TCR_FRAMESZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) | LPSPI_TCR_LSBF(LSBBit);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (0u != (TransferCommand & LPSPI_TCR_CONT_MASK))
|
|
|
+ {
|
|
|
+ if(TRUE == FirstCmd)
|
|
|
+ {
|
|
|
+ FirstCmd = FALSE;
|
|
|
+
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmd = TransferCommand;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmd = TransferCommand | LPSPI_TCR_CONTC_MASK;
|
|
|
+ }
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmdLast = TransferCommand & (~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmd = TransferCommand;
|
|
|
+ State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmdLast = TransferCommand;
|
|
|
+ }
|
|
|
+ if(FALSE == FastTransferCfg[Count].KeepCs)
|
|
|
+ {
|
|
|
+
|
|
|
+ FirstCmd = TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Disable DMA HW request at the end of transfer. */
|
|
|
+ if (Count == (NumberOfTransfer - 1u))
|
|
|
+ {
|
|
|
+ ClearCS = TRUE;
|
|
|
+ DisHwRequest = 1u;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(FALSE == FastTransferCfg[Count].KeepCs)
|
|
|
+ {
|
|
|
+ ClearCS = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ClearCS = FALSE;
|
|
|
+ }
|
|
|
+ DisHwRequest = 0u;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_CmdTxDmaTcdSGConfig(Instance, TxDmaTCDSGIndex, (uint32)&State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmd, 0u);
|
|
|
+ TxDmaTCDSGIndex++;
|
|
|
+
|
|
|
+ if((TRUE == ClearCS) && (0u != (TransferCommand & LPSPI_TCR_CONT_MASK)))
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_TxDmaTcdSGConfig(Instance, TxDmaTCDSGIndex, 0u, (const uint32 *)&State->PhyUnitConfig->CmdDmaFast[Count].DefaultData);
|
|
|
+ TxDmaTCDSGIndex++;
|
|
|
+
|
|
|
+ Lpspi_Ip_CmdTxDmaTcdSGConfig(Instance, TxDmaTCDSGIndex, (uint32)&State->PhyUnitConfig->CmdDmaFast[Count].DmaFastTcrCmdLast, DisHwRequest);
|
|
|
+ TxDmaTCDSGIndex++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ Lpspi_Ip_TxDmaTcdSGConfig(Instance, TxDmaTCDSGIndex, DisHwRequest, (const uint32 *)&State->PhyUnitConfig->CmdDmaFast[Count].DefaultData);
|
|
|
+ TxDmaTCDSGIndex++;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Lpspi_Ip_RxDmaTcdSGConfig(Instance, Count, DisHwRequest);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Dma_Ip interrupt function will not call Spi Dma notification due to it understood as spurious interrupt(Done flag = 1, INTMAJOR=0).
|
|
|
+ So, the workaround is set INTMAJOR=1 for next TCD ScatterGather. */
|
|
|
+ if (TxDmaTCDSGIndex < State->PhyUnitConfig->NumberTxSG)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TxDmaTCDSGIndex], DmaTcdList, 1u);
|
|
|
+ }
|
|
|
+ if (NumberOfTransfer < State->PhyUnitConfig->NumberRxSG)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[NumberOfTransfer], DmaTcdList, 1u);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[0u]);
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[0u]);
|
|
|
+
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
|
|
|
+}
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+void Lpspi_Ip_ManageBuffers(uint8 Instance)
|
|
|
+{
|
|
|
+ const LPSPI_Type* Base;
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ Dma_Ip_LogicChannelStatusType DmaChannelStatus;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+ if (LPSPI_IP_POLLING == State->TransferMode)
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ if(FALSE == State->PhyUnitConfig->DmaUsed)
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+
|
|
|
+ - Transmit: TDF is set only, RDF will never be set by RX FIFO have masked.
|
|
|
+ - Receive: Both TDF (push CDM) and DRF (receive data) are set.
|
|
|
+ In half duplex Slave mode:
|
|
|
+ - Transmit: TDF is set only, RDF will never be set by RX FIFO have masked.
|
|
|
+ - Receive: Both TDF and RDF are set. But only process for RDF to receive data. In this case, State->CurrentTxFifoSlot will be set to 0 */
|
|
|
+ if(
|
|
|
+ (0u != (Base->SR & LPSPI_SR_RDF_MASK)) ||
|
|
|
+ ((0u != (Base->SR & LPSPI_SR_TDF_MASK)) && (0u!= State->CurrentTxFifoSlot))
|
|
|
+ )
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (LPSPI_IP_FULL_DUPLEX != State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ {
|
|
|
+ Lpspi_Ip_TransferProcessHalfDuplex(Instance);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ Lpspi_Ip_TransferProcess(Instance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_GetLogicChannelStatus(State->PhyUnitConfig->RxDmaChannel, &DmaChannelStatus);
|
|
|
+ if(TRUE == DmaChannelStatus.Done)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_CLEAR_DONE);
|
|
|
+ Lpspi_Ip_IrqRxDmaHandler(Instance);
|
|
|
+ }
|
|
|
+
|
|
|
+ (void)Dma_Ip_GetLogicChannelStatus(State->PhyUnitConfig->TxDmaChannel, &DmaChannelStatus);
|
|
|
+ if(TRUE == DmaChannelStatus.Done)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_CLEAR_DONE);
|
|
|
+ Lpspi_Ip_IrqTxDmaHandler(Instance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_UpdateFrameSize(const Lpspi_Ip_ExternalDeviceType *ExternalDevice, uint8 FrameSize)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != ExternalDevice);
|
|
|
+ DevAssert(LPSPI_IP_FRAMESIZE_MAX_U8 >= FrameSize);
|
|
|
+ DevAssert(LPSPI_IP_FRAMESIZE_MIN_U8 <= FrameSize);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[ExternalDevice->Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (State->Status != LPSPI_IP_BUSY)
|
|
|
+ {
|
|
|
+ ExternalDevice->DeviceParams->FrameSize = FrameSize;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_UpdateLsb(const Lpspi_Ip_ExternalDeviceType *ExternalDevice, boolean Lsb)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != ExternalDevice);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[ExternalDevice->Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (State->Status != LPSPI_IP_BUSY)
|
|
|
+ {
|
|
|
+ ExternalDevice->DeviceParams->Lsb = Lsb;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_UpdateDefaultTransmitData(const Lpspi_Ip_ExternalDeviceType *ExternalDevice, uint32 DefaultData)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != ExternalDevice);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[ExternalDevice->Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (State->Status != LPSPI_IP_BUSY)
|
|
|
+ {
|
|
|
+ ExternalDevice->DeviceParams->DefaultData = DefaultData;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_UpdateTransferMode(uint8 Instance, Lpspi_Ip_ModeType Mode)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (State->Status != LPSPI_IP_BUSY)
|
|
|
+ {
|
|
|
+ State->TransferMode = Mode;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+void Lpspi_Ip_Cancel(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base;
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ uint32 Cfgr1 = 0u;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+ SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_10();
|
|
|
+ if (LPSPI_IP_BUSY == State->Status)
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->TCR |= LPSPI_TCR_RXMSK(1);
|
|
|
+
|
|
|
+ Cfgr1 = Base->CFGR1;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Base->CR |= LPSPI_CR_RST_MASK;
|
|
|
+ Base->CR &= ~LPSPI_CR_RST_MASK;
|
|
|
+
|
|
|
+ Base->CFGR1 = Cfgr1;
|
|
|
+ #if (STD_ON == LPSPI_IP_DMA_USED)
|
|
|
+ if(TRUE == State->PhyUnitConfig->DmaUsed)
|
|
|
+ {
|
|
|
+
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
|
|
|
+ (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ State->Status = LPSPI_IP_IDLE;
|
|
|
+ }
|
|
|
+ SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_10();
|
|
|
+}
|
|
|
+
|
|
|
+* @brief This function is called by LSPI ISRs.
|
|
|
+* @details This function will process activities for flags TDF, RDF, REF and TEF.
|
|
|
+*
|
|
|
+* @param[in] Instance Instance of the hardware unit.
|
|
|
+*
|
|
|
+* @implements Lpspi_Ip_IrqHandler_Activity
|
|
|
+*/
|
|
|
+void Lpspi_Ip_IrqHandler(uint8 Instance)
|
|
|
+{
|
|
|
+ LPSPI_Type* Base = Lpspi_Ip_apxBases[Instance];
|
|
|
+ const Lpspi_Ip_StateStructureType* State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ uint32 IrqFlags = 0u;
|
|
|
+
|
|
|
+ if (NULL_PTR != State)
|
|
|
+ {
|
|
|
+
|
|
|
+ IrqFlags = Base->SR & (LPSPI_SR_TDF_MASK | LPSPI_SR_RDF_MASK | LPSPI_SR_TEF_MASK | LPSPI_SR_REF_MASK);
|
|
|
+ IrqFlags &= Base->IER & (LPSPI_IER_TDIE_MASK | LPSPI_IER_RDIE_MASK | LPSPI_IER_TEIE_MASK | LPSPI_IER_REIE_MASK);
|
|
|
+ if (0u != IrqFlags)
|
|
|
+ {
|
|
|
+ #if (STD_ON == LPSPI_IP_HALF_DUPLEX_MODE_SUPPORT)
|
|
|
+ if (
|
|
|
+ (LPSPI_IP_HALF_DUPLEX_TRANSMIT == State->ExternalDevice->DeviceParams->TransferType) ||
|
|
|
+ (LPSPI_IP_HALF_DUPLEX_RECEIVE == State->ExternalDevice->DeviceParams->TransferType)
|
|
|
+ )
|
|
|
+ {
|
|
|
+ Lpspi_Ip_TransferProcessHalfDuplex(Instance);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ Lpspi_Ip_TransferProcess(Instance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ Base->SR &= LPSPI_IP_SR_W1C_MASK_U32;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Lpspi_Ip_HwStatusType Lpspi_Ip_GetStatus(uint8 Instance)
|
|
|
+{
|
|
|
+ const Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_HwStatusType Status = LPSPI_IP_UNINIT;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ if (State != NULL_PTR)
|
|
|
+ {
|
|
|
+ Status = State->Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+#if (STD_ON == LPSPI_IP_DUAL_CLOCK_MODE)
|
|
|
+Lpspi_Ip_StatusType Lpspi_Ip_SetClockMode(uint8 Instance, Lpspi_Ip_DualClockModeType ClockMode)
|
|
|
+{
|
|
|
+ Lpspi_Ip_StateStructureType* State;
|
|
|
+ Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(Instance < LPSPI_INSTANCE_COUNT);
|
|
|
+ #endif
|
|
|
+ State = Lpspi_Ip_apxStateStructureArray[Instance];
|
|
|
+ #if (STD_ON == LPSPI_IP_DEV_ERROR_DETECT)
|
|
|
+ DevAssert(NULL_PTR != State);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ if (State->Status != LPSPI_IP_BUSY)
|
|
|
+ {
|
|
|
+ State->ClockMode = ClockMode;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Status = LPSPI_IP_STATUS_FAIL;
|
|
|
+ }
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#define SPI_STOP_SEC_CODE
|
|
|
+#include "Spi_MemMap.h"
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+
|