1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020, 2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_i2c_dma.h"
10 #include "fsl_flexcomm.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 /* Component ID definition, used by tools. */
17 #ifndef FSL_COMPONENT_ID
18 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2c_dma"
19 #endif
20 
21 /*<! @brief Structure definition for i2c_master_dma_handle_t. The structure is private. */
22 typedef struct _i2c_master_dma_private_handle
23 {
24     I2C_Type *base;
25     i2c_master_dma_handle_t *handle;
26 } i2c_master_dma_private_handle_t;
27 
28 /*!
29  * @brief Used for conversion from `flexcomm_irq_handler_t` to `flexcomm_i2c_dma_master_irq_handler_t`
30  */
31 typedef union i2c_dma_to_flexcomm
32 {
33     flexcomm_i2c_dma_master_irq_handler_t i2c_dma_master_handler;
34     flexcomm_irq_handler_t flexcomm_handler;
35 } i2c_dma_to_flexcomm_t;
36 
37 /*******************************************************************************
38  * Prototypes
39  ******************************************************************************/
40 
41 /*!
42  * @brief DMA callback for I2C master DMA driver.
43  *
44  * @param handle DMA handler for I2C master DMA driver
45  * @param userData user param passed to the callback function
46  */
47 static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode);
48 
49 /*!
50  * @brief Set up master transfer, send slave address and sub address(if any), wait until the
51  * wait until address sent status return.
52  *
53  * @param base I2C peripheral base address.
54  * @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state.
55  * @param xfer pointer to i2c_master_transfer_t structure.
56  */
57 static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
58                                                 i2c_master_dma_handle_t *handle,
59                                                 i2c_master_transfer_t *xfer);
60 
61 static void I2C_RunDMATransfer(I2C_Type *base, i2c_master_dma_handle_t *handle);
62 
63 /*!
64  * @brief Execute states until the transfer is done.
65  * @param handle Master nonblocking driver handle.
66  * @param[out] isDone Set to true if the transfer has completed.
67  * @retval #kStatus_Success
68  * @retval #kStatus_I2C_ArbitrationLost
69  * @retval #kStatus_I2C_Nak
70  */
71 static status_t I2C_RunTransferStateMachineDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, bool *isDone);
72 /*******************************************************************************
73  * Variables
74  ******************************************************************************/
75 
76 /*! @brief IRQ name array */
77 static const IRQn_Type s_i2cIRQ[] = I2C_IRQS;
78 
79 /*<! Private handle only used for internally. */
80 static i2c_master_dma_private_handle_t s_dmaPrivateHandle[ARRAY_SIZE(s_i2cIRQ)];
81 
82 /*******************************************************************************
83  * Codes
84  ******************************************************************************/
I2C_InitTransferStateMachineDMA(I2C_Type * base,i2c_master_dma_handle_t * handle,i2c_master_transfer_t * xfer)85 static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
86                                                 i2c_master_dma_handle_t *handle,
87                                                 i2c_master_transfer_t *xfer)
88 {
89     struct _i2c_master_transfer *transfer;
90 
91     handle->transfer = *xfer;
92     transfer         = &(handle->transfer);
93 
94     handle->transferCount     = 0U;
95     handle->remainingBytesDMA = 0U;
96     handle->buf               = (uint8_t *)transfer->data;
97     handle->remainingSubaddr  = 0U;
98 
99     if ((transfer->flags & (uint32_t)kI2C_TransferNoStartFlag) != 0U)
100     {
101         handle->checkAddrNack = false;
102         /* Start condition shall not be ommited, switch directly to next phase */
103         if (transfer->dataSize == 0U)
104         {
105             handle->state = (uint8_t)kStopState;
106         }
107         else if (handle->transfer.direction == kI2C_Write)
108         {
109             handle->state = (uint8_t)kTransmitDataState;
110         }
111         else if (handle->transfer.direction == kI2C_Read)
112         {
113             handle->state = (xfer->dataSize == 1U) ? (uint8_t)kReceiveLastDataState : (uint8_t)kReceiveDataState;
114         }
115         else
116         {
117             return kStatus_I2C_InvalidParameter;
118         }
119     }
120     else
121     {
122         if (transfer->subaddressSize != 0U)
123         {
124             int i;
125             uint32_t subaddress;
126 
127             if (transfer->subaddressSize > sizeof(handle->subaddrBuf))
128             {
129                 return kStatus_I2C_InvalidParameter;
130             }
131 
132             /* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
133             subaddress = xfer->subaddress;
134             for (i = (int)xfer->subaddressSize - 1; i >= 0; i--)
135             {
136                 handle->subaddrBuf[i] = (uint8_t)subaddress & 0xffU;
137                 subaddress >>= 8;
138             }
139             handle->remainingSubaddr = transfer->subaddressSize;
140         }
141 
142         handle->state         = (uint8_t)kStartState;
143         handle->checkAddrNack = true;
144     }
145 
146     return kStatus_Success;
147 }
148 
I2C_RunDMATransfer(I2C_Type * base,i2c_master_dma_handle_t * handle)149 static void I2C_RunDMATransfer(I2C_Type *base, i2c_master_dma_handle_t *handle)
150 {
151     uint32_t transfer_size;
152     dma_transfer_config_t xferConfig;
153     uint32_t address;
154     address = (uint32_t)&base->MSTDAT;
155 
156     /* Update transfer count */
157     int32_t count = handle->buf - (uint8_t *)handle->transfer.data;
158     assert(count >= 0);
159     handle->transferCount = (uint32_t)count;
160 
161     /* Check if there is anything to be transferred at all */
162     if (handle->remainingBytesDMA == 0U)
163     {
164         /* No data to be transferrred, disable DMA */
165         base->MSTCTL = 0;
166         return;
167     }
168 
169     /* Calculate transfer size */
170     transfer_size = handle->remainingBytesDMA;
171     if (transfer_size > (uint32_t)I2C_MAX_DMA_TRANSFER_COUNT)
172     {
173         transfer_size = (uint32_t)I2C_MAX_DMA_TRANSFER_COUNT;
174     }
175 
176     switch (handle->transfer.direction)
177     {
178         case kI2C_Write:
179             DMA_PrepareTransfer(&xferConfig, handle->buf, (uint32_t *)address, sizeof(uint8_t), transfer_size,
180                                 kDMA_MemoryToPeripheral, NULL);
181             break;
182 
183         case kI2C_Read:
184             DMA_PrepareTransfer(&xferConfig, (uint32_t *)address, handle->buf, sizeof(uint8_t), transfer_size,
185                                 kDMA_PeripheralToMemory, NULL);
186             break;
187 
188         default:
189             /* This should never happen */
190             assert(0);
191             break;
192     }
193 
194     (void)DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
195     DMA_StartTransfer(handle->dmaHandle);
196 
197     handle->remainingBytesDMA -= transfer_size;
198     handle->buf += transfer_size;
199     handle->checkAddrNack = false;
200 }
201 
I2C_RunTransferStateMachineDMA(I2C_Type * base,i2c_master_dma_handle_t * handle,bool * isDone)202 static status_t I2C_RunTransferStateMachineDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, bool *isDone)
203 {
204     uint32_t status;
205     uint32_t master_state;
206     struct _i2c_master_transfer *transfer;
207     dma_transfer_config_t xferConfig;
208     status_t err;
209     uint32_t start_flag = 0U;
210     uint32_t address;
211     address = (uint32_t)&base->MSTDAT;
212 
213     transfer = &(handle->transfer);
214 
215     *isDone = false;
216 
217     status = I2C_GetStatusFlags(base);
218 
219     if ((status & (uint32_t)I2C_STAT_MSTARBLOSS_MASK) != 0U)
220     {
221         I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK);
222         DMA_AbortTransfer(handle->dmaHandle);
223         base->MSTCTL = 0;
224         return kStatus_I2C_ArbitrationLost;
225     }
226 
227     if ((status & (uint32_t)I2C_STAT_MSTSTSTPERR_MASK) != 0U)
228     {
229         I2C_MasterClearStatusFlags(base, I2C_STAT_MSTSTSTPERR_MASK);
230         DMA_AbortTransfer(handle->dmaHandle);
231         base->MSTCTL = 0;
232         return kStatus_I2C_StartStopError;
233     }
234 
235     /* Event timeout happens when the time since last bus event has been longer than the time specified by TIMEOUT
236        register. eg: Start signal fails to generate, no error status is set and transfer hangs if glitch on bus happens
237        before, the timeout status can be used to avoid the transfer hangs indefinitely. */
238     if ((status & (uint32_t)kI2C_EventTimeoutFlag) != 0U)
239     {
240         I2C_ClearStatusFlags(base, (uint32_t)kI2C_EventTimeoutFlag);
241         DMA_AbortTransfer(handle->dmaHandle);
242         base->MSTCTL = 0;
243         return kStatus_I2C_EventTimeout;
244     }
245 
246     /* SCL timeout happens when the slave is holding the SCL line low and the time has been longer than the time
247        specified by TIMEOUT register. */
248     if ((status & (uint32_t)kI2C_SclTimeoutFlag) != 0U)
249     {
250         I2C_ClearStatusFlags(base, (uint32_t)kI2C_SclTimeoutFlag);
251         DMA_AbortTransfer(handle->dmaHandle);
252         base->MSTCTL = 0;
253         return kStatus_I2C_SclLowTimeout;
254     }
255 
256     if ((status & (uint32_t)I2C_STAT_MSTPENDING_MASK) == 0U)
257     {
258         return kStatus_I2C_Busy;
259     }
260 
261     /* Get the state of the I2C module */
262     master_state = (base->STAT & (uint32_t)I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
263 
264     if ((master_state == (uint32_t)I2C_STAT_MSTCODE_NACKADR) || (master_state == (uint32_t)I2C_STAT_MSTCODE_NACKDAT))
265     {
266         /* Slave NACKed last byte, issue stop and return error */
267         DMA_AbortTransfer(handle->dmaHandle);
268         base->MSTCTL  = I2C_MSTCTL_MSTSTOP_MASK;
269         handle->state = (uint8_t)kWaitForCompletionState;
270         if ((master_state == (uint32_t)I2C_STAT_MSTCODE_NACKADR) || (handle->checkAddrNack == true))
271         {
272             return kStatus_I2C_Addr_Nak;
273         }
274         else
275         {
276             return kStatus_I2C_Nak;
277         }
278     }
279 
280     err = kStatus_Success;
281 
282     if (handle->state == (uint8_t)kStartState)
283     {
284         /* set start flag for later use */
285         start_flag = I2C_MSTCTL_MSTSTART_MASK;
286 
287         if (handle->remainingSubaddr != 0U)
288         {
289             base->MSTDAT  = (uint32_t)transfer->slaveAddress << 1;
290             handle->state = (uint8_t)kTransmitSubaddrState;
291         }
292         else if (transfer->direction == kI2C_Write)
293         {
294             base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
295             if (transfer->dataSize == 0U)
296             {
297                 /* No data to be transferred, initiate start and schedule stop */
298                 base->MSTCTL  = I2C_MSTCTL_MSTSTART_MASK;
299                 handle->state = (uint8_t)kStopState;
300                 return err;
301             }
302             handle->state = (uint8_t)kTransmitDataState;
303         }
304         else if ((transfer->direction == kI2C_Read) && (transfer->dataSize > 0U))
305         {
306             base->MSTDAT = ((uint32_t)transfer->slaveAddress << 1) | 1u;
307             if (transfer->dataSize == 1U)
308             {
309                 /* The very last byte is always received by means of SW */
310                 base->MSTCTL  = I2C_MSTCTL_MSTSTART_MASK;
311                 handle->state = (uint8_t)kReceiveLastDataState;
312                 return err;
313             }
314             handle->state = (uint8_t)kReceiveDataState;
315         }
316         else
317         {
318             handle->state = (uint8_t)kIdleState;
319             err           = kStatus_I2C_UnexpectedState;
320             return err;
321         }
322     }
323 
324     switch (handle->state)
325     {
326         case (uint8_t)kTransmitSubaddrState:
327             if ((master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY) && (0U == start_flag))
328             {
329                 return kStatus_I2C_UnexpectedState;
330             }
331 
332             base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
333 
334             /* Prepare and submit DMA transfer. */
335             DMA_PrepareTransfer(&xferConfig, handle->subaddrBuf, (uint32_t *)address, sizeof(uint8_t),
336                                 handle->remainingSubaddr, kDMA_MemoryToPeripheral, NULL);
337             (void)DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
338             DMA_StartTransfer(handle->dmaHandle);
339             handle->remainingSubaddr = 0;
340             if (transfer->dataSize != 0U)
341             {
342                 /* There is data to be transferred, if there is write to read turnaround it is necessary to perform
343                  * repeated start */
344                 handle->state = (transfer->direction == kI2C_Read) ? (uint8_t)kStartState : (uint8_t)kTransmitDataState;
345             }
346             else
347             {
348                 /* No more data, schedule stop condition */
349                 handle->state = (uint8_t)kStopState;
350             }
351             break;
352 
353         case (uint8_t)kTransmitDataState:
354             if ((master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY) && (0U == start_flag))
355             {
356                 return kStatus_I2C_UnexpectedState;
357             }
358 
359             base->MSTCTL              = start_flag | I2C_MSTCTL_MSTDMA_MASK;
360             handle->remainingBytesDMA = handle->transfer.dataSize;
361 
362             I2C_RunDMATransfer(base, handle);
363 
364             /* Schedule stop condition */
365             handle->state         = (uint8_t)kStopState;
366             handle->checkAddrNack = false;
367             break;
368 
369         case (uint8_t)kReceiveDataState:
370             if ((master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY) && (0U == start_flag))
371             {
372                 if (0U == (transfer->flags & (uint32_t)kI2C_TransferNoStartFlag))
373                 {
374                     return kStatus_I2C_UnexpectedState;
375                 }
376             }
377 
378             base->MSTCTL              = start_flag | I2C_MSTCTL_MSTDMA_MASK;
379             handle->remainingBytesDMA = handle->transfer.dataSize - 1U;
380 
381             if ((transfer->flags & (uint32_t)kI2C_TransferNoStartFlag) != 0U)
382             {
383                 /* Read the master data register to avoid the data be read again */
384                 (void)base->MSTDAT;
385             }
386             I2C_RunDMATransfer(base, handle);
387 
388             /* Schedule reception of last data byte */
389             handle->state         = (uint8_t)kReceiveLastDataState;
390             handle->checkAddrNack = false;
391             break;
392 
393         case (uint8_t)kReceiveLastDataState:
394             if (master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY)
395             {
396                 return kStatus_I2C_UnexpectedState;
397             }
398 
399             ((uint8_t *)transfer->data)[transfer->dataSize - 1U] = (uint8_t)base->MSTDAT;
400             handle->transferCount++;
401 
402             /* No more data expected, issue NACK and STOP right away */
403             if (0U == (transfer->flags & (uint32_t)kI2C_TransferNoStopFlag))
404             {
405                 base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
406             }
407             handle->state = (uint8_t)kWaitForCompletionState;
408             break;
409 
410         case (uint8_t)kStopState:
411             if ((transfer->flags & (uint32_t)kI2C_TransferNoStopFlag) != 0U)
412             {
413                 /* Stop condition is omitted, we are done */
414                 *isDone       = true;
415                 handle->state = (uint8_t)kIdleState;
416                 break;
417             }
418             /* Send stop condition */
419             base->MSTCTL  = I2C_MSTCTL_MSTSTOP_MASK;
420             handle->state = (uint8_t)kWaitForCompletionState;
421             break;
422 
423         case (uint8_t)kWaitForCompletionState:
424             *isDone       = true;
425             handle->state = (uint8_t)kIdleState;
426             break;
427 
428         case (uint8_t)kStartState:
429         case (uint8_t)kIdleState:
430         default:
431             /* State machine shall not be invoked again once it enters the idle state */
432             err = kStatus_I2C_UnexpectedState;
433             break;
434     }
435 
436     return err;
437 }
438 
I2C_MasterTransferDMAHandleIRQ(I2C_Type * base,i2c_master_dma_handle_t * handle)439 static void I2C_MasterTransferDMAHandleIRQ(I2C_Type *base, i2c_master_dma_handle_t *handle)
440 {
441     bool isDone;
442     status_t result;
443 
444     /* Don't do anything if we don't have a valid handle. */
445     if (NULL == handle)
446     {
447         return;
448     }
449 
450     result = I2C_RunTransferStateMachineDMA(base, handle, &isDone);
451 
452     if ((result != kStatus_Success) || isDone)
453     {
454         /* Restore handle to idle state. */
455         handle->state = (uint8_t)kIdleState;
456 
457         /* Disable internal IRQ enables. */
458         I2C_DisableInterrupts(base, I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK |
459                                         I2C_INTSTAT_MSTSTSTPERR_MASK | I2C_INTSTAT_EVENTTIMEOUT_MASK);
460 
461         /* Invoke callback. */
462         if (handle->completionCallback != NULL)
463         {
464             handle->completionCallback(base, handle, result, handle->userData);
465         }
466     }
467 }
468 
I2C_MasterTransferCallbackDMA(dma_handle_t * handle,void * userData,bool transferDone,uint32_t intmode)469 static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData, bool transferDone, uint32_t intmode)
470 {
471     i2c_master_dma_private_handle_t *dmaPrivateHandle;
472 
473     /* Don't do anything if we don't have a valid handle. */
474     if (NULL == handle)
475     {
476         return;
477     }
478 
479     dmaPrivateHandle = (i2c_master_dma_private_handle_t *)userData;
480     I2C_RunDMATransfer(dmaPrivateHandle->base, dmaPrivateHandle->handle);
481 }
482 
483 /*!
484  * brief Init the I2C handle which is used in transactional functions
485  *
486  * param base I2C peripheral base address
487  * param handle pointer to i2c_master_dma_handle_t structure
488  * param callback pointer to user callback function
489  * param userData user param passed to the callback function
490  * param dmaHandle DMA handle pointer
491  */
I2C_MasterTransferCreateHandleDMA(I2C_Type * base,i2c_master_dma_handle_t * handle,i2c_master_dma_transfer_callback_t callback,void * userData,dma_handle_t * dmaHandle)492 void I2C_MasterTransferCreateHandleDMA(I2C_Type *base,
493                                        i2c_master_dma_handle_t *handle,
494                                        i2c_master_dma_transfer_callback_t callback,
495                                        void *userData,
496                                        dma_handle_t *dmaHandle)
497 {
498     assert(handle != NULL);
499     assert(dmaHandle != NULL);
500 
501     uint32_t instance;
502     i2c_dma_to_flexcomm_t handler;
503     handler.i2c_dma_master_handler = I2C_MasterTransferDMAHandleIRQ;
504 
505     /* Zero handle. */
506     (void)memset(handle, 0, sizeof(*handle));
507 
508     /* Look up instance number */
509     instance = I2C_GetInstance(base);
510 
511     /* Set the user callback and userData. */
512     handle->completionCallback = callback;
513     handle->userData           = userData;
514 
515     FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
516 
517     /* Clear internal IRQ enables and enable NVIC IRQ. */
518     I2C_DisableInterrupts(base, I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK |
519                                     I2C_INTSTAT_MSTSTSTPERR_MASK | I2C_INTSTAT_EVENTTIMEOUT_MASK);
520     (void)EnableIRQ(s_i2cIRQ[instance]);
521 
522     /* Set the handle for DMA. */
523     handle->dmaHandle = dmaHandle;
524 
525     s_dmaPrivateHandle[instance].base   = base;
526     s_dmaPrivateHandle[instance].handle = handle;
527 
528     DMA_SetCallback(dmaHandle, I2C_MasterTransferCallbackDMA, &s_dmaPrivateHandle[instance]);
529 }
530 
531 /*!
532  * brief Performs a master dma non-blocking transfer on the I2C bus
533  *
534  * param base I2C peripheral base address
535  * param handle pointer to i2c_master_dma_handle_t structure
536  * param xfer pointer to transfer structure of i2c_master_transfer_t
537  * retval kStatus_Success Sucessully complete the data transmission.
538  * retval kStatus_I2C_Busy Previous transmission still not finished.
539  * retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
540  * retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
541  * retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
542  */
I2C_MasterTransferDMA(I2C_Type * base,i2c_master_dma_handle_t * handle,i2c_master_transfer_t * xfer)543 status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer)
544 {
545     status_t result;
546 
547     assert(handle != NULL);
548     assert(xfer != NULL);
549     assert(xfer->subaddressSize <= sizeof(xfer->subaddress));
550 
551     /* Return busy if another transaction is in progress. */
552     if (handle->state != (uint8_t)kIdleState)
553     {
554         return kStatus_I2C_Busy;
555     }
556 
557     /* Enable the master function and disable the slave function. */
558     I2C_MasterEnable(base, true);
559     I2C_SlaveEnable(base, false);
560 
561     /* Prepare transfer state machine. */
562     result = I2C_InitTransferStateMachineDMA(base, handle, xfer);
563 
564     /* Clear error flags. */
565     I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
566 
567     /* Enable I2C internal IRQ sources */
568     /* Enable arbitration lost interrupt, start/stop error interrupt and master pending interrupt.
569        The master pending flag is not set during dma transfer. */
570     I2C_EnableInterrupts(base, I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK |
571                                    I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_EVENTTIMEOUT_MASK);
572 
573     return result;
574 }
575 
576 /*!
577  * brief Get master transfer status during a dma non-blocking transfer
578  *
579  * param base I2C peripheral base address
580  * param handle pointer to i2c_master_dma_handle_t structure
581  * param count Number of bytes transferred so far by the non-blocking transaction.
582  */
I2C_MasterTransferGetCountDMA(I2C_Type * base,i2c_master_dma_handle_t * handle,size_t * count)583 status_t I2C_MasterTransferGetCountDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, size_t *count)
584 {
585     assert(handle != NULL);
586 
587     if (NULL == count)
588     {
589         return kStatus_InvalidArgument;
590     }
591 
592     /* Catch when there is not an active transfer. */
593     if (handle->state == (uint8_t)kIdleState)
594     {
595         *count = 0;
596         return kStatus_NoTransferInProgress;
597     }
598 
599     /* There is no necessity to disable interrupts as we read a single integer value */
600     *count = handle->transferCount;
601     return kStatus_Success;
602 }
603 
604 /*!
605  * brief Abort a master dma non-blocking transfer in a early time
606  *
607  * param base I2C peripheral base address
608  * param handle pointer to i2c_master_dma_handle_t structure
609  */
I2C_MasterTransferAbortDMA(I2C_Type * base,i2c_master_dma_handle_t * handle)610 void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle)
611 {
612     uint32_t status;
613     uint32_t master_state;
614 
615     if (handle->state != (uint8_t)kIdleState)
616     {
617         DMA_AbortTransfer(handle->dmaHandle);
618 
619         /* Disable DMA */
620         base->MSTCTL = 0;
621 
622         /* Disable internal IRQ enables. */
623         I2C_DisableInterrupts(base, I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK |
624                                         I2C_INTSTAT_MSTSTSTPERR_MASK | I2C_INTSTAT_EVENTTIMEOUT_MASK);
625 
626         /* Wait until module is ready */
627         do
628         {
629             status = I2C_GetStatusFlags(base);
630         } while ((status & (uint8_t)I2C_STAT_MSTPENDING_MASK) == 0U);
631 
632         /* Clear controller state. */
633         I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
634 
635         /* Get the state of the I2C module */
636         master_state = (base->STAT & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
637 
638         if (master_state != (uint32_t)I2C_STAT_MSTCODE_IDLE)
639         {
640             /* Send a stop command to finalize the transfer. */
641             base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
642 
643             /* Wait until module is ready */
644             do
645             {
646                 status = I2C_GetStatusFlags(base);
647             } while ((status & (uint32_t)I2C_STAT_MSTPENDING_MASK) == 0U);
648 
649             /* Clear controller state. */
650             I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
651         }
652 
653         /* Reset the state to idle. */
654         handle->state = (uint8_t)kIdleState;
655     }
656 }
657