1 /*
2  * Copyright 2021-2023 NXP NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 /**
7 *   @file    Spi_Ip.c
8 *
9 *
10 *   @brief   SPI low-level driver implementations.
11 *   @details SPI low-level driver implementations.
12 *
13 *   @addtogroup SPI_IP_DRIVER Spi Ip Driver
14 *   @{
15 */
16 
17 #ifdef __cplusplus
18 extern "C"
19 {
20 #endif
21 
22 
23 /*==================================================================================================
24 *                                        INCLUDE FILES
25 * 1) system and project includes
26 * 2) needed interfaces from external units
27 * 3) internal and external interfaces from this unit
28 ==================================================================================================*/
29 #include "Mcal.h"
30 #include "Spi_Ip.h"
31 #include "Spi_Ip_Cfg.h"
32 #include "OsIf.h"
33 #if (SPI_IP_DMA_USED == STD_ON)
34     #include "Dma_Ip.h"
35 #endif
36 #if (STD_ON == SPI_IP_ENABLE_USER_MODE_SUPPORT)
37    #define USER_MODE_REG_PROT_ENABLED   (SPI_IP_ENABLE_USER_MODE_SUPPORT)
38    #include "RegLockMacros.h"
39 #endif
40 #include "SchM_Spi.h"
41 #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
42     #include "Devassert.h"
43 #endif
44 
45 /*==================================================================================================
46 *                                       SOURCE FILE VERSION INFORMATION
47 ==================================================================================================*/
48 #define SPI_IP_VENDOR_ID_C                      43
49 #define SPI_IP_AR_RELEASE_MAJOR_VERSION_C       4
50 #define SPI_IP_AR_RELEASE_MINOR_VERSION_C       7
51 #define SPI_IP_AR_RELEASE_REVISION_VERSION_C    0
52 #define SPI_IP_SW_MAJOR_VERSION_C               1
53 #define SPI_IP_SW_MINOR_VERSION_C               0
54 #define SPI_IP_SW_PATCH_VERSION_C               0
55 /*==================================================================================================
56 *                                     FILE VERSION CHECKS
57 ==================================================================================================*/
58 #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
59     /* Check if current file and Mcal header file are of the same Autosar version */
60     #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
61          (SPI_IP_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION))
62     #error "AutoSar Version Numbers of Spi_Ip.c and Mcal.h are different"
63     #endif
64 
65     #if (SPI_IP_DMA_USED == STD_ON)
66         /* Check if current file and Dma_Ip header file are of the same Autosar version */
67         #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != DMA_IP_AR_RELEASE_MAJOR_VERSION) || \
68              (SPI_IP_AR_RELEASE_MINOR_VERSION_C != DMA_IP_AR_RELEASE_MINOR_VERSION))
69         #error "AutoSar Version Numbers of Spi_Ip.c and Dma_Ip.h are different"
70         #endif
71     #endif
72 
73     #if (STD_ON == SPI_IP_ENABLE_USER_MODE_SUPPORT)
74         #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != REGLOCKMACROS_AR_RELEASE_MAJOR_VERSION) || \
75              (SPI_IP_AR_RELEASE_MINOR_VERSION_C != REGLOCKMACROS_AR_RELEASE_MINOR_VERSION))
76         #error "AutoSar Version Numbers of Spi_Ip.c and RegLockMacros.h are different"
77         #endif
78     #endif
79 
80     /* Check if the current file and SchM_Spi.h header file are of the same version */
81     #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != SCHM_SPI_AR_RELEASE_MAJOR_VERSION) || \
82          (SPI_IP_AR_RELEASE_MINOR_VERSION_C != SCHM_SPI_AR_RELEASE_MINOR_VERSION) \
83         )
84         #error "AutoSar Version Numbers of Spi_Ip.c and SchM_Spi.h are different"
85     #endif
86 
87     /* Check if the current file and OsIf.h header file are of the same version */
88     #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
89          (SPI_IP_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION) \
90         )
91         #error "AutoSar Version Numbers of Spi_Ip.c and OsIf.h are different"
92     #endif
93 #endif
94 
95 #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
96     #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
97         /* Check if Spi_Ip source file and Devassert.h header file are of the same release version */
98         #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_C != DEVASSERT_AR_RELEASE_MAJOR_VERSION) || \
99              (SPI_IP_AR_RELEASE_MINOR_VERSION_C != DEVASSERT_AR_RELEASE_MINOR_VERSION)    \
100             )
101             #error "AutoSar Version Numbers of Spi_Ip.c and Devassert.h are different"
102         #endif
103     #endif
104 #endif /* (STD_ON == SPI_IP_DEV_ERROR_DETECT) */
105 
106 /* Check if Spi_Ip.h and Spi_Ip.c are of the same vendor */
107 #if (SPI_IP_VENDOR_ID != SPI_IP_VENDOR_ID_C)
108     #error "Spi_Ip.h and Spi_Ip.c have different vendor ids"
109 #endif
110 /* Check if Spi_Ip.h file and Spi_Ip.c file are of the same Autosar version */
111 #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION != SPI_IP_AR_RELEASE_MAJOR_VERSION_C) || \
112      (SPI_IP_AR_RELEASE_MINOR_VERSION != SPI_IP_AR_RELEASE_MINOR_VERSION_C) || \
113      (SPI_IP_AR_RELEASE_REVISION_VERSION != SPI_IP_AR_RELEASE_REVISION_VERSION_C))
114 #error "AutoSar Version Numbers of Spi_Ip.h and Spi_Ip.c are different"
115 #endif
116 #if ((SPI_IP_SW_MAJOR_VERSION != SPI_IP_SW_MAJOR_VERSION_C) || \
117      (SPI_IP_SW_MINOR_VERSION != SPI_IP_SW_MINOR_VERSION_C) || \
118      (SPI_IP_SW_PATCH_VERSION != SPI_IP_SW_PATCH_VERSION_C))
119 #error "Software Version Numbers of Spi_Ip.h and Spi_Ip.c are different"
120 #endif
121 
122 /* Check if Spi_Ip_Cfg.h and Spi_Ip.c are of the same vendor */
123 #if (SPI_IP_VENDOR_ID_CFG != SPI_IP_VENDOR_ID_C)
124     #error "Spi_Ip_Cfg.h and Spi_Ip.c have different vendor ids"
125 #endif
126 /* Check if Spi_Ip_Cfg.h file and Spi_Ip.c file are of the same Autosar version */
127 #if ((SPI_IP_AR_RELEASE_MAJOR_VERSION_CFG != SPI_IP_AR_RELEASE_MAJOR_VERSION_C) || \
128      (SPI_IP_AR_RELEASE_MINOR_VERSION_CFG != SPI_IP_AR_RELEASE_MINOR_VERSION_C) || \
129      (SPI_IP_AR_RELEASE_REVISION_VERSION_CFG != SPI_IP_AR_RELEASE_REVISION_VERSION_C))
130 #error "AutoSar Version Numbers of Spi_Ip_Cfg.h and Spi_Ip.c are different"
131 #endif
132 #if ((SPI_IP_SW_MAJOR_VERSION_CFG != SPI_IP_SW_MAJOR_VERSION_C) || \
133      (SPI_IP_SW_MINOR_VERSION_CFG != SPI_IP_SW_MINOR_VERSION_C) || \
134      (SPI_IP_SW_PATCH_VERSION_CFG != SPI_IP_SW_PATCH_VERSION_C))
135 #error "Software Version Numbers of Spi_Ip_Cfg.h and Spi_Ip.c are different"
136 #endif
137 /*==================================================================================================
138 *                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
139 ==================================================================================================*/
140 /*==================================================================================================
141 *                                       LOCAL MACROS
142 ==================================================================================================*/
143 #if (SPI_IP_DMA_USED == STD_ON)
144     /* the maximum of Major loop when Minor loop Channel Linking Disabled */
145     #define SPI_IP_DMA_MAX_ITER_CNT_U16 ((uint16)0x7FFFu)
146 #endif
147 
148 /**
149 * @brief Maximum value of CTARE[DTCP]
150 */
151 #define SPI_IP_CTARE_DTCP_MAX_U16    (uint16) 2047u
152 /*==================================================================================================
153 *                                       LOCAL CONSTANTS
154 ==================================================================================================*/
155 /*==================================================================================================
156 *                                       LOCAL VARIABLES
157 ==================================================================================================*/
158 /*==================================================================================================
159 *                                      GLOBAL CONSTANTS
160 ==================================================================================================*/
161 /*==================================================================================================
162                                     GLOBAL VARIABLES
163 ==================================================================================================*/
164 #if (SPI_IP_DMA_USED == STD_ON)
165     #define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
166 #else
167     #define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED
168 #endif
169 #include "Spi_MemMap.h"
170 
171 static Spi_Ip_StateStructureType Spi_Ip_axStateStructure[SPI_IP_NUMBER_OF_INSTANCES];
172 
173 #if (SPI_IP_DMA_USED == STD_ON)
174     #define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
175 #else
176     #define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED
177 #endif
178 #include "Spi_MemMap.h"
179 
180 #if (SPI_IP_DMA_USED == STD_ON)
181     #define SPI_START_SEC_VAR_CLEARED_32_NO_CACHEABLE
182     #include "Spi_MemMap.h"
183 uint32 Spi_Ip_u32DiscardData;
184     #define SPI_STOP_SEC_VAR_CLEARED_32_NO_CACHEABLE
185     #include "Spi_MemMap.h"
186 #endif
187 
188 #define SPI_START_SEC_VAR_CLEARED_UNSPECIFIED
189 #include "Spi_MemMap.h"
190 
191 Spi_Ip_StateStructureType* Spi_Ip_apxStateStructureArray[SPI_INSTANCE_COUNT];
192 
193 #define SPI_STOP_SEC_VAR_CLEARED_UNSPECIFIED
194 #include "Spi_MemMap.h"
195 
196 #define SPI_START_SEC_CONST_UNSPECIFIED
197 #include "Spi_MemMap.h"
198 
199 static SPI_Type* const Spi_Ip_apxBases[SPI_INSTANCE_COUNT] = IP_SPI_BASE_PTRS;
200 
201 #define SPI_STOP_SEC_CONST_UNSPECIFIED
202 #include "Spi_MemMap.h"
203 /*==================================================================================================
204 *                                  LOCAL FUNCTION PROTOTYPES
205 ==================================================================================================*/
206 #define SPI_START_SEC_CODE
207 #include "Spi_MemMap.h"
208 
209 static void Spi_Ip_TransferProcess(uint8 Instance);
210 #if (SPI_IP_DMA_USED == STD_ON)
211 static void Spi_Ip_DmaConfig(uint8 Instance);
212 static void Spi_Ip_CmdDmaTcdSGInit(uint8 Instance);
213 static void Spi_Ip_CmdDmaTcdSGConfig(   uint8 Instance,
214                                         uint8 TCDSGId,
215                                         uint32 CmdAdd,
216                                         uint16 Iter,
217                                         uint8 DisHwReq
218                                     );
219 static void Spi_Ip_DmaContinueTransfer(uint8 Instance);
220 #if (SPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT == STD_ON)
221 static void Spi_Ip_DmaFastConfig(uint8 Instance, const Spi_Ip_FastTransferType *FastTransferCfg, uint8 NumberOfTransfer);
222 static void Spi_Ip_RxDmaTcdSGConfig(uint8 Instance, uint8 TCDSGIndex, uint8 DisHwReq);
223 static void Spi_Ip_RxDmaTcdSGInit(uint8 Instance);
224 static void Spi_Ip_TxDmaTcdSGConfig(uint8 Instance, uint8 TCDSGIndex, uint8 DisHwReq);
225 static void Spi_Ip_TxDmaTcdSGInit(uint8 Instance);
226 #endif
227 #endif
228 #if (STD_ON == SPI_IP_ENABLE_USER_MODE_SUPPORT)
229 void Spi_Ip_SetUserAccess(uint8 Instance);
230 static void Spi_Ip_SetUserAccessAllowed(uint8 Instance);
231 #endif /* SPI_IP_ENABLE_USER_MODE_SUPPORT */
232 
233 static void Spi_Ip_ReadRxFifo
234 (
235     uint16 NumberOfReads,
236     uint8 Instance
237 );
238 static void Spi_Ip_WriteTxFifo
239 (
240     uint16 NumberOfWrites,
241     uint8 Instance
242 );
243 static void Spi_Ip_ReceiveData
244 (
245     uint16 NumberOfReads,
246     uint8 Instance
247 );
248 static void Spi_Ip_ChannelFinished
249 (
250     uint8 Instance, boolean ErrorFlag
251 );
252 static void Spi_Ip_WriteCmdFifo
253 (
254     uint16 NumberOfWrites,
255     uint8 Instance
256 );
257 
258 static void Spi_Ip_UpdateTxRxCounter
259 (
260     uint8 Instance,
261     uint16 Length
262 );
263 
264 #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
265 static void Spi_Ip_CheckValidParameters
266 (
267     const Spi_Ip_ExternalDeviceType *ExternalDevice,
268     uint16 Length
269 );
270 #endif
271 /*==================================================================================================
272 *                                      LOCAL FUNCTIONS
273 ==================================================================================================*/
274 /**
275 * @brief   This function is called by Spi_Ip_IrqHandler or Spi_Ip_ManageBuffers. It will process transfer in interrupt mode and polling mode.
276 * @details This function will fill data into TX FIFO and read data in RX FIFO fill to Rx Buffers.
277 *
278 * @param[in]     Instance      Index of the hardware instance.
279 * @return void
280 */
Spi_Ip_TransferProcess(uint8 Instance)281 static void Spi_Ip_TransferProcess(uint8 Instance)
282 {
283     SPI_Type* Base = Spi_Ip_apxBases[Instance];
284     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
285     uint32 SrStatusRegister;
286     uint16 NumberOfReads;
287     uint16 NumberOfWrites;
288     boolean ErrorFlag = (boolean)FALSE;
289 
290     if (SPI_IP_BUSY == State->Status)
291     {
292         /* Read Status and clear all flags. */
293         SrStatusRegister = Base->SR;
294         Base->SR &= 0xFFFF0000u;
295 
296         if ( (0u != (SrStatusRegister & (SPI_SR_RFOF_MASK | SPI_SR_TFUF_MASK))) )
297         {
298             /* mark error flag */
299             ErrorFlag = (boolean)TRUE;
300         }
301         else
302         {
303             /* Read all data available in receive HW fifo. */
304             NumberOfReads = (uint16)(((Base->SR) & SPI_SR_RXCTR_MASK) >> SPI_SR_RXCTR_SHIFT);
305             if(NumberOfReads != 0u)
306             {
307                 /* Read data from RX FIFO */
308                 Spi_Ip_ReceiveData(NumberOfReads, Instance);
309             }
310 
311 #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
312             if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
313 #endif
314             {
315                 /* Cmd must be pushed before data, push Cmd until HW cmd fifo is full */
316                 NumberOfWrites = (uint16)((Base->SREX) & SPI_SREX_CMDCTR_MASK) >> SPI_SREX_CMDCTR_SHIFT;
317                 NumberOfWrites = SPI_IP_FIFO_SIZE_U16 - NumberOfWrites;
318                 /* Write to CMD FIFO */
319                 if ((NumberOfWrites != 0u) && (State->ExpectedCmdFifoWrites != 0u))
320                 {
321                     Spi_Ip_WriteCmdFifo(NumberOfWrites, Instance);
322                 }
323             }
324             /* Push data until HW fifo is full or transfer is done. */
325             /* After driver code read all frames in RX FIFO, if there are still some frames in TX FIFO, at the time before driver code check number of frames available in TX FIFO to prepare
326             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
327             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.
328             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.
329             So, RX FIFO can be overflow due to SPI interrupt function is not serviced to read RX FIFO.
330             To avoid this, limitation total of frames in TX FIFO and RX FIFO is lower than FIFO's size(considered that maybe there is an frame on going). */
331             if (State->CurrentTxFifoSlot > (State->ExpectedFifoWrites - State->TxIndex))
332             {
333                 State->CurrentTxFifoSlot = State->ExpectedFifoWrites - State->TxIndex;
334             }
335             if(State->CurrentTxFifoSlot != 0u)
336             {
337                 Spi_Ip_WriteTxFifo(State->CurrentTxFifoSlot, Instance);
338                 /* Update current TX FIFO slot can be written */
339                 State->CurrentTxFifoSlot = 0u;
340             }
341         }
342         /* End of transfer if all of frames are received or has error */
343         if ((State->RxIndex == State->ExpectedFifoReads) || ((boolean)TRUE == ErrorFlag))
344         {
345             /* Only set HALT bit to stop transfer when there is a error or request to de-assert CS at the end of transfers sequence */
346             if(((boolean)TRUE == ErrorFlag) || ((boolean)FALSE == State->KeepCs))
347             {
348                 SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_12();
349                 /* Stop Transfer */
350                 Base->MCR |= SPI_MCR_HALT_MASK;
351                 SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_12();
352             }
353             /* Disable interrupts and DMA requests. */
354             Base->RSER = 0U;
355             /* Channel finished */
356             Spi_Ip_ChannelFinished(Instance, ErrorFlag);
357         }
358     }
359 }
360 
361 #if (SPI_IP_DMA_USED == STD_ON)
362 /**
363 * @brief   This function will initialize all software TCDs Scatter Gather for Command DMA channel.
364 *          And load software TCD Scatter Gather 0 into hardware TCD.
365 *
366 * @param[in]     Instance      Index of the hardware instance.
367 * @return void
368 */
Spi_Ip_CmdDmaTcdSGInit(uint8 Instance)369 static void Spi_Ip_CmdDmaTcdSGInit(uint8 Instance)
370 {
371     SPI_Type* Base = Spi_Ip_apxBases[Instance];
372     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
373     Dma_Ip_LogicChannelScatterGatherListType DmaTcdList[9u];
374     uint8 TCDSGIndex = 0u;
375 
376     /* initialze configuration software TCD Scatter Gather for Cmd DMA channel */
377     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
378     DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
379     DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
380     DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
381     DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
382     DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
383     DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
384     DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
385     DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
386 
387     DmaTcdList[0u].Value = 0u; /* dummy src address read, it will be updated later */
388     DmaTcdList[1u].Value = (uint32)&Base->PUSHR.FIFO.CMD;    /* dest address write*/
389     DmaTcdList[2u].Value = 0u;    /* no src offset */
390     DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes src transfer size */
391     DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes dest transfer size */
392     DmaTcdList[5u].Value = 2u; /* bytes to transfer for each request */
393     DmaTcdList[6u].Value = 0u;    /* no dest offset */
394     DmaTcdList[7u].Value = 0u;    /* dummy iteration count will be updated later */
395     DmaTcdList[8u].Value = 1u;   /* dummy disable hardware request when major loop complete, will be updated latter in the case of Scatter Gather enabled */
396 
397     for(TCDSGIndex = 0u; TCDSGIndex < State->PhyUnitConfig->NumTxCmdDmaSGId; TCDSGIndex++)
398     {
399         /* Update software TCD Scatter Gather */
400         (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxCmdDmaChannel, State->PhyUnitConfig->TxCmdDmaSGId[TCDSGIndex], DmaTcdList, 9u);
401     }
402 
403     /* Load software TCD Scatter Gather 0 into hardware TCD */
404     (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxCmdDmaChannel, State->PhyUnitConfig->TxCmdDmaSGId[0u]);
405 }
406 
407 #if (SPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT == STD_ON)
Spi_Ip_TxDmaTcdSGInit(uint8 Instance)408 static void Spi_Ip_TxDmaTcdSGInit(uint8 Instance)
409 {
410     SPI_Type* Base = Spi_Ip_apxBases[Instance];
411     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
412     Dma_Ip_LogicChannelTransferListType DmaTcdList[10u];
413     uint8 TCDSGIndex = 0u;
414 
415     /* initialze configuration software TCD Scatter Gather for Tx DMA channel */
416     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
417     DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
418     DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
419     DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
420     DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
421     DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
422     DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
423     DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
424     DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
425     DmaTcdList[9u].Param = DMA_IP_CH_SET_SOURCE_MODULO;
426 
427     DmaTcdList[1u].Value = (uint32)&Base->PUSHR.FIFO.TX;    /* dest address write*/
428     DmaTcdList[2u].Value = 1u;  /* dummy src offset is 1 byte, will be updated latter according to frame size and transfer default data */
429     DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* dummy 1 byte src transfer size, will be updated latter according to frame size */
430     DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* dummy 1 byte dest transfer size, will be updated latter according to frame size */
431     DmaTcdList[5u].Value = 1u;   /* dummy bytes to transfer for each request, will be updated latter according to frame size */
432     DmaTcdList[6u].Value = 0u; /* no dest offset */
433     DmaTcdList[7u].Value = 0u; /* dummy iteration count, will be updated latter according to number of frames */
434     DmaTcdList[8u].Value = 1u; /* dummy disable hardware request when major loop complete, will be updated latter according to last transfer or not */
435     DmaTcdList[9u].Value = 0u;  /* dummy no src address modulo, will be updated latter Base on transfer default data or not */
436     DmaTcdList[0u].Value = 0u; /* dummy src address read, will be updated latter Base on TxBuffer */
437 
438     for(TCDSGIndex = 0u; TCDSGIndex < State->PhyUnitConfig->MaxNumOfFastTransfer; TCDSGIndex++)
439     {
440         /* Update software TX DMA TCD Scatter Gather */
441         (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TCDSGIndex], DmaTcdList, 10u);
442     }
443 }
444 
Spi_Ip_TxDmaTcdSGConfig(uint8 Instance,uint8 TCDSGIndex,uint8 DisHwReq)445 static void Spi_Ip_TxDmaTcdSGConfig(uint8 Instance, uint8 TCDSGIndex, uint8 DisHwReq)
446 {
447     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
448     Dma_Ip_LogicChannelTransferListType DmaTcdList[8u];
449 
450     /* Update buffers index */
451     State->TxIndex = State->ExpectedFifoWrites;
452 
453     /* configure TX DMA TCD Scatter Gather */
454     /* No need to configure dest address and dest offset due to they are already set by Spi_Ip_TxDmaTcdSGInit */
455     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
456     DmaTcdList[1u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
457     DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
458     DmaTcdList[3u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
459     DmaTcdList[4u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
460     DmaTcdList[5u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
461     DmaTcdList[6u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
462     DmaTcdList[7u].Param = DMA_IP_CH_SET_SOURCE_MODULO;
463 
464     if(State->ExternalDevice->DeviceParams->FrameSize < 9u)
465     {
466         DmaTcdList[1u].Value = 1u;  /* src offset is 1 byte */
467         DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* 1 byte src transfer size */
468         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* 1 byte dest transfer size */
469         DmaTcdList[4u].Value = 1u;   /* bytes to transfer for each request */
470     }
471     else
472     {
473         DmaTcdList[1u].Value = 2u;  /* src offset is 2 bytes */
474         DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes src transfer size */
475         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;    /* 2 bytes dest transfer size */
476         DmaTcdList[4u].Value = 2u;   /* bytes to transfer for each request */
477     }
478     DmaTcdList[5u].Value = State->ExpectedFifoWrites; /* iteration count */
479     DmaTcdList[6u].Value = DisHwReq; /* disable hardware request when major loop complete */
480     DmaTcdList[7u].Value = 0u;  /* no src address modulo */
481     if(NULL_PTR == State->TxBuffer)
482     {
483         /* send default data */
484         DmaTcdList[0u].Value = (uint32)&State->PhyUnitConfig->CmdDmaFast[TCDSGIndex].DefaultData; /* src address read */
485         if(State->ExternalDevice->DeviceParams->FrameSize < 17u)
486         {
487             DmaTcdList[1u].Value = 0u;  /* src offset is 0 byte */
488         }
489         else
490         {
491             DmaTcdList[7u].Value = 2u;  /* data is 4 bytes, src address modulo is 2 bits */
492         }
493     }
494     else
495     {
496         DmaTcdList[0u].Value = (uint32)State->TxBuffer; /* src address read */
497     }
498     /* Update software TX DMA TCD Scatter Gather */
499     (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[TCDSGIndex], DmaTcdList, 8u);
500 }
501 
Spi_Ip_RxDmaTcdSGInit(uint8 Instance)502 static void Spi_Ip_RxDmaTcdSGInit(uint8 Instance)
503 {
504     SPI_Type* Base = Spi_Ip_apxBases[Instance];
505     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
506     Dma_Ip_LogicChannelTransferListType DmaTcdList[9u];
507     uint8 TCDSGIndex = 0u;
508 
509     /* initialze configuration software TCD Scatter Gather for Rx DMA channel */
510     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
511     DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
512     DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
513     DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
514     DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
515     DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
516     DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
517     DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
518     DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
519 
520     DmaTcdList[0u].Value = (uint32)&Base->POPR; /* src address read */
521     DmaTcdList[2u].Value = 0u;  /* no src offset */
522     DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* dummy 1 byte src transfer size, will be updated latter Base on frame size */
523     DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* dummy 1 byte dest transfer size, will be updated latter Base on frame size */
524     DmaTcdList[5u].Value = 1u;   /* dummy 1 byte to transfer for each request, will be updated latter Base on frame size */
525     DmaTcdList[6u].Value = 1u; /* dummy dest offset is 1 byte, will be updated latter Base on frame size and discard info */
526     DmaTcdList[1u].Value = 0u;    /* dummy dest address write, will be updated latter Base on RxBuffer */
527     DmaTcdList[7u].Value = 0u; /* dummy iteration count, will be updated latter Base on number of frames */
528     DmaTcdList[8u].Value = 1u; /* dummy disable hardware request when major loop complete, will be updated latter according to last transfer or not */
529 
530     for(TCDSGIndex = 0u; TCDSGIndex < State->PhyUnitConfig->MaxNumOfFastTransfer; TCDSGIndex++)
531     {
532         /* Update software RX DMA TCD Scatter Gather */
533         (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[TCDSGIndex], DmaTcdList, 9u);
534     }
535 }
536 
Spi_Ip_RxDmaTcdSGConfig(uint8 Instance,uint8 TCDSGIndex,uint8 DisHwReq)537 static void Spi_Ip_RxDmaTcdSGConfig(uint8 Instance, uint8 TCDSGIndex, uint8 DisHwReq)
538 {
539     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
540     Dma_Ip_LogicChannelTransferListType DmaTcdList[8u];
541 
542     /* Update buffers index */
543     State->RxIndex = State->ExpectedFifoReads;
544 
545     /* configure RX DMA TCD Scatter Gather */
546     /* No need to configure src address and src offset due to they are already set by Spi_Ip_RxDmaTcdSGInit */
547     DmaTcdList[0u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
548     DmaTcdList[1u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
549     DmaTcdList[2u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
550     DmaTcdList[3u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
551     DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
552     DmaTcdList[5u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
553     DmaTcdList[6u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
554     DmaTcdList[7u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
555 
556     if(State->ExternalDevice->DeviceParams->FrameSize < 9u)
557     {
558         DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* 1 byte src transfer size */
559         DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* 1 byte dest transfer size */
560         DmaTcdList[3u].Value = 1u;   /* 1 byte to transfer for each request */
561         DmaTcdList[4u].Value = 1u; /* dest offset is 1 bytes */
562     }
563     else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
564     {
565         DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes src transfer size */
566         DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;    /* 2 bytes dest transfer size */
567         DmaTcdList[3u].Value = 2u;   /* 2 bytes to transfer for each request */
568         DmaTcdList[4u].Value = 2u; /* dest offset is 2 bytes */
569     }
570     else
571     {
572         DmaTcdList[1u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE; /* 4 bytes src transfer size */
573         DmaTcdList[2u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;    /* 4 bytes dest transfer size */
574         DmaTcdList[3u].Value = 4u;   /* 4 bytes to transfer for each request */
575         DmaTcdList[4u].Value = 4u; /* dest offset is 4 bytes */
576     }
577     if(NULL_PTR == State->RxBuffer)
578     {
579         /* Discard data */
580         DmaTcdList[0u].Value = (uint32)&Spi_Ip_u32DiscardData;    /* dest address write*/
581         DmaTcdList[4u].Value = 0u; /* dest offset is 0 bytes */
582     }
583     else
584     {
585         DmaTcdList[0u].Value = (uint32)State->RxBuffer;    /* dest address write*/
586     }
587     DmaTcdList[5u].Value = State->ExpectedFifoReads; /* iteration count */
588     DmaTcdList[6u].Value = DisHwReq; /* disable hardware request when major loop complete */
589     DmaTcdList[7u].Value = DisHwReq; /* Enable Major interrupt at the end of transfer sequence(meanning when DisHwReq = 1u) */
590 
591     /* Update software RX DMA TCD Scatter Gather */
592     (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[TCDSGIndex], DmaTcdList, 8u);
593 }
594 
595 #endif
596 
597 /**
598 * @brief   This function will configure TCD Scatter Gather for the CMD DMA channel
599 */
Spi_Ip_CmdDmaTcdSGConfig(uint8 Instance,uint8 TCDSGId,uint32 CmdAdd,uint16 Iter,uint8 DisHwReq)600 static void Spi_Ip_CmdDmaTcdSGConfig(   uint8 Instance,
601                                         uint8 TCDSGId,
602                                         uint32 CmdAdd,
603                                         uint16 Iter,
604                                         uint8 DisHwReq
605                                     )
606 {
607     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
608     Dma_Ip_LogicChannelTransferListType DmaTcdList[3u];
609 
610     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
611     DmaTcdList[1u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
612     DmaTcdList[2u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
613 
614     /* configure TCD Scatter Gather for Cmd DMA channel */
615     DmaTcdList[0u].Value = CmdAdd; /* src address read */
616     DmaTcdList[1u].Value = Iter;    /* iteration count */
617     DmaTcdList[2u].Value = DisHwReq;    /* disable hardware request when major loop complete */
618     /* Update software TCD Scatter Gather */
619     (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->TxCmdDmaChannel, TCDSGId, DmaTcdList, 3u);
620 }
621 
622 /**
623 * @brief   This function will configure hardware TCDs for the channels TX DMA, RX DMA and CMD DMA
624 *          according to current transfer configuration. DMA channels will be started at the end of the function.
625 *
626 * @param[in]     Instance      Index of the hardware instance.
627 * @return void
628 */
Spi_Ip_DmaConfig(uint8 Instance)629 static void Spi_Ip_DmaConfig(uint8 Instance)
630 {
631     SPI_Type* Base = Spi_Ip_apxBases[Instance];
632     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
633     Dma_Ip_LogicChannelTransferListType DmaTcdList[11u];
634     uint16 NumberDmaIterWrite = State->ExpectedFifoWrites;
635     uint16 NumberDmaIterRead = 0u;
636     uint16 NumberCmdDmaIterWrite = 0u;
637     boolean ClearCS = (boolean)FALSE;
638     boolean EnScatterGather = (boolean)FALSE;
639 
640     /* Update last command */
641     State->PushrCmdLast = State->PushrCmd & (~((uint16)(SPI_PUSHR_CONT_MASK>>16u)));
642 
643     /* Limits number of major count */
644     if(SPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterWrite)
645     {
646         NumberDmaIterWrite = SPI_IP_DMA_MAX_ITER_CNT_U16;
647     }
648     else
649     {
650         if((boolean)FALSE == State->KeepCs)
651         {
652             ClearCS = (boolean)TRUE;
653         }
654     }
655 
656     NumberDmaIterRead = NumberDmaIterWrite;
657     if(State->ExternalDevice->DeviceParams->FrameSize > 16u)
658     {
659         /* TX DMA can read 4 bytes from POPR for each request, so the number of RX DMA iter will be a half */
660         NumberDmaIterRead = NumberDmaIterWrite/2u;
661         /* check to make sure number of frames written should equal number of frame read,
662         avoid the case of data is written without command available in CMD FIFO.
663         NumberDmaIterWrite may not be multiple of 2 due to it was assigned to SPI_IP_DMA_MAX_ITER_CNT_U16
664         or by user in Spi_Ip_AsyncTransmit */
665         if(0u != (NumberDmaIterWrite%2u))
666         {
667             NumberDmaIterWrite = NumberDmaIterRead;
668         }
669     }
670     /* Update buffers index */
671     State->TxIndex = NumberDmaIterWrite;
672     State->RxIndex = NumberDmaIterRead;
673 
674     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
675     if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
676     #endif
677     {
678         /* configure CMD DMA channel */
679         NumberCmdDmaIterWrite = NumberDmaIterRead;
680         /* Update number of remain commands */
681         State->ExpectedCmdFifoWrites -= NumberCmdDmaIterWrite;
682         DmaTcdList[1u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
683         DmaTcdList[1u].Value = (uint32)&State->PushrCmd;    /* default source address */
684         if((boolean)TRUE == ClearCS)
685         {
686             if(1u == NumberCmdDmaIterWrite)
687             {
688                 DmaTcdList[1u].Value = (uint32)&State->PushrCmdLast;    /* Clear CS command is source address */
689                 EnScatterGather = (boolean)FALSE;
690             }
691             else
692             {
693                 NumberCmdDmaIterWrite = NumberDmaIterRead - 1u;
694                 EnScatterGather = (boolean)TRUE;
695             }
696         }
697         else
698         {
699             EnScatterGather = (boolean)FALSE;
700         }
701         DmaTcdList[0u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
702         DmaTcdList[0u].Value = NumberCmdDmaIterWrite;    /* iteration count */
703         if((boolean)TRUE == EnScatterGather)
704         {
705             /* Update software TCD Scatter Gather 0 */
706             Spi_Ip_CmdDmaTcdSGConfig(Instance, /* Cmd Dma Channel Id */
707                                      State->PhyUnitConfig->TxCmdDmaSGId[0u], /* TCD Scatter Gather Id */
708                                      DmaTcdList[1u].Value, /* src address read */
709                                      (uint16)DmaTcdList[0u].Value, /* iteration count */
710                                      0u /* Not disable hardware request when major loop complete */
711                                     );
712             /* Load software TCD Scatter Gather 0 into hardware TCD with ESG bit already set in software TCD */
713             (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxCmdDmaChannel, State->PhyUnitConfig->TxCmdDmaSGId[0u]);
714             /* Config next TCD Scatter Gather will clear CS */
715             Spi_Ip_CmdDmaTcdSGConfig(Instance,
716                                      State->PhyUnitConfig->TxCmdDmaSGId[1u], /* TCD Scatter Gather Id */
717                                      (uint32)&State->PushrCmdLast, /* src address read */
718                                      1u, /* iteration count is 1 for last push command */
719                                      1u /* disable hardware request when major loop complete */
720                                     );
721         }
722         else
723         {
724             DmaTcdList[2u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
725             DmaTcdList[2u].Value = 1u;    /* disable hardware request when major loop complete */
726             DmaTcdList[3u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_LAST_ADDR_ADJ;
727             DmaTcdList[3u].Value = 0u;    /* No adjust DADD when major loop completed */
728             /* Update TCD for CMD DMA channel, ESG bit will be clear in this function */
729             (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxCmdDmaChannel, DmaTcdList, 4u);
730         }
731     }
732 
733     /* configure TX DMA channel */
734     DmaTcdList[0u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
735     DmaTcdList[1u].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
736     DmaTcdList[2u].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
737     DmaTcdList[3u].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
738     DmaTcdList[4u].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
739     DmaTcdList[5u].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
740     DmaTcdList[6u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
741     DmaTcdList[7u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
742     DmaTcdList[8u].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
743     DmaTcdList[9u].Param = DMA_IP_CH_SET_SOURCE_MODULO;
744 
745     DmaTcdList[1u].Value = (uint32)&Base->PUSHR.FIFO.TX;    /* dest address write*/
746     if(State->ExternalDevice->DeviceParams->FrameSize < 9u)
747     {
748         DmaTcdList[2u].Value = 1u;  /* src offset is 1 byte */
749         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* 1 byte src transfer size */
750         DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* 1 byte dest transfer size */
751         DmaTcdList[5u].Value = 1u;   /* bytes to transfer for each request */
752     }
753     else
754     {
755         DmaTcdList[2u].Value = 2u;  /* src offset is 2 bytes */
756         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes src transfer size */
757         DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;    /* 2 bytes dest transfer size */
758         DmaTcdList[5u].Value = 2u;   /* bytes to transfer for each request */
759     }
760     DmaTcdList[6u].Value = 0u; /* no dest offset */
761     DmaTcdList[7u].Value = NumberDmaIterWrite; /* iteration count */
762     DmaTcdList[8u].Value = 1u; /* disable hardware request when major loop complete */
763     DmaTcdList[9u].Value = 0u;  /* no src address modulo */
764     if(NULL_PTR == State->TxBuffer)
765     {
766         /* send default data */
767         DmaTcdList[0u].Value = (uint32)&State->ExternalDevice->DeviceParams->DefaultData; /* src address read */
768         if(State->ExternalDevice->DeviceParams->FrameSize < 17u)
769         {
770             DmaTcdList[2u].Value = 0u;  /* src offset is 0 byte */
771         }
772         else
773         {
774             DmaTcdList[9u].Value = 2u;  /* data is 4 bytes, src address modulo is 2 bits */
775         }
776     }
777     else
778     {
779         DmaTcdList[0u].Value = (uint32)State->TxBuffer; /* src address read */
780     }
781     /* Set DESTINATION_SIGNED_LAST_ADDR_ADJ = 0 to avoid the case it still stored from previous TCD Scatter Gather */
782     DmaTcdList[10u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_LAST_ADDR_ADJ;
783     DmaTcdList[10u].Value = 0u;    /* No adjust DADD when major loop completed */
784     /* write TCD for TX DMA channel */
785     (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 11u);
786 
787     /* configure RX DMA channel */
788     DmaTcdList[0u].Value = (uint32)&Base->POPR; /* src address read */
789     DmaTcdList[2u].Value = 0u;  /* no src offset */
790     if(State->ExternalDevice->DeviceParams->FrameSize < 9u)
791     {
792         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; /* 1 byte src transfer size */
793         DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;    /* 1 byte dest transfer size */
794         DmaTcdList[5u].Value = 1u;   /* 1 byte to transfer for each request */
795         DmaTcdList[6u].Value = 1u; /* dest offset is 1 bytes */
796     }
797     else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
798     {
799         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE; /* 2 bytes src transfer size */
800         DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_2_BYTE;    /* 2 bytes dest transfer size */
801         DmaTcdList[5u].Value = 2u;   /* 2 bytes to transfer for each request */
802         DmaTcdList[6u].Value = 2u; /* dest offset is 2 bytes */
803     }
804     else
805     {
806         DmaTcdList[3u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE; /* 4 bytes src transfer size */
807         DmaTcdList[4u].Value = DMA_IP_TRANSFER_SIZE_4_BYTE;    /* 4 bytes dest transfer size */
808         DmaTcdList[5u].Value = 4u;   /* 4 bytes to transfer for each request */
809         DmaTcdList[6u].Value = 4u; /* dest offset is 4 bytes */
810     }
811     if(NULL_PTR == State->RxBuffer)
812     {
813         /* Discard data */
814         DmaTcdList[1u].Value = (uint32)&Spi_Ip_u32DiscardData;    /* dest address write*/
815         DmaTcdList[6u].Value = 0u; /* dest offset is 0 bytes */
816     }
817     else
818     {
819         DmaTcdList[1u].Value = (uint32)State->RxBuffer;    /* dest address write*/
820     }
821     DmaTcdList[7u].Value = NumberDmaIterRead; /* iteration count */
822     DmaTcdList[8u].Value = 1u; /* disable hardware request when major loop complete */
823     /* Set DESTINATION_SIGNED_LAST_ADDR_ADJ = 0 to avoid the case it still stored from previous TCD Scatter Gather */
824     DmaTcdList[9u].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_LAST_ADDR_ADJ;
825     DmaTcdList[9u].Value = 0u;    /* No adjust DADD when major loop completed */
826     /* write TCD for RX DMA channel */
827     (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 10u);
828 
829     /* Enable HW request for RX DMA channel before TX DMA channel */
830     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
831     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
832     if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
833     #endif
834     {
835         (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxCmdDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
836     }
837     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
838 }
839 
840 /**
841 * @brief   Update hardware TCD for DMA channels to continue transfer remain data frames.
842 * @details In the case number of data frames are greater than SPI_IP_DMA_MAX_ITER_CNT_U16, this function will update hardware TCD for DMA channels
843 *          to continue transfer remain data frames. DMA channels will be started at the end of the function.
844 *
845 * @param[in]     Instance      Index of the hardware instance.
846 * @return void
847 */
Spi_Ip_DmaContinueTransfer(uint8 Instance)848 static void Spi_Ip_DmaContinueTransfer(uint8 Instance)
849 {
850     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
851     Dma_Ip_LogicChannelTransferListType DmaTcdList[2u];
852     uint16 NumberDmaIterWrite = State->ExpectedFifoWrites - State->TxIndex;
853     uint16 NumberCmdDmaIterWrite = 0u;
854     uint16 NumberDmaIterRead = 0u;
855     boolean ClearCS = (boolean)FALSE;
856     boolean EnScatterGather = (boolean)FALSE;
857 
858     /* Limits number of major count */
859     if(SPI_IP_DMA_MAX_ITER_CNT_U16 < NumberDmaIterWrite)
860     {
861         NumberDmaIterWrite = SPI_IP_DMA_MAX_ITER_CNT_U16;
862     }
863     else
864     {
865         if((boolean)FALSE == State->KeepCs)
866         {
867             ClearCS = (boolean)TRUE;
868         }
869     }
870 
871     NumberDmaIterRead = NumberDmaIterWrite;
872     if(State->ExternalDevice->DeviceParams->FrameSize > 16u)
873     {
874         /* TX DMA can read 4 bytes from POPR for each request, so the number of RX DMA iter will be a haft */
875         NumberDmaIterRead = NumberDmaIterWrite/2u;
876         /* check to make sure number of frames written should equal number of frame read,
877         avoid the case of data is written without command available in CMD FIFO.
878         NumberDmaIterWrite may not be multiple of 2 due to it was assigned to SPI_IP_DMA_MAX_ITER_CNT_U16
879         or by user in Spi_Ip_AsyncTransmit */
880         if(0u != (NumberDmaIterWrite%2u))
881         {
882             NumberDmaIterWrite = NumberDmaIterRead;
883         }
884     }
885 
886     State->TxIndex += NumberDmaIterWrite;
887     State->RxIndex += NumberDmaIterRead;
888 
889     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
890     if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
891     #endif
892     {
893         /* Update CMD DMA channel */
894         NumberCmdDmaIterWrite = NumberDmaIterRead;
895         /* Update number of remain commands */
896         State->ExpectedCmdFifoWrites -= NumberCmdDmaIterWrite;
897         DmaTcdList[1u].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
898         DmaTcdList[1u].Value = (uint32)&State->PushrCmd;    /* default source address */
899         if((boolean)TRUE == ClearCS)
900         {
901             if(1u == NumberCmdDmaIterWrite)
902             {
903                 DmaTcdList[1u].Value = (uint32)&State->PushrCmdLast;    /* Clear CS command is source address */
904                 EnScatterGather = (boolean)FALSE;
905             }
906             else
907             {
908                 NumberCmdDmaIterWrite = NumberDmaIterRead - 1u;
909                 EnScatterGather = (boolean)TRUE;
910             }
911         }
912         else
913         {
914             EnScatterGather = (boolean)FALSE;
915         }
916         DmaTcdList[0u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
917         DmaTcdList[0u].Value = NumberCmdDmaIterWrite;    /* iteration count */
918         if((boolean)TRUE == EnScatterGather)
919         {
920             /* Update software TCD Scatter Gather 0 */
921             Spi_Ip_CmdDmaTcdSGConfig(Instance, /* Cmd Dma Channel Id */
922                                      State->PhyUnitConfig->TxCmdDmaSGId[0u], /* TCD Scatter Gather Id */
923                                      DmaTcdList[1u].Value, /* src address read */
924                                      (uint16)DmaTcdList[0u].Value, /* iteration count */
925                                      0u /* Not disable hardware request when major loop complete */
926                                     );
927             /* Load software TCD Scatter Gather 0 into hardware TCD with ESG bit already set in software TCD */
928             (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxCmdDmaChannel, State->PhyUnitConfig->TxCmdDmaSGId[0u]);
929             /* Config next TCD Scatter Gather will clear CS */
930             Spi_Ip_CmdDmaTcdSGConfig(Instance,
931                                      State->PhyUnitConfig->TxCmdDmaSGId[1u], /* TCD Scatter Gather Id */
932                                      (uint32)&State->PushrCmdLast, /* src address read */
933                                      1u, /* iteration count is 1 for last push command */
934                                      1u /* disable hardware request when major loop complete */
935                                     );
936         }
937         else
938         {
939             /* Update TCD for CMD DMA channel, ESG bit will be clear in this function */
940             (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxCmdDmaChannel, DmaTcdList, 2u);
941         }
942     }
943 
944     /* Update TX DMA channel */
945     DmaTcdList[0u].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
946     DmaTcdList[0u].Value = NumberDmaIterWrite;    /* iteration count */
947     (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->TxDmaChannel, DmaTcdList, 1u);
948 
949     /* Update RX DMA channel */
950     DmaTcdList[0u].Value = NumberDmaIterRead;    /* iteration count */
951     (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 1u);
952 
953     /* Enable HW request for RX DMA channel before TX DMA channel */
954     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
955     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
956     if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
957     #endif
958     {
959         (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxCmdDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
960     }
961     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
962 }
963 #endif /*#if (SPI_IP_DMA_USED == STD_ON)*/
964 
965 /**
966 * @brief   This function will read data from RX FIFO.
967 * @details This function will read data from RX FIFO.
968 *
969 * @param[in]     NumberOfReads   Number of bytes data will be read from RX FIFO .
970 * @param[in]     Instance       Index of the hardware instance.
971 * @return none
972 */
Spi_Ip_ReadRxFifo(uint16 NumberOfReads,uint8 Instance)973 static void Spi_Ip_ReadRxFifo
974 (
975     uint16 NumberOfReads,
976     uint8 Instance
977 )
978 {
979     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
980     const SPI_Type* Base = Spi_Ip_apxBases[Instance];
981     uint16 Count;
982     uint32 Data;
983 
984     for (Count=0; Count < NumberOfReads; Count++)
985     {
986         Data = Base->POPR;
987         if(NULL_PTR != State->RxBuffer)
988         {
989             if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
990             {
991                 *((uint8*)(&State->RxBuffer[State->RxIndex])) = (uint8)Data;
992             }
993             else if (State->ExternalDevice->DeviceParams->FrameSize < 17u)
994             {
995                 *((uint16*)(&State->RxBuffer[2u * State->RxIndex])) = (uint16)Data;
996             }
997             else
998             {
999                 *((uint32*)(&State->RxBuffer[4u * State->RxIndex])) = Data;
1000             }
1001         }
1002         State->RxIndex++;
1003     }
1004 }
1005 
1006 /**
1007 * @brief   This function will write data to TX FIFO.
1008 * @details This function will write data to TX FIFO.
1009 *
1010 * @param[in]     NumberOfReads   Number of bytes data will be wrote to TX FIFO .
1011 * @param[in]     Instance         Index of the hardware instance.
1012 * @return none
1013 */
Spi_Ip_WriteTxFifo(uint16 NumberOfWrites,uint8 Instance)1014 static void Spi_Ip_WriteTxFifo
1015 (
1016     uint16 NumberOfWrites,
1017     uint8 Instance
1018 )
1019 {
1020     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1021     SPI_Type* Base = Spi_Ip_apxBases[Instance];
1022     uint16 Count;
1023     uint16 Data = 0u;
1024 
1025     for (Count=0; Count < NumberOfWrites; Count++)
1026     {
1027         if(NULL_PTR != State->TxBuffer)
1028         {
1029             if(State->ExternalDevice->DeviceParams->FrameSize < 9u)
1030             {
1031                 Data = *((const uint8*)(&State->TxBuffer[State->TxIndex]));
1032             }
1033             else
1034             {
1035                 Data = *((const uint16*)(&State->TxBuffer[2u * State->TxIndex]));
1036             }
1037         }
1038         else
1039         {
1040             if(State->ExternalDevice->DeviceParams->FrameSize > 16u)
1041             {
1042                 if ((uint16)0u == (State->TxIndex%2u))
1043                 {
1044                     Data = (uint16)State->ExternalDevice->DeviceParams->DefaultData;  /* get 2 bytes */
1045                 }
1046                 else
1047                 {
1048                     Data = (uint16)(State->ExternalDevice->DeviceParams->DefaultData >> 16u);  /* get 2 bytes */
1049                 }
1050             }
1051             else
1052             {
1053                 Data = (uint16)State->ExternalDevice->DeviceParams->DefaultData;
1054             }
1055         }
1056         State->TxIndex++;
1057         Base->PUSHR.FIFO.TX = (uint16)Data;
1058     }
1059 }
1060 
1061 /**
1062 * @brief   This function will read data from RX FIFO in Asynchronous mode.
1063 * @details This function will read data from RX FIFO in Asynchronous mode.
1064 *
1065 * @param[in]     NumberOfReads    Number of bytes in RX FIFO will be read.
1066 * @param[in]     Instance       Index of the hardware instance.
1067 * @return none
1068 */
Spi_Ip_ReceiveData(uint16 NumberOfReads,uint8 Instance)1069 static void Spi_Ip_ReceiveData
1070 (
1071     uint16 NumberOfReads,
1072     uint8 Instance
1073 )
1074 {
1075     Spi_Ip_StateStructureType* const State = Spi_Ip_apxStateStructureArray[Instance];
1076     uint16 ActualNumberOfReads = NumberOfReads;
1077     /* Limits to remaining frames. */
1078     if (ActualNumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
1079     {
1080         ActualNumberOfReads = State->ExpectedFifoReads - State->RxIndex;
1081     }
1082     /* Read data from RX FIFO */
1083     Spi_Ip_ReadRxFifo(ActualNumberOfReads, Instance);
1084     /* Update current TX FIFO slot */
1085     if (State->ExternalDevice->DeviceParams->FrameSize > 16u)
1086     {
1087         State->CurrentTxFifoSlot += NumberOfReads*2u;
1088     }
1089     else
1090     {
1091         State->CurrentTxFifoSlot += NumberOfReads;
1092     }
1093 }
1094 
1095 /**
1096 * @brief   This function will finish transfer of a channel.
1097 * @details This function will finish transfer of a channel.
1098 *
1099 * @param[in]     Instance            Index of the hardware instance.
1100 * @param[in]     ErrorFlag           Save the status of transfer error flags
1101 * @return void
1102 */
Spi_Ip_ChannelFinished(uint8 Instance,boolean ErrorFlag)1103 static void Spi_Ip_ChannelFinished(uint8 Instance, boolean ErrorFlag)
1104 {
1105     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1106     Spi_Ip_EventType EventState = SPI_IP_EVENT_FAULT;
1107 
1108     if (TRUE == ErrorFlag)
1109     {
1110         State->Status = SPI_IP_FAULT;
1111         EventState = SPI_IP_EVENT_FAULT;
1112     }
1113     else
1114     {
1115         State->Status = SPI_IP_IDLE;
1116         EventState = SPI_IP_EVENT_END_TRANSFER;
1117     }
1118 
1119     if (NULL_PTR != State->Callback)
1120     {
1121         State->Callback(Instance, EventState);
1122     }
1123     else
1124     {
1125         (void)EventState;
1126     }
1127 }
1128 
1129 /**
1130 * @brief   This function will write command to CMD FIFO.
1131 * @details This function will write command to CMD FIFO.
1132 *
1133 * @param[in]     NumberOfWrites   Number of time the command will be writen to CMD FIFO .
1134 * @param[in]     Instance         Index of the hardware instance.
1135 * @return none
1136 */
Spi_Ip_WriteCmdFifo(uint16 NumberOfWrites,uint8 Instance)1137 static void Spi_Ip_WriteCmdFifo
1138 (
1139     uint16 NumberOfWrites,
1140     uint8 Instance
1141 )
1142 {
1143     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1144     SPI_Type* Base = Spi_Ip_apxBases[Instance];
1145     uint16 Count;
1146     uint16 ActualNumberOfWrites = NumberOfWrites;
1147 
1148     if (ActualNumberOfWrites > State->ExpectedCmdFifoWrites)
1149     {
1150         ActualNumberOfWrites = State->ExpectedCmdFifoWrites;
1151     }
1152     for (Count=0; Count < ActualNumberOfWrites; Count++)
1153     {
1154         if((1u == State->ExpectedCmdFifoWrites) && ((boolean)FALSE == State->KeepCs))
1155         {
1156             Base->PUSHR.FIFO.CMD = State->PushrCmd & (~((uint16)(SPI_PUSHR_CONT_MASK>>16u)));
1157         }
1158         else
1159         {
1160             Base->PUSHR.FIFO.CMD = State->PushrCmd;
1161         }
1162         State->ExpectedCmdFifoWrites--;
1163     }
1164 }
1165 
1166 /**
1167 * @brief   This function calculates actual TX/RX counter depends on FrameSize.
1168 * @details This function calculates actual TX/RX counter depends on FrameSize.
1169 *
1170 * @param[in]     Instance         Index of the hardware instance.
1171 * @param[in]     Length           Number of bytes transfer.
1172 * @return none
1173 */
Spi_Ip_UpdateTxRxCounter(uint8 Instance,uint16 Length)1174 static void Spi_Ip_UpdateTxRxCounter(uint8 Instance, uint16 Length)
1175 {
1176     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1177 
1178     if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
1179     {
1180         State->ExpectedFifoWrites = Length;
1181     }
1182     else
1183     {
1184         State->ExpectedFifoWrites = Length/2u;
1185     }
1186     State->ExpectedFifoReads = State->ExpectedFifoWrites;
1187     if (State->ExternalDevice->DeviceParams->FrameSize > 16u)
1188     {
1189         State->ExpectedFifoReads = State->ExpectedFifoWrites/2u;
1190     }
1191     State->ExpectedCmdFifoWrites = State->ExpectedFifoReads;
1192 }
1193 
1194 
1195 #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1196 /**
1197 * @brief   This function will verify the validation of some input parameters of transmision functions.
1198 * @details This function will verify the validation of some input parameters of transmision functions.
1199 *
1200 * @param[in]     ExternalDevice   Pointer to the external device where data is transmitted.
1201 * @param[in]     Length         Number of bytes to be sent.
1202 * @return        SPI_IP_STATUS_SUCCESS: Don't have any errors was found.
1203 *                SPI_IP_STATUS_FAIL: Transmission command has not been accepted.
1204 */
Spi_Ip_CheckValidParameters(const Spi_Ip_ExternalDeviceType * ExternalDevice,uint16 Length)1205 static void Spi_Ip_CheckValidParameters(
1206                                                     const Spi_Ip_ExternalDeviceType *ExternalDevice,
1207                                                     uint16 Length
1208                                               )
1209 {
1210 
1211     if (ExternalDevice->DeviceParams->FrameSize > 16u)
1212     {
1213         DevAssert((Length%4) == 0u);
1214     }
1215     else if (ExternalDevice->DeviceParams->FrameSize > 8u)
1216     {
1217         DevAssert((Length%2) == 0u);
1218     }
1219     else
1220     {
1221         /* do nothing */
1222     }
1223 }
1224 #endif
1225 /*==================================================================================================
1226 *                                      GLOBAL FUNCTIONS
1227 ==================================================================================================*/
1228 #if (SPI_IP_DMA_USED == STD_ON)
1229 /**
1230 * @brief   This function will process DMA transfer complete interrupt.
1231 * @details This function will process continue transfer or end of transfer via DMA.
1232 *
1233 * @param[in]     Instance      Index of the hardware instance.
1234 * @return void
1235 * @implements Spi_Ip_IrqDmaHandler_Activity
1236 */
Spi_Ip_IrqDmaHandler(uint8 Instance)1237 void Spi_Ip_IrqDmaHandler(uint8 Instance)
1238 {
1239     SPI_Type* Base = Spi_Ip_apxBases[Instance];
1240     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1241     uint32 SrStatusRegister = 0u;
1242     boolean ErrorFlag = (boolean)FALSE;
1243     boolean EndOfTransferFlag = (boolean)FALSE;
1244 
1245     if(NULL_PTR != State)
1246     {
1247         if (SPI_IP_BUSY == State->Status)
1248         {
1249             /* Read Status and clear all flags. */
1250             SrStatusRegister = Base->SR;
1251             Base->SR &= 0xFFFF0000u;
1252 
1253             if ( (0u != (SrStatusRegister & (SPI_SR_RFOF_MASK | SPI_SR_TFUF_MASK))) )
1254             {
1255                  /* mark error flag */
1256                 ErrorFlag = (boolean)TRUE;
1257             }
1258             else
1259             {
1260                 if (State->ExpectedFifoReads != State->RxIndex)
1261                 {
1262                     /* Transfer is not finished => update TX, RX pointers */
1263                     Spi_Ip_DmaContinueTransfer(Instance);
1264                 }
1265                 else
1266                 {
1267                     EndOfTransferFlag = (boolean)TRUE;
1268                 }
1269             }
1270 
1271             if (((boolean)TRUE == EndOfTransferFlag) || ((boolean)TRUE == ErrorFlag))
1272             {
1273                 /* Only set HALT bit to stop transfer when there is a error or request to de-assert CS at the end of transfers sequence */
1274                 if(((boolean)TRUE == ErrorFlag) || ((boolean)FALSE == State->KeepCs))
1275                 {
1276                     SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_13();
1277                     /* Stop Transfer */
1278                     Base->MCR |= SPI_MCR_HALT_MASK;
1279                     SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_13();
1280                 }
1281                 /* Disable interrupts and DMA requests. */
1282                 Base->RSER = 0U;
1283 
1284                 if((boolean)TRUE == ErrorFlag)
1285                 {
1286                     State->Status = SPI_IP_FAULT;
1287                 }
1288                 else
1289                 {
1290                     State->Status = SPI_IP_IDLE;
1291                 }
1292                 if (State->Callback != NULL_PTR)
1293                 {
1294                     if((boolean)TRUE == ErrorFlag)
1295                     {
1296                         State->Callback(Instance, SPI_IP_EVENT_FAULT);
1297                     }
1298                     else
1299                     {
1300                         State->Callback(Instance, SPI_IP_EVENT_END_TRANSFER);
1301                     }
1302                 }
1303             }
1304         }
1305     }
1306     else
1307     {
1308         /* Driver is initialized but there was no poll request*/
1309         /* nothing to do */
1310     }
1311 }
1312 #endif /* (SPI_IP_DMA_USED == STD_ON) */
1313 
1314 #if (STD_ON == SPI_IP_ENABLE_USER_MODE_SUPPORT)
1315 /**
1316 * @brief This function will set UAA bit in REG_PROT for SPI unit
1317 */
Spi_Ip_SetUserAccess(uint8 Instance)1318 void Spi_Ip_SetUserAccess(uint8 Instance)
1319 {
1320     SPI_Type* Base = Spi_Ip_apxBases[Instance];
1321 
1322     SET_USER_ACCESS_ALLOWED((uint32)Base,SPI_IP_PROT_MEM_U32);
1323 }
1324 
1325 /**
1326 * @brief This function will enable writing all SPI registers under protection in User mode by configuring REG_PROT
1327 */
Spi_Ip_SetUserAccessAllowed(uint8 Instance)1328 static void Spi_Ip_SetUserAccessAllowed(uint8 Instance)
1329 {
1330     OsIf_Trusted_Call1param(Spi_Ip_SetUserAccess, Instance);
1331 }
1332 #endif /* SPI_IP_ENABLE_USER_MODE_SUPPORT */
1333 /*================================================================================================*/
Spi_Ip_Init(const Spi_Ip_ConfigType * PhyUnitConfigPtr)1334 Spi_Ip_StatusType Spi_Ip_Init(const Spi_Ip_ConfigType *PhyUnitConfigPtr)
1335 {
1336     SPI_Type* Base;
1337     Spi_Ip_StateStructureType* State;
1338     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
1339     uint8 Instance = 0u;
1340 
1341     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1342     DevAssert(PhyUnitConfigPtr != NULL_PTR);
1343     #endif
1344     Instance = PhyUnitConfigPtr->Instance;
1345     State = Spi_Ip_apxStateStructureArray[Instance];
1346     Base = Spi_Ip_apxBases[Instance];
1347     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1348     DevAssert(State == NULL_PTR);
1349     #endif
1350     Spi_Ip_apxStateStructureArray[Instance] = &Spi_Ip_axStateStructure[PhyUnitConfigPtr->StateIndex];
1351     State = Spi_Ip_apxStateStructureArray[Instance];
1352     State->PhyUnitConfig = PhyUnitConfigPtr;
1353     #if (STD_ON == SPI_IP_ENABLE_USER_MODE_SUPPORT)
1354     Spi_Ip_SetUserAccessAllowed(Instance);
1355     #endif
1356     /* Halt before update other fields */
1357     Base->MCR |= SPI_MCR_HALT_MASK;
1358     Base->MCR = PhyUnitConfigPtr->Mcr;
1359 
1360     #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1361     State->ClockMode = SPI_IP_NORMAL_CLOCK;
1362     #endif
1363     State->KeepCs = (boolean)FALSE;
1364     #if (SPI_IP_DMA_USED == STD_ON)
1365     #if (SPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT == STD_ON)
1366     Spi_Ip_TxDmaTcdSGInit(Instance);
1367     Spi_Ip_RxDmaTcdSGInit(Instance);
1368     #endif
1369     if((boolean)TRUE == State->PhyUnitConfig->DmaUsed)
1370     {
1371         Spi_Ip_CmdDmaTcdSGInit(Instance);
1372     }
1373     #endif
1374     /* set State to idle */
1375     Status = Spi_Ip_UpdateTransferMode(Instance, PhyUnitConfigPtr->TransferMode);
1376     if (SPI_IP_STATUS_SUCCESS == Status)
1377     {
1378         State->Status = SPI_IP_IDLE;
1379     }
1380     return Status;
1381 }
1382 /*================================================================================================*/
Spi_Ip_DeInit(uint8 Instance)1383 Spi_Ip_StatusType Spi_Ip_DeInit(uint8 Instance)
1384 {
1385     SPI_Type* Base;
1386     const Spi_Ip_StateStructureType* State;
1387     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
1388 
1389     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1390     DevAssert(Instance < SPI_INSTANCE_COUNT);
1391     #endif
1392     Base = Spi_Ip_apxBases[Instance];
1393     State = Spi_Ip_apxStateStructureArray[Instance];
1394     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1395     DevAssert(State != NULL_PTR);
1396     #endif
1397     if (State->Status == SPI_IP_BUSY)
1398     {
1399         Status = SPI_IP_STATUS_FAIL;
1400     }
1401     else
1402     {
1403         /* Halt before update other fields */
1404         Base->MCR |= SPI_MCR_HALT_MASK;
1405         /* Reset FIFOs */
1406         Base->MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK;
1407         Base->MCR = 0x4001u;
1408         Base->MODE.CTAR[0] = 0x78000000u;
1409         Base->SR = 0xFFFF0000u;
1410         Base->RSER = 0u;
1411         Base->CTARE[0] = 0x1u;
1412 
1413         Spi_Ip_apxStateStructureArray[Instance] = NULL_PTR;
1414     }
1415     return Status;
1416 }
1417 
1418 /*================================================================================================*/
Spi_Ip_SyncTransmit(const Spi_Ip_ExternalDeviceType * ExternalDevice,const uint8 * TxBuffer,uint8 * RxBuffer,uint16 Length,uint32 TimeOut)1419 Spi_Ip_StatusType Spi_Ip_SyncTransmit(
1420                                       const Spi_Ip_ExternalDeviceType *ExternalDevice,
1421                                       const uint8 *TxBuffer,
1422                                       uint8 *RxBuffer,
1423                                       uint16 Length,
1424                                       uint32 TimeOut
1425                                      )
1426 {
1427     SPI_Type *Base;
1428     Spi_Ip_StateStructureType *State;
1429     uint16 NumberOfReads;
1430     uint16 NumberOfWrites;
1431     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
1432     uint32 TimeoutTicks = OsIf_MicrosToTicks(TimeOut, SPI_IP_TIMEOUT_METHOD);
1433     uint32 CurrentTicks = 0u; /* initialize current counter */
1434     uint32 ElapsedTicks = 0u; /* elapsed will give timeout */
1435     uint8 Instance = 0u;
1436     uint16 PushrCmd = 0u;
1437     uint32 LsbValue = 0u;
1438 
1439     #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
1440     DevAssert(ExternalDevice != NULL_PTR);
1441     DevAssert(0u != Length);
1442     DevAssert(0u != TimeOut);
1443     Spi_Ip_CheckValidParameters(ExternalDevice, Length);
1444     #endif
1445     Instance = ExternalDevice->Instance;
1446     State = Spi_Ip_apxStateStructureArray[Instance];
1447     #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
1448     DevAssert(State != NULL_PTR);
1449     #endif
1450 
1451     PushrCmd = ExternalDevice->PushrCmd;
1452     Base = Spi_Ip_apxBases[Instance];
1453     SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_08();
1454     if (State->Status == SPI_IP_BUSY)
1455     {
1456         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
1457         Status = SPI_IP_STATUS_FAIL;
1458     }
1459     else
1460     {
1461         State->ExternalDevice = ExternalDevice;
1462         /* Get Lsb value */
1463         LsbValue = State->ExternalDevice->DeviceParams->Lsb ? 1UL : 0UL;
1464         /* Update State structure and internal variables used for timeout */
1465         State->Status = SPI_IP_BUSY;
1466         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
1467 
1468         /* Make sure that FIFOs will be empty before start new transfer session */
1469         Base->MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK;
1470         /* Reset Flags */
1471         Base->SR = 0xFFFF0000u;
1472 
1473         State->PushrCmd = ExternalDevice->PushrCmd;
1474         State->RxIndex = 0u;
1475         State->TxIndex = 0u;
1476         State->TxBuffer = TxBuffer;
1477         State->RxBuffer = RxBuffer;
1478 
1479         Spi_Ip_UpdateTxRxCounter(Instance, Length);
1480         /* To increase the performance, Some frames can be transferred using 1 CMD. Support maximum SPI_IP_CTARE_DTCP_MAX_U16 frames. */
1481         /* Due to CS signal always de-assert at the beginning of next channel (after move driver to stop mode by set HALT bit) so this mode only support in IP layer
1482            or Job has only 1 channel */
1483         if ((State->ExpectedCmdFifoWrites <= SPI_IP_CTARE_DTCP_MAX_U16) && (State->ExpectedCmdFifoWrites > 1u) && (FALSE == State->KeepCs))
1484         {
1485             State->CtareDtcpSupport = TRUE;
1486         }
1487         else
1488         {
1489             State->CtareDtcpSupport = FALSE;
1490         }
1491 
1492         /* Configure external device parameters  like: cs, clock phase, clock polarity. */
1493         #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1494         Base->MODE.CTAR[0u] = ExternalDevice->Ctar[State->ClockMode] | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1495         #else
1496         Base->MODE.CTAR[0u] = ExternalDevice->Ctar | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1497         #endif
1498         if (State->CtareDtcpSupport)
1499         {
1500             /* Use CTAR0/CTARE0 to transfer all (frames - 1) */
1501             Base->CTARE[0u] = SPI_CTARE_FMSZE((((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) >> 4u) & 0x1u) | SPI_CTARE_DTCP((uint32)State->ExpectedCmdFifoWrites - 1u);
1502             Base->PUSHR.FIFO.CMD = (PushrCmd | (uint16)(SPI_PUSHR_CTAS(0U)>>16u));
1503             /* Use CTAR1/CTARE1 to transfer latest frame to clear CONT bit */
1504             Base->CTARE[1u] = SPI_CTARE_FMSZE((((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) >> 4u) & 0x1u) | SPI_CTARE_DTCP(1u);
1505             Base->PUSHR.FIFO.CMD = (PushrCmd | (uint16)(SPI_PUSHR_CTAS(1U)>>16u)) & (~((uint16)(SPI_PUSHR_CONT_MASK>>16u)));
1506             /* Configure external device parameters  like: cs, clock phase, clock polarity. */
1507             #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1508                 Base->MODE.CTAR[1u] = ExternalDevice->Ctar[State->ClockMode] | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1509             #else
1510                 Base->MODE.CTAR[1u] = ExternalDevice->Ctar | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1511             #endif
1512         }
1513         else
1514         {
1515             Base->CTARE[0u] = ExternalDevice->Ctare | SPI_CTARE_FMSZE((((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) >> 4u) & 0x1u);
1516         }
1517 
1518         CurrentTicks = OsIf_GetCounter(SPI_IP_TIMEOUT_METHOD); /* initialize current counter */
1519 
1520         /* Get current FIFO slots are available.*/
1521         State->CurrentTxFifoSlot = SPI_IP_FIFO_SIZE_U16;
1522         while(SPI_IP_STATUS_SUCCESS == Status)
1523         {
1524             /* SEND CMD */
1525             /* if number of frames <= SPI_IP_CTARE_DTCP_MAX_U16 and this is latest channel. All frames will be transferred using only 1 CMD which has push to TX CMD above */
1526             if (FALSE == State->CtareDtcpSupport)
1527             {
1528                 /* Cmd must be pushed before data, push Cmd until HW cmd fifo is full */
1529                 NumberOfWrites = (uint16)((Base->SREX) & SPI_SREX_CMDCTR_MASK) >> SPI_SREX_CMDCTR_SHIFT;
1530                 NumberOfWrites = SPI_IP_FIFO_SIZE_U16 - NumberOfWrites;
1531                 /* Write to CMD FIFO */
1532                 if ((NumberOfWrites != 0u) && (State->ExpectedCmdFifoWrites != 0u))
1533                 {
1534                     Spi_Ip_WriteCmdFifo(NumberOfWrites, Instance);
1535                     ElapsedTicks = 0;
1536                 }
1537             }
1538             /* TRANSMIT */
1539 
1540             /* Push data until HW fifo is full or transfer is done. */
1541             /* After driver code read all frames in RX FIFO, if there are still some frames in TX FIFO, at the time before driver code check number of frames available in TX FIFO
1542             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.
1543             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.
1544             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.
1545             So, RX FIFO can be overflow. To avoid this, limits total of frames in TX FIFO and RX FIFO must be lower than FIFO size.
1546             State->CurrentTxFifoSlot variable is used to hanlde number of frames are "on bus transfer". They are always less than FIFO size */
1547 
1548             /* Limits to remaining frames. */
1549             if (State->CurrentTxFifoSlot > (State->ExpectedFifoWrites - State->TxIndex))
1550             {
1551                 State->CurrentTxFifoSlot = State->ExpectedFifoWrites - State->TxIndex;
1552             }
1553             if (State->CurrentTxFifoSlot != 0u)
1554             {
1555                 Spi_Ip_WriteTxFifo(State->CurrentTxFifoSlot, Instance);
1556                 /* Update current TX FIFO slot can be written */
1557                 State->CurrentTxFifoSlot = 0u;
1558                 ElapsedTicks = 0;
1559 				/* Clear Halt bit, then transfer */
1560 				if(((Base->MCR) & SPI_MCR_HALT_MASK) == SPI_MCR_HALT_MASK)
1561 				{
1562 					Base->MCR &= ~SPI_MCR_HALT_MASK;
1563 				}
1564             }
1565             /* RECEIVE */
1566             /* Read all data available in receive HW fifo. */
1567             NumberOfReads = (uint16)(((Base->SR) & SPI_SR_RXCTR_MASK) >> SPI_SR_RXCTR_SHIFT);
1568             if(NumberOfReads != 0u)
1569             {
1570                 /* Read data from RX FIFO */
1571                 Spi_Ip_ReceiveData(NumberOfReads, Instance);
1572                 /* Finish the transfer if all frames have received */
1573                 if (State->RxIndex == State->ExpectedFifoReads)
1574                 {
1575                     break;
1576                 }
1577                  ElapsedTicks = 0;
1578             }
1579 
1580             /* Check if errors like overflow or underflow are reported in Status register or timeout error */
1581             ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, SPI_IP_TIMEOUT_METHOD);
1582             if (ElapsedTicks >= TimeoutTicks)
1583             {
1584                 Status = SPI_IP_TIMEOUT;
1585             }
1586         }
1587         /* Only set HALT bit to stop transfer when there is a error or request to de-assert CS at the end of transfers sequence */
1588         if((SPI_IP_STATUS_SUCCESS != Status) || ((boolean)FALSE == State->KeepCs))
1589         {
1590             /* Stop transfer */
1591             Base->MCR |= SPI_MCR_HALT_MASK;
1592         }
1593         /* Channel finished */
1594         Spi_Ip_ChannelFinished(Instance, FALSE);
1595     }
1596     return Status;
1597 }
1598 
Spi_Ip_AsyncTransmit(const Spi_Ip_ExternalDeviceType * ExternalDevice,const uint8 * TxBuffer,uint8 * RxBuffer,uint16 Length,Spi_Ip_CallbackType EndCallback)1599 Spi_Ip_StatusType Spi_Ip_AsyncTransmit(
1600                                        const Spi_Ip_ExternalDeviceType *ExternalDevice,
1601                                        const uint8 *TxBuffer,
1602                                        uint8 *RxBuffer,
1603                                        uint16 Length,
1604                                        Spi_Ip_CallbackType EndCallback
1605                                       )
1606 {
1607     SPI_Type* Base;
1608     Spi_Ip_StateStructureType* State;
1609     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
1610     uint32 LsbValue;
1611     uint8 Instance;
1612     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
1613     uint16 NumberOfWrites = 0u;
1614     #endif
1615     uint16 NumberOfCmdWrites = 0u;
1616     #if (SPI_IP_DMA_USED == STD_ON)
1617     Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
1618     #endif
1619 
1620     #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
1621     DevAssert(ExternalDevice != NULL_PTR);
1622     DevAssert(0u != Length);
1623     Spi_Ip_CheckValidParameters(ExternalDevice, Length);
1624     #endif
1625     Instance = ExternalDevice->Instance;
1626     State = Spi_Ip_apxStateStructureArray[Instance];
1627     #if (STD_ON == SPI_IP_DEV_ERROR_DETECT)
1628     DevAssert(State != NULL_PTR);
1629     #endif
1630 
1631     Base = Spi_Ip_apxBases[Instance];
1632     SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_09();
1633     if (SPI_IP_BUSY == State->Status)
1634     {
1635         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
1636         Status = SPI_IP_STATUS_FAIL;
1637     }
1638     else
1639     {
1640         State->ExternalDevice = ExternalDevice;
1641         /* Get Lsb value */
1642         LsbValue = State->ExternalDevice->DeviceParams->Lsb ? 1UL : 0UL;
1643         /* Mark the hardware as busy. */
1644         State->Status = SPI_IP_BUSY;
1645         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_09();
1646 
1647         /* Update State structure. */
1648         State->RxIndex = 0u;
1649         State->TxIndex = 0u;
1650         State->TxBuffer = TxBuffer;
1651         State->RxBuffer = RxBuffer;
1652         State->Callback = EndCallback;
1653         if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
1654         {
1655             State->ExpectedFifoWrites = Length;
1656         }
1657         else
1658         {
1659             State->ExpectedFifoWrites = Length/2u;
1660         }
1661 
1662         State->ExpectedFifoReads = State->ExpectedFifoWrites;
1663         if (State->ExternalDevice->DeviceParams->FrameSize >16u)
1664         {
1665             State->ExpectedFifoReads = State->ExpectedFifoWrites/2u;
1666         }
1667         State->ExpectedCmdFifoWrites = State->ExpectedFifoReads;
1668         State->PushrCmd = ExternalDevice->PushrCmd;
1669         /* Get current FIFO slots are available.*/
1670         State->CurrentTxFifoSlot = SPI_IP_FIFO_SIZE_U16;
1671         /* Make sure that FIFOs will be empty before start new transfer session */
1672         Base->MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK;
1673         /* Clear all flags. */
1674         Base->SR &= 0xFFFF0000u;
1675         /* Configure external device parameters  like: cs, clock phase, clock polarity. */
1676         #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
1677         if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
1678         #endif
1679         {
1680             #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1681                 Base->MODE.CTAR[0u] = ExternalDevice->Ctar[State->ClockMode] | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1682             #else
1683                 Base->MODE.CTAR[0u] = ExternalDevice->Ctar | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1684             #endif
1685             Base->CTARE[0u] = ExternalDevice->Ctare | SPI_CTARE_FMSZE((((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) >> 4u) & 0x1u);
1686         }
1687         #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
1688         else
1689         {
1690             #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1691                 Base->MODE.CTAR[0u] = (ExternalDevice->Ctar[State->ClockMode] & (~SPI_CTAR_SLAVE_FMSZ_MASK)) | SPI_CTAR_SLAVE_FMSZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u);
1692             #else
1693                 Base->MODE.CTAR[0u] = (ExternalDevice->Ctar & (~SPI_CTAR_SLAVE_FMSZ_MASK)) | SPI_CTAR_SLAVE_FMSZ((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u);
1694             #endif
1695         }
1696         #endif
1697 
1698         #if (SPI_IP_DMA_USED == STD_ON)
1699         if((boolean)FALSE == State->PhyUnitConfig->DmaUsed)
1700         #endif
1701         {
1702             switch(State->TransferMode)
1703             {
1704                 case SPI_IP_POLLING:
1705                     /* Disable interrupts and DMA requests. */
1706                     Base->RSER = 0U;
1707                     break;
1708                 case SPI_IP_INTERRUPT:
1709                     /* Enable interrupts. */
1710                     Base->RSER = SPI_RSER_TCF_RE(1) | SPI_RSER_TFUF_RE(1) | SPI_RSER_RFOF_RE(1);
1711                     /* Fill data into TX FIFO to trigger TCF interrupt */
1712                     /* Write to CMD field first*/
1713                     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
1714                     if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
1715                     #endif
1716                     {
1717                         /* Cmd must be pushed before data, push Cmd until HW cmd fifo is full */
1718                         NumberOfCmdWrites = (uint16)((Base->SREX) & SPI_SREX_CMDCTR_MASK) >> SPI_SREX_CMDCTR_SHIFT;
1719                         NumberOfCmdWrites = SPI_IP_FIFO_SIZE_U16 - NumberOfCmdWrites;
1720                         /* Write to CMD FIFO */
1721                         if ((NumberOfCmdWrites != 0u) && (State->ExpectedCmdFifoWrites != 0u))
1722                         {
1723                             Spi_Ip_WriteCmdFifo(NumberOfCmdWrites, Instance);
1724                         }
1725                         /* Limits to remaining frames. */
1726 						if (State->CurrentTxFifoSlot > (State->ExpectedFifoWrites - State->TxIndex))
1727 						{
1728 							State->CurrentTxFifoSlot = State->ExpectedFifoWrites - State->TxIndex;
1729 						}
1730 						if (State->CurrentTxFifoSlot != 0u)
1731 						{
1732 							Spi_Ip_WriteTxFifo(State->CurrentTxFifoSlot, Instance);
1733 							/* Update current TX FIFO slot can be written */
1734 							State->CurrentTxFifoSlot = 0u;
1735 						}
1736                     }
1737                     #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
1738                     else
1739                     {
1740                         /* In slave mode, TXFIFO will be wrote full first before Master device performs transmision */
1741                         NumberOfWrites = (uint16)((Base->SR) & SPI_SR_TXCTR_MASK) >> SPI_SR_TXCTR_SHIFT;
1742                         if (NumberOfWrites < SPI_IP_FIFO_SIZE_U16)
1743                         {
1744                             NumberOfWrites = SPI_IP_FIFO_SIZE_U16 - NumberOfWrites;
1745                         }
1746                         else
1747                         {
1748                             NumberOfWrites = 0u;
1749                         }
1750                         /* Limits to remaining frames. */
1751                         if (NumberOfWrites > (State->ExpectedFifoWrites - State->TxIndex))
1752                         {
1753                             NumberOfWrites = State->ExpectedFifoWrites - State->TxIndex;
1754                         }
1755                         /* Write to TXFIFO*/
1756                         Spi_Ip_WriteTxFifo(NumberOfWrites, Instance);
1757                         /* Update current TX FIFO available */
1758                         State->CurrentTxFifoSlot -= NumberOfWrites;
1759                     }
1760                     #endif
1761                     break;
1762                 default:
1763                     /* Should be non-empty to avoid misra 16.4 */
1764                     break;
1765             }
1766         }
1767         #if (SPI_IP_DMA_USED == STD_ON)
1768         else
1769         {
1770             /* Activate RX DMA interrupt in interrupt mode or disable then in polling mode. */
1771             DmaTcdList[0u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
1772             switch(State->TransferMode)
1773             {
1774                 case SPI_IP_POLLING:
1775                     /* Disable DMA major interrupt. */
1776                     DmaTcdList[0u].Value = 0u;
1777                     break;
1778                 case SPI_IP_INTERRUPT:
1779                     /* Enable DMA major interrupt. */
1780                     DmaTcdList[0u].Value = 1u;
1781                     break;
1782                 default:
1783                     /* Should be non-empty to avoid misra 16.4 */
1784                     break;
1785             }
1786             (void)Dma_Ip_SetLogicChannelTransferList(State->PhyUnitConfig->RxDmaChannel, DmaTcdList, 1u);
1787             /* Config and Enable DMA request. */
1788 			Spi_Ip_DmaConfig(Instance);
1789             Base->RSER = SPI_RSER_CMDFFF_RE(1) | SPI_RSER_CMDFFF_DIRS(1) | SPI_RSER_TFFF_RE(1) | SPI_RSER_TFFF_DIRS(1) | SPI_RSER_RFDF_RE(1) | SPI_RSER_RFDF_DIRS(1);
1790         }
1791         #endif
1792 		SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_11();
1793         /* Clear Halt bit before transfer */
1794         Base->MCR &= ~SPI_MCR_HALT_MASK;
1795         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_11();
1796     }
1797     return Status;
1798 }
1799 
1800 #if ((SPI_IP_DMA_USED == STD_ON) && (SPI_IP_ENABLE_DMAFASTTRANSFER_SUPPORT == STD_ON))
Spi_Ip_AsyncTransmitFast(const Spi_Ip_FastTransferType * FastTransferCfg,uint8 NumberOfTransfer,Spi_Ip_CallbackType EndCallback)1801 Spi_Ip_StatusType Spi_Ip_AsyncTransmitFast(
1802                                        const Spi_Ip_FastTransferType *FastTransferCfg,
1803                                        uint8 NumberOfTransfer,
1804                                        Spi_Ip_CallbackType EndCallback
1805                                       )
1806 {
1807     SPI_Type* Base;
1808     Spi_Ip_StateStructureType* State;
1809     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
1810     uint8 Instance = 0u;
1811     uint32 LsbValue = 0u;
1812     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1813     uint8 Count = 0u;
1814     #endif
1815 
1816 #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1817     DevAssert(NULL_PTR != FastTransferCfg);
1818     DevAssert(NULL_PTR != FastTransferCfg[0u].ExternalDevice);
1819 #endif
1820     Instance = FastTransferCfg[0u].ExternalDevice->Instance;
1821     Base = Spi_Ip_apxBases[Instance];
1822     State = Spi_Ip_apxStateStructureArray[Instance];
1823     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
1824     DevAssert(NULL_PTR != State);
1825     DevAssert(State->TransferMode == SPI_IP_INTERRUPT);
1826     DevAssert(NumberOfTransfer <= State->PhyUnitConfig->MaxNumOfFastTransfer);
1827 
1828     for(Count = 0u; Count < NumberOfTransfer; Count++)
1829     {
1830         DevAssert(NULL_PTR != FastTransferCfg[Count].ExternalDevice);
1831         DevAssert(0u != FastTransferCfg[Count].Length);
1832         if (FastTransferCfg[0u].ExternalDevice->DeviceParams->FrameSize > 16u)
1833         {
1834             DevAssert((FastTransferCfg[Count].Length%4) == 0u);
1835         }
1836         else if (FastTransferCfg[0u].ExternalDevice->DeviceParams->FrameSize > 8u)
1837         {
1838             DevAssert((FastTransferCfg[Count].Length%2) == 0u);
1839         }
1840         else
1841         {
1842             DevAssert(SPI_IP_DMA_MAX_ITER_CNT_U16 >= FastTransferCfg[Count].Length);
1843         }
1844     }
1845     #endif
1846     SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_14();
1847     if (SPI_IP_BUSY == State->Status)
1848     {
1849         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_14();
1850         Status = SPI_IP_STATUS_FAIL;
1851     }
1852     else
1853     {
1854         /* Mark the hardware as busy. */
1855         State->Status = SPI_IP_BUSY;
1856         SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_14();
1857 
1858         /* Make sure that FIFOs will be empty before start new transfer session */
1859         Base->MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK;
1860         /* Clear all flags. */
1861         Base->SR &= 0xFFFF0000u;
1862 
1863         /* Update State structure. */
1864         /* For Dma Fast transfer, All transfers use the same HWUnit and in Master mode only. Only some parameters can be changed as Continuous CS, PCS.
1865         Some parameters such as Baudrate, Clock Polarity, Clock Phase, Delays timming configuration, Bit Order, Frame Size
1866         must be the same between transfers. So, make sure they are configured the same in each External Device allocated for Dma Fast Transfers.
1867         And all those attributes can be got from first transfer in FastTransferCfg */
1868         State->ExternalDevice = FastTransferCfg[0u].ExternalDevice;
1869         /* Get Lsb value */
1870         LsbValue = State->ExternalDevice->DeviceParams->Lsb ? 1UL : 0UL;
1871         State->Callback = EndCallback;
1872         /* Stop transfer at the end of transfers sequence by set HALT bit in Spi_Ip_IrqDmaHandler */
1873         State->KeepCs = (boolean)FALSE;
1874 
1875         /* Configure external device parameters  like: frane size, clock phase, clock polarity. */
1876         #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
1877             Base->MODE.CTAR[0u] = FastTransferCfg[0u].ExternalDevice->Ctar[State->ClockMode] | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & 0xFu) | SPI_CTAR_LSBFE(LsbValue);
1878         #else
1879             Base->MODE.CTAR[0u] = FastTransferCfg[0u].ExternalDevice->Ctar | SPI_CTAR_FMSZ(((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) & (uint32)0xFu) | SPI_CTAR_LSBFE(LsbValue);
1880         #endif
1881         Base->CTARE[0u] = FastTransferCfg[0u].ExternalDevice->Ctare | SPI_CTARE_FMSZE((((uint32)State->ExternalDevice->DeviceParams->FrameSize - 1u) >> 4u) & (uint32)0x1u);
1882         /* Config and Enable DMA request. */
1883 		Spi_Ip_DmaFastConfig(Instance, FastTransferCfg, NumberOfTransfer);
1884         Base->RSER = SPI_RSER_CMDFFF_RE(1u) | SPI_RSER_CMDFFF_DIRS(1u) | SPI_RSER_TFFF_RE(1u) | SPI_RSER_TFFF_DIRS(1u) | SPI_RSER_RFDF_RE(1u) | SPI_RSER_RFDF_DIRS(1u);
1885 
1886         /* Clear Halt bit before transfer */
1887         Base->MCR &= ~SPI_MCR_HALT_MASK;
1888     }
1889     return Status;
1890 }
1891 
1892 /**
1893 * @brief   This function will configure Scatter/Gather TCDs for the channels TX DMA, RX DMA and CMD DMA
1894 *          according to Dma Fast transfers configuration. DMA channels will be started at the end of the function.
1895 */
Spi_Ip_DmaFastConfig(uint8 Instance,const Spi_Ip_FastTransferType * FastTransferCfg,uint8 NumberOfTransfer)1896 static void Spi_Ip_DmaFastConfig(uint8 Instance, const Spi_Ip_FastTransferType *FastTransferCfg, uint8 NumberOfTransfer)
1897 {
1898     Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
1899     boolean ClearCS = (boolean)FALSE;
1900     uint8 DisHwRequest = 0u;
1901     uint8 Count = 0u;
1902     uint8 CmdTCDSGIndex = 0u;
1903     Dma_Ip_LogicChannelTransferListType DmaTcdList[1u];
1904 
1905     DmaTcdList[0u].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
1906     DmaTcdList[0u].Value = 1u;
1907 
1908     for(Count = 0u; Count < NumberOfTransfer; Count++)
1909     {
1910         /* Update State structure. */
1911         State->RxIndex = 0u;
1912         State->TxIndex = 0u;
1913         State->TxBuffer = FastTransferCfg[Count].TxBuffer;
1914         State->RxBuffer = FastTransferCfg[Count].RxBuffer;
1915         if (State->ExternalDevice->DeviceParams->FrameSize < 9u)
1916         {
1917             State->ExpectedFifoWrites = FastTransferCfg[Count].Length;
1918         }
1919         else
1920         {
1921             State->ExpectedFifoWrites = FastTransferCfg[Count].Length/2u;
1922         }
1923         State->ExpectedFifoReads = State->ExpectedFifoWrites;
1924         if (State->ExternalDevice->DeviceParams->FrameSize >16u)
1925         {
1926             State->ExpectedFifoReads = State->ExpectedFifoWrites/2u;
1927         }
1928         State->ExpectedCmdFifoWrites = State->ExpectedFifoReads;
1929         State->PhyUnitConfig->CmdDmaFast[Count].DefaultData = FastTransferCfg[Count].DefaultData;
1930         State->PhyUnitConfig->CmdDmaFast[Count].DmaFastPushrCmd = FastTransferCfg[Count].ExternalDevice->PushrCmd;
1931         State->PhyUnitConfig->CmdDmaFast[Count].DmaFastPushrCmdLast = FastTransferCfg[Count].ExternalDevice->PushrCmd & (~((uint16)(SPI_PUSHR_CONT_MASK>>16u)));
1932 
1933         /* CS will be cleared for last transfer or depend on KeepCs if not last transfer.
1934         Disable DMA HW request at the end of transfer. */
1935         if(Count == (NumberOfTransfer - 1u))
1936         {
1937             ClearCS = (boolean)TRUE;
1938             DisHwRequest = 1u;
1939         }
1940         else
1941         {
1942             if((boolean)FALSE == FastTransferCfg[Count].KeepCs)
1943             {
1944                 ClearCS = (boolean)TRUE;
1945             }
1946             else
1947             {
1948                 ClearCS = (boolean)FALSE;
1949             }
1950             DisHwRequest = 0u;
1951         }
1952 
1953         /* Configure software TCDs Scatter Gather for CMD DMA channel */
1954         if((boolean)TRUE == ClearCS)
1955         {
1956             if(State->ExpectedCmdFifoWrites > 1u)
1957             {
1958                 Spi_Ip_CmdDmaTcdSGConfig(   Instance,
1959                                             State->PhyUnitConfig->TxCmdDmaSGId[CmdTCDSGIndex],
1960                                             (uint32)&State->PhyUnitConfig->CmdDmaFast[Count].DmaFastPushrCmd,
1961                                             State->ExpectedCmdFifoWrites - 1u,
1962                                             0u  /* not disable dma hw request, the transfer will be continued after next software TCD Scatter Gather loaded */
1963                                         );
1964                 CmdTCDSGIndex++;
1965             }
1966             Spi_Ip_CmdDmaTcdSGConfig(   Instance,
1967                                         State->PhyUnitConfig->TxCmdDmaSGId[CmdTCDSGIndex],
1968                                         (uint32)&State->PhyUnitConfig->CmdDmaFast[Count].DmaFastPushrCmdLast,
1969                                         1u, /* transfer last command to clear CS */
1970                                         DisHwRequest
1971                                     );
1972             CmdTCDSGIndex++;
1973         }
1974         else
1975         {
1976             Spi_Ip_CmdDmaTcdSGConfig(   Instance,
1977                                         State->PhyUnitConfig->TxCmdDmaSGId[CmdTCDSGIndex],
1978                                         (uint32)&State->PhyUnitConfig->CmdDmaFast[Count].DmaFastPushrCmd,
1979                                         State->ExpectedCmdFifoWrites,
1980                                         DisHwRequest
1981                                     );
1982             CmdTCDSGIndex++;
1983         }
1984         State->ExpectedCmdFifoWrites = 0u;
1985 
1986         /* Configure software TCDs Scatter Gather for TX DMA channel */
1987         Spi_Ip_TxDmaTcdSGConfig(Instance, Count, DisHwRequest);
1988 
1989         /* Configure software TCDs Scatter Gather for RX DMA channel */
1990         Spi_Ip_RxDmaTcdSGConfig(Instance, Count, DisHwRequest);
1991     }
1992 
1993     /* When all transfers session are completed and next TCD ScatterGather is loaded to HW. If next TCD ScatterGather loaded has INTMAJOR=0 then
1994     Dma_Ip interrupt function will not call Spi Dma notification due to it understood as spurious interrupt(Done flag = 1, INTMAJOR=0).
1995     So, the workaround is set INTMAJOR=1 for next TCD ScatterGather. */
1996     if (NumberOfTransfer < State->PhyUnitConfig->NumberRxSG)
1997     {
1998         /* Set INTMAJOR=1 for next RX TCD ScatterGather */
1999         (void)Dma_Ip_SetLogicChannelScatterGatherList(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[NumberOfTransfer], DmaTcdList, 1u);
2000     }
2001 
2002     /* Load first software TCD to hardware TCD for CMD DMA channel */
2003     (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxCmdDmaChannel, State->PhyUnitConfig->TxCmdDmaSGId[0u]);
2004     /* Load first software TCD to hardware TCD for TX DMA channel */
2005     (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->TxDmaChannel, State->PhyUnitConfig->TxDmaFastSGId[0u]);
2006     /* Load first software TCD to hardware TCD for RX DMA channel */
2007     (void)Dma_Ip_SetLogicChannelScatterGatherConfig(State->PhyUnitConfig->RxDmaChannel, State->PhyUnitConfig->RxDmaFastSGId[0u]);
2008 
2009     /* Enable HW request for RX DMA channel before TX DMA channel */
2010     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
2011     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxCmdDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
2012     (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
2013 }
2014 #endif
2015 
Spi_Ip_ManageBuffers(uint8 Instance)2016 void Spi_Ip_ManageBuffers(uint8 Instance)
2017 {
2018     const Spi_Ip_StateStructureType* State;
2019     #if (SPI_IP_DMA_USED == STD_ON)
2020     Dma_Ip_LogicChannelStatusType DmaChannelStatus;
2021     #endif
2022 
2023     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2024     DevAssert(Instance < SPI_INSTANCE_COUNT);
2025     #endif
2026     State = Spi_Ip_apxStateStructureArray[Instance];
2027     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2028     DevAssert(State != NULL_PTR);
2029     #endif
2030     if(SPI_IP_POLLING == State->TransferMode)
2031     {
2032         #if (SPI_IP_DMA_USED == STD_ON)
2033         if((boolean)FALSE == State->PhyUnitConfig->DmaUsed)
2034         #endif
2035         {
2036             Spi_Ip_TransferProcess(Instance);
2037         }
2038         #if (SPI_IP_DMA_USED == STD_ON)
2039         else
2040         {
2041             DmaChannelStatus.Done = FALSE;
2042             (void)Dma_Ip_GetLogicChannelStatus(State->PhyUnitConfig->RxDmaChannel, &DmaChannelStatus);
2043             if((boolean)TRUE == DmaChannelStatus.Done)
2044             {
2045                 /* Clear DONE bit */
2046                 (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_CLEAR_DONE);
2047                 Spi_Ip_IrqDmaHandler(Instance);
2048             }
2049         }
2050         #endif
2051     }
2052 }
2053 /*================================================================================================*/
Spi_Ip_UpdateFrameSize(const Spi_Ip_ExternalDeviceType * ExternalDevice,uint8 FrameSize)2054 Spi_Ip_StatusType Spi_Ip_UpdateFrameSize(const Spi_Ip_ExternalDeviceType *ExternalDevice, uint8 FrameSize)
2055 {
2056     const Spi_Ip_StateStructureType* State;
2057     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
2058 
2059     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2060     DevAssert(ExternalDevice != NULL_PTR);
2061     DevAssert(SPI_IP_FRAMESIZE_MAX_U8 >= FrameSize);
2062     DevAssert(SPI_IP_FRAMESIZE_MIN_U8 <= FrameSize);
2063     #endif
2064     State = Spi_Ip_apxStateStructureArray[ExternalDevice->Instance];
2065     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2066     DevAssert(State != NULL_PTR);
2067     #endif
2068     /* Frame size can be changed when no transfers are in progress. */
2069     if (State->Status != SPI_IP_BUSY)
2070     {
2071         ExternalDevice->DeviceParams->FrameSize = FrameSize;
2072     }
2073     else
2074     {
2075         Status = SPI_IP_STATUS_FAIL;
2076     }
2077     return Status;
2078 }
2079 
Spi_Ip_UpdateLsb(const Spi_Ip_ExternalDeviceType * ExternalDevice,boolean Lsb)2080 Spi_Ip_StatusType Spi_Ip_UpdateLsb(const Spi_Ip_ExternalDeviceType *ExternalDevice, boolean Lsb)
2081 {
2082     const Spi_Ip_StateStructureType* State;
2083     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
2084 
2085     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2086     DevAssert(ExternalDevice != NULL_PTR);
2087     #endif
2088     State = Spi_Ip_apxStateStructureArray[ExternalDevice->Instance];
2089     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2090     DevAssert(State != NULL_PTR);
2091     #endif
2092     /* Bite order can be changed when no transfers are in progress. */
2093     if (State->Status != SPI_IP_BUSY)
2094     {
2095         ExternalDevice->DeviceParams->Lsb = Lsb;
2096     }
2097     else
2098     {
2099         Status = SPI_IP_STATUS_FAIL;
2100     }
2101     return Status;
2102 }
2103 
Spi_Ip_UpdateDefaultTransmitData(const Spi_Ip_ExternalDeviceType * ExternalDevice,uint32 DefaultData)2104 Spi_Ip_StatusType Spi_Ip_UpdateDefaultTransmitData(const Spi_Ip_ExternalDeviceType *ExternalDevice, uint32 DefaultData)
2105 {
2106     const Spi_Ip_StateStructureType* State;
2107     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
2108 
2109     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2110     DevAssert(ExternalDevice != NULL_PTR);
2111     #endif
2112     State = Spi_Ip_apxStateStructureArray[ExternalDevice->Instance];
2113     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2114     DevAssert(State != NULL_PTR);
2115     #endif
2116     /* Bite order can be changed when no transfers are in progress. */
2117     if (State->Status != SPI_IP_BUSY)
2118     {
2119         ExternalDevice->DeviceParams->DefaultData = DefaultData;
2120     }
2121     else
2122     {
2123         Status = SPI_IP_STATUS_FAIL;
2124     }
2125     return Status;
2126 }
2127 
Spi_Ip_UpdateTransferMode(uint8 Instance,Spi_Ip_ModeType Mode)2128 Spi_Ip_StatusType Spi_Ip_UpdateTransferMode(uint8 Instance, Spi_Ip_ModeType Mode)
2129 {
2130     Spi_Ip_StateStructureType* State;
2131     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
2132 
2133     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2134     DevAssert(Instance < SPI_INSTANCE_COUNT);
2135     #endif
2136     State = Spi_Ip_apxStateStructureArray[Instance];
2137     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2138     DevAssert(State != NULL_PTR);
2139     #endif
2140     /* Transfer mode can be changed when no transfers are in progress. */
2141     if (State->Status != SPI_IP_BUSY)
2142     {
2143         State->TransferMode = Mode;
2144     }
2145     else
2146     {
2147         Status = SPI_IP_STATUS_FAIL;
2148     }
2149     return Status;
2150 }
2151 
Spi_Ip_Cancel(uint8 Instance)2152 void Spi_Ip_Cancel(uint8 Instance)
2153 {
2154     SPI_Type* Base;
2155     Spi_Ip_StateStructureType* State;
2156 
2157     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2158     DevAssert(Instance < SPI_INSTANCE_COUNT);
2159     #endif
2160     Base = Spi_Ip_apxBases[Instance];
2161     State = Spi_Ip_apxStateStructureArray[Instance];
2162     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2163     DevAssert(State != NULL_PTR);
2164     #endif
2165     SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_10();
2166     if(SPI_IP_BUSY == State->Status)
2167     {
2168         /* Halt before update RSER */
2169         Base->MCR |= SPI_MCR_HALT_MASK;
2170         /* Disable interrupts and DMA requests. */
2171         Base->RSER = 0U;
2172         #if (SPI_IP_DMA_USED == STD_ON)
2173         if((boolean)TRUE == State->PhyUnitConfig->DmaUsed)
2174         {
2175             /* Disable all HW request */
2176             (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->RxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
2177             #if (SPI_IP_SLAVE_SUPPORT == STD_ON)
2178             if((boolean)FALSE == State->PhyUnitConfig->SlaveMode)
2179             #endif
2180             {
2181                 (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxCmdDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
2182             }
2183             (void)Dma_Ip_SetLogicChannelCommand(State->PhyUnitConfig->TxDmaChannel, DMA_IP_CH_CLEAR_HARDWARE_REQUEST);
2184         }
2185         #endif
2186         /* Clear FIFO */
2187         Base->MCR |= (SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK);
2188         /* set State to idle */
2189         State->Status = SPI_IP_IDLE;
2190     }
2191     SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_10();
2192 }
2193 
2194 /**
2195 * @brief   This function is called by SPI ISRs.
2196 * @details This function will process activities for flags TCF, RFOF and TFUF.
2197 *
2198 * @param[in]     Instance            Instance of the hardware unit.
2199 *
2200 * @implements Spi_Ip_IrqHandler_Activity
2201 */
Spi_Ip_IrqHandler(uint8 Instance)2202 void Spi_Ip_IrqHandler(uint8 Instance)
2203 {
2204     SPI_Type* Base = Spi_Ip_apxBases[Instance];
2205     const Spi_Ip_StateStructureType* State = Spi_Ip_apxStateStructureArray[Instance];
2206     uint32 IrqFlags = 0u;
2207 
2208     if(NULL_PTR != State)
2209     {
2210         /* the driver has been initialized */
2211         IrqFlags = Base->SR & (SPI_SR_TCF_MASK | SPI_SR_RFOF_MASK | SPI_SR_TFUF_MASK);
2212         IrqFlags &= Base->RSER & (SPI_RSER_TCF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_TFUF_RE_MASK);
2213         if(0u != IrqFlags)
2214         {
2215             Spi_Ip_TransferProcess(Instance);
2216         }
2217         else
2218         {
2219             /* Do nothing - Return immediately */
2220         }
2221     }
2222     else
2223     {
2224         /* the driver has not been initialized */
2225         /* clear all flags */
2226         Base->SR &= 0xFFFF0000u;
2227     }
2228 }
2229 
2230 /**
2231 * @brief   This function returns the status of the SPI driver.
2232 * @details This function returns the status of the SPI driver.
2233 *
2234 * @return Spi_Ip_HwStatusType
2235 *
2236 * @param[in]     Instance            Instance of the hardware unit.
2237 */
Spi_Ip_GetStatus(uint8 Instance)2238 Spi_Ip_HwStatusType Spi_Ip_GetStatus(uint8 Instance)
2239 {
2240     const Spi_Ip_StateStructureType* State;
2241     Spi_Ip_HwStatusType Status = SPI_IP_UNINIT;
2242 
2243     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2244     DevAssert(Instance < SPI_INSTANCE_COUNT);
2245     #endif
2246     State = Spi_Ip_apxStateStructureArray[Instance];
2247     if (State != NULL_PTR)
2248     {
2249         Status = State->Status;
2250     }
2251     return Status;
2252 }
2253 
2254 #if (SPI_IP_DUAL_CLOCK_MODE == STD_ON)
Spi_Ip_SetClockMode(uint8 Instance,Spi_Ip_DualClockModeType ClockMode)2255 Spi_Ip_StatusType Spi_Ip_SetClockMode(uint8 Instance, Spi_Ip_DualClockModeType ClockMode)
2256 {
2257     Spi_Ip_StateStructureType* State;
2258     Spi_Ip_StatusType Status = SPI_IP_STATUS_SUCCESS;
2259 
2260     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2261     DevAssert(Instance < SPI_INSTANCE_COUNT);
2262     #endif
2263     State = Spi_Ip_apxStateStructureArray[Instance];
2264     #if (SPI_IP_DEV_ERROR_DETECT == STD_ON)
2265     DevAssert(State != NULL_PTR);
2266     #endif
2267     /* Clock mode can be changed when no transfers are in progress. */
2268     if (State->Status != SPI_IP_BUSY)
2269     {
2270         State->ClockMode = ClockMode;
2271     }
2272     else
2273     {
2274         Status = SPI_IP_STATUS_FAIL;
2275     }
2276     return Status;
2277 }
2278 #endif
2279 
2280 #define SPI_STOP_SEC_CODE
2281 #include "Spi_MemMap.h"
2282 
2283 #ifdef __cplusplus
2284 }
2285 #endif
2286 
2287 /** @} */
2288