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