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