1 /*
2  * Copyright (c) 2015, 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_flexio_i2c_master.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.flexio_i2c_master"
18 #endif
19 
20 /*! @brief  FLEXIO I2C transfer state */
21 enum _flexio_i2c_master_transfer_states
22 {
23     kFLEXIO_I2C_Idle             = 0x0U, /*!< I2C bus idle */
24     kFLEXIO_I2C_Start            = 0x1U, /*!< I2C start phase */
25     kFLEXIO_I2C_SendCommand      = 0x2U, /*!< Send command byte phase */
26     kFLEXIO_I2C_SendData         = 0x3U, /*!< Send data transfer phase*/
27     kFLEXIO_I2C_ReceiveDataBegin = 0x4U, /*!< Receive data begin transfer phase*/
28     kFLEXIO_I2C_ReceiveData      = 0x5U, /*!< Receive data transfer phase*/
29 };
30 
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 
35 /*!
36  * @brief Set up master transfer, send slave address and decide the initial
37  * transfer state.
38  *
39  * @param base pointer to FLEXIO_I2C_Type structure
40  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
41  * @param transfer pointer to flexio_i2c_master_transfer_t structure
42  */
43 static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
44                                                           flexio_i2c_master_handle_t *handle,
45                                                           flexio_i2c_master_transfer_t *xfer);
46 
47 /*!
48  * @brief Master run transfer state machine to perform a byte of transfer.
49  *
50  * @param base pointer to FLEXIO_I2C_Type structure
51  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
52  * @param statusFlags flexio i2c hardware status
53  * @retval kStatus_Success Successfully run state machine
54  * @retval kStatus_FLEXIO_I2C_Nak Receive Nak during transfer
55  */
56 static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
57                                                          flexio_i2c_master_handle_t *handle,
58                                                          uint32_t statusFlags);
59 
60 /*!
61  * @brief Complete transfer, disable interrupt and call callback.
62  *
63  * @param base pointer to FLEXIO_I2C_Type structure
64  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
65  * @param status flexio transfer status
66  */
67 static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
68                                               flexio_i2c_master_handle_t *handle,
69                                               status_t status);
70 
71 /*******************************************************************************
72  * Codes
73  ******************************************************************************/
74 
FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type * base)75 static uint32_t FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type *base)
76 {
77     return FLEXIO_GetInstance(base->flexioBase);
78 }
79 
FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_t * xfer)80 static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
81                                                           flexio_i2c_master_handle_t *handle,
82                                                           flexio_i2c_master_transfer_t *xfer)
83 {
84     bool needRestart;
85     uint32_t byteCount;
86 
87     /* Init the handle member. */
88     handle->transfer.slaveAddress   = xfer->slaveAddress;
89     handle->transfer.direction      = xfer->direction;
90     handle->transfer.subaddress     = xfer->subaddress;
91     handle->transfer.subaddressSize = xfer->subaddressSize;
92     handle->transfer.data           = xfer->data;
93     handle->transfer.dataSize       = xfer->dataSize;
94     handle->transfer.flags          = xfer->flags;
95     handle->transferSize            = xfer->dataSize;
96 
97     /* Initial state, i2c start state. */
98     handle->state = (uint8_t)kFLEXIO_I2C_Start;
99 
100     /* Clear all status before transfer. */
101     FLEXIO_I2C_MasterClearStatusFlags(base, (uint32_t)kFLEXIO_I2C_ReceiveNakFlag);
102 
103     /* Calculate whether need to send re-start. */
104     needRestart         = (handle->transfer.subaddressSize != 0U) && (handle->transfer.direction == kFLEXIO_I2C_Read);
105     handle->needRestart = needRestart;
106 
107     /* Calculate total byte count in a frame. */
108     byteCount = 1U;
109 
110     if (!needRestart)
111     {
112         byteCount += handle->transfer.dataSize;
113     }
114 
115     if (handle->transfer.subaddressSize != 0U)
116     {
117         byteCount += handle->transfer.subaddressSize;
118     }
119 
120     /* Configure data count. */
121     if (FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)byteCount) != kStatus_Success)
122     {
123         return kStatus_InvalidArgument;
124     }
125 
126     /* Configure timer1 disable condition. */
127     uint32_t tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
128     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
129     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPreTimerDisable);
130     base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
131 
132 #if I2C_RETRY_TIMES
133     uint32_t waitTimes = I2C_RETRY_TIMES;
134     while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
135            (0U != --waitTimes))
136     {
137     }
138     if (0U == waitTimes)
139     {
140         return kStatus_FLEXIO_I2C_Timeout;
141     }
142 #else
143     while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
144     {
145     }
146 #endif
147 
148     return kStatus_Success;
149 }
150 
FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)151 static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
152                                                          flexio_i2c_master_handle_t *handle,
153                                                          uint32_t statusFlags)
154 {
155 #if I2C_RETRY_TIMES
156     uint32_t waitTimes = I2C_RETRY_TIMES;
157 #endif
158 
159     if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
160     {
161         /* Clear receive nak flag. */
162         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
163 
164         if ((!((handle->state == (uint8_t)kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
165             (!(((handle->state == (uint8_t)kFLEXIO_I2C_ReceiveData) ||
166                 (handle->state == (uint8_t)kFLEXIO_I2C_ReceiveDataBegin)) &&
167                (handle->transfer.dataSize == 1U))))
168         {
169             (void)FLEXIO_I2C_MasterReadByte(base);
170 
171             FLEXIO_I2C_MasterAbortStop(base);
172 
173             /* Delay one clk cycle to ensure the bus is idle. */
174             SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
175 
176             handle->state = (uint8_t)kFLEXIO_I2C_Idle;
177 
178             return kStatus_FLEXIO_I2C_Nak;
179         }
180     }
181 
182     if (((statusFlags & (uint8_t)kFLEXIO_I2C_RxFullFlag) != 0U) && (handle->state != (uint8_t)kFLEXIO_I2C_ReceiveData))
183     {
184         (void)FLEXIO_I2C_MasterReadByte(base);
185     }
186 
187     switch (handle->state)
188     {
189         /* Initial state, i2c start state. */
190         case (uint8_t)kFLEXIO_I2C_Start:
191             /* Send address byte first. */
192             if (handle->needRestart)
193             {
194                 FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
195             }
196             else
197             {
198                 FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
199             }
200             if (handle->transfer.subaddressSize == 0U)
201             {
202                 if (handle->transfer.direction == kFLEXIO_I2C_Write)
203                 {
204                     /* Next state, send data. */
205                     handle->state = (uint8_t)kFLEXIO_I2C_SendData;
206                 }
207                 else
208                 {
209                     /* Next state, receive data begin. */
210                     handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
211                 }
212             }
213             else
214             {
215                 /* Next state, send command byte. */
216                 handle->state = (uint8_t)kFLEXIO_I2C_SendCommand;
217             }
218             break;
219 
220         /* Check address only needed for transfer with subaddress */
221         case (uint8_t)kFLEXIO_I2C_SendCommand:
222             if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
223             {
224                 if (handle->transfer.subaddressSize > 0U)
225                 {
226                     handle->transfer.subaddressSize--;
227                     FLEXIO_I2C_MasterWriteByte(
228                         base, ((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize)));
229 
230                     if (handle->transfer.subaddressSize == 0U)
231                     {
232                         /* Load re-start in advance. */
233                         if (handle->transfer.direction == kFLEXIO_I2C_Read)
234                         {
235 #if I2C_RETRY_TIMES
236                             while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) &
237                                            (1UL << base->shifterIndex[0]))) &&
238                                    (0U != --waitTimes))
239                             {
240                             }
241                             if (0U == waitTimes)
242                             {
243                                 return kStatus_FLEXIO_I2C_Timeout;
244                             }
245 #else
246                             while (0U ==
247                                    (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
248                             {
249                             }
250 #endif
251                             FLEXIO_I2C_MasterRepeatedStart(base);
252                         }
253                     }
254                 }
255                 else
256                 {
257                     if (handle->transfer.direction == kFLEXIO_I2C_Write)
258                     {
259                         /* Send first byte of data. */
260                         if (handle->transfer.dataSize > 0U)
261                         {
262                             /* Next state, send data. */
263                             handle->state = (uint8_t)kFLEXIO_I2C_SendData;
264 
265                             FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
266                             handle->transfer.data++;
267                             handle->transfer.dataSize--;
268                         }
269                         else
270                         {
271                             FLEXIO_I2C_MasterStop(base);
272 
273 #if I2C_RETRY_TIMES
274                             while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
275                                    (0U != --waitTimes))
276                             {
277                             }
278                             if (0U == waitTimes)
279                             {
280                                 return kStatus_FLEXIO_I2C_Timeout;
281                             }
282 #else
283                             while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
284                             {
285                             }
286 #endif
287                             (void)FLEXIO_I2C_MasterReadByte(base);
288 
289                             handle->state = (uint8_t)kFLEXIO_I2C_Idle;
290                         }
291                     }
292                     else
293                     {
294                         (void)FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)(handle->transfer.dataSize + 1U));
295                         FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);
296 
297                         /* Next state, receive data begin. */
298                         handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
299                     }
300                 }
301             }
302             break;
303 
304         /* Send command byte. */
305         case (uint8_t)kFLEXIO_I2C_SendData:
306             if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
307             {
308                 /* Send one byte of data. */
309                 if (handle->transfer.dataSize > 0U)
310                 {
311                     FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
312 
313                     handle->transfer.data++;
314                     handle->transfer.dataSize--;
315                 }
316                 else
317                 {
318                     FLEXIO_I2C_MasterStop(base);
319 
320 #if I2C_RETRY_TIMES
321                     while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
322                            (0U != --waitTimes))
323                     {
324                     }
325                     if (0U == waitTimes)
326                     {
327                         return kStatus_FLEXIO_I2C_Timeout;
328                     }
329 #else
330                     while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
331                     {
332                     }
333 #endif
334                     (void)FLEXIO_I2C_MasterReadByte(base);
335 
336                     handle->state = (uint8_t)kFLEXIO_I2C_Idle;
337                 }
338             }
339             break;
340 
341         case (uint8_t)kFLEXIO_I2C_ReceiveDataBegin:
342             if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
343             {
344                 handle->state = (uint8_t)kFLEXIO_I2C_ReceiveData;
345                 /* Send nak at the last receive byte. */
346                 if (handle->transfer.dataSize == 1U)
347                 {
348                     FLEXIO_I2C_MasterEnableAck(base, false);
349 #if I2C_RETRY_TIMES
350                     while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
351                            (0U != --waitTimes))
352                     {
353                     }
354                     if (0U == waitTimes)
355                     {
356                         return kStatus_FLEXIO_I2C_Timeout;
357                     }
358 #else
359                     while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
360                     {
361                     }
362 #endif
363                     FLEXIO_I2C_MasterStop(base);
364                 }
365                 else
366                 {
367                     FLEXIO_I2C_MasterEnableAck(base, true);
368                 }
369             }
370             else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
371             {
372                 /* Read one byte of data. */
373                 FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
374             }
375             else
376             {
377                 ; /* Avoid MISRA 2012 rule 15.7 */
378             }
379             break;
380 
381         case (uint8_t)kFLEXIO_I2C_ReceiveData:
382             if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
383             {
384                 *handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
385                 handle->transfer.data++;
386                 if (0U != handle->transfer.dataSize--)
387                 {
388                     if (handle->transfer.dataSize == 0U)
389                     {
390                         FLEXIO_I2C_MasterDisableInterrupts(base, (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
391                         handle->state = (uint8_t)kFLEXIO_I2C_Idle;
392                         /* Return nak if ReceiveNakFlag is not set */
393                         if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) == 0U)
394                         {
395                             return kStatus_FLEXIO_I2C_Nak;
396                         }
397                     }
398 
399                     /* Send nak at the last receive byte. */
400                     if (handle->transfer.dataSize == 1U)
401                     {
402                         FLEXIO_I2C_MasterEnableAck(base, false);
403 #if I2C_RETRY_TIMES
404                         while (
405                             (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
406                             (0U != --waitTimes))
407                         {
408                         }
409                         if (0U == waitTimes)
410                         {
411                             return kStatus_FLEXIO_I2C_Timeout;
412                         }
413 #else
414                         while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
415                         {
416                         }
417 #endif
418                         FLEXIO_I2C_MasterStop(base);
419                     }
420                 }
421             }
422             else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
423             {
424                 if (handle->transfer.dataSize > 1U)
425                 {
426                     FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
427                 }
428             }
429             else
430             {
431                 ; /* Avoid MISRA 2012 rule 15.7 */
432             }
433             break;
434 
435         default:
436             /* Add comment to avoid MISRA violation */
437             break;
438     }
439 
440     return kStatus_Success;
441 }
442 
FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,status_t status)443 static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
444                                               flexio_i2c_master_handle_t *handle,
445                                               status_t status)
446 {
447     FLEXIO_I2C_MasterDisableInterrupts(
448         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
449 
450     if (handle->completionCallback != NULL)
451     {
452         handle->completionCallback(base, handle, status, handle->userData);
453     }
454 }
455 
456 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
457 /*!
458  * brief Make sure the bus isn't already pulled down.
459  *
460  * Check the FLEXIO pin status to see whether either of SDA and SCL pin is pulled down.
461  *
462  * param base Pointer to FLEXIO_I2C_Type structure..
463  * retval kStatus_Success
464  * retval kStatus_FLEXIO_I2C_Busy
465  */
FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type * base)466 status_t FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type *base)
467 {
468     uint32_t mask;
469     /* If in certain loops the SDA/SCL is continuously pulled down, then return bus busy status. */
470     /* The loop count is determined by maximum CPU clock frequency */
471     for (uint32_t i = 0U; i < SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 600000U; ++i)
472     {
473         mask = 1UL << base->SDAPinIndex | 1UL << base->SCLPinIndex;
474         if ((FLEXIO_ReadPinInput(base->flexioBase) & mask) == mask)
475         {
476             return kStatus_Success;
477         }
478     }
479     return kStatus_FLEXIO_I2C_Busy;
480 }
481 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
482 
483 /*!
484  * brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
485  * hardware configuration.
486  *
487  * Example
488    code
489    FLEXIO_I2C_Type base = {
490    .flexioBase = FLEXIO,
491    .SDAPinIndex = 0,
492    .SCLPinIndex = 1,
493    .shifterIndex = {0,1},
494    .timerIndex = {0,1}
495    };
496    flexio_i2c_master_config_t config = {
497    .enableInDoze = false,
498    .enableInDebug = true,
499    .enableFastAccess = false,
500    .baudRate_Bps = 100000
501    };
502    FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
503    endcode
504  *
505  * param base Pointer to FLEXIO_I2C_Type structure.
506  * param masterConfig Pointer to flexio_i2c_master_config_t structure.
507  * param srcClock_Hz FlexIO source clock in Hz.
508  * retval kStatus_Success Initialization successful
509  * retval kStatus_InvalidArgument The source clock exceed upper range limitation
510 */
FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type * base,flexio_i2c_master_config_t * masterConfig,uint32_t srcClock_Hz)511 status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
512 {
513     assert((base != NULL) && (masterConfig != NULL));
514 
515     flexio_shifter_config_t shifterConfig;
516     flexio_timer_config_t timerConfig;
517     uint32_t controlVal = 0;
518     uint16_t timerDiv   = 0;
519     status_t result     = kStatus_Success;
520 
521     (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
522     (void)memset(&timerConfig, 0, sizeof(timerConfig));
523 
524 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
525     /* Ungate flexio clock. */
526     CLOCK_EnableClock(s_flexioClocks[FLEXIO_I2C_GetInstance(base)]);
527 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
528 
529     /* Do hardware configuration. */
530     /* 1. Configure the shifter 0 for tx. */
531     shifterConfig.timerSelect   = base->timerIndex[2];
532     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
533     shifterConfig.pinConfig     = kFLEXIO_PinConfigOpenDrainOrBidirection;
534     shifterConfig.pinSelect     = base->SDAPinIndex;
535     shifterConfig.pinPolarity   = kFLEXIO_PinActiveLow;
536     shifterConfig.shifterMode   = kFLEXIO_ShifterModeTransmit;
537     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
538     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitHigh;
539     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitLow;
540 
541     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
542 
543     /* 2. Configure the shifter 1 for rx. */
544     shifterConfig.timerSelect   = base->timerIndex[2];
545     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
546     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutputDisabled;
547     shifterConfig.pinSelect     = base->SDAPinIndex;
548     shifterConfig.pinPolarity   = kFLEXIO_PinActiveHigh;
549     shifterConfig.shifterMode   = kFLEXIO_ShifterModeReceive;
550     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
551     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitLow;
552     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
553 
554     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
555 
556     /*3. Configure the timer 0 and timer 1 for generating bit clock. */
557     /* timer 1 is used to config baudrate */
558     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
559     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
560     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
561     timerConfig.pinConfig       = kFLEXIO_PinConfigOpenDrainOrBidirection;
562     timerConfig.pinSelect       = base->SCLPinIndex;
563     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
564     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
565     timerConfig.timerOutput     = kFLEXIO_TimerOutputZeroNotAffectedByReset;
566     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
567     timerConfig.timerReset      = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput;
568     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnPreTimerDisable;
569     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
570     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
571     timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
572 
573     /* Set TIMCMP = (baud rate divider / 2) - 1. */
574     timerDiv = (uint16_t)(srcClock_Hz / masterConfig->baudRate_Bps) / 2U - 1U;
575     /* Calculate and assign the actual baudrate. */
576     base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
577 
578     timerConfig.timerCompare = timerDiv;
579 
580     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
581 
582     /* timer 0 is used to config total shift clock edges */
583     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
584     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
585     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
586     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
587     timerConfig.pinSelect       = base->SCLPinIndex;
588     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
589     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
590     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
591     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
592     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
593     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
594     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
595     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
596     timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
597 
598     /* Set TIMCMP when confinguring transfer bytes. */
599     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
600 
601     /* 4. Configure the timer 2 for controlling shifters. */
602     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
603     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
604     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
605     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
606     timerConfig.pinSelect       = base->SCLPinIndex;
607     timerConfig.pinPolarity     = kFLEXIO_PinActiveLow;
608     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
609     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
610     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
611     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
612     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnPreTimerDisable;
613     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPrevTimerEnable;
614     timerConfig.timerStop       = kFLEXIO_TimerStopBitEnableOnTimerCompare;
615     timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
616 
617     /* Set TIMCMP[15:0] = (number of bits x 2) - 1. */
618     timerConfig.timerCompare = 8U * 2U - 1U;
619 
620     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[2], &timerConfig);
621 
622     /* Configure FLEXIO I2C Master. */
623     controlVal = base->flexioBase->CTRL;
624     controlVal &=
625         ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
626     controlVal |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
627                    FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
628     if (!masterConfig->enableInDoze)
629     {
630         controlVal |= FLEXIO_CTRL_DOZEN_MASK;
631     }
632 
633     base->flexioBase->CTRL = controlVal;
634     /* Disable internal IRQs. */
635     FLEXIO_I2C_MasterDisableInterrupts(
636         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
637     return result;
638 }
639 
640 /*!
641  * brief De-initializes the FlexIO I2C master peripheral. Calling this API Resets the FlexIO I2C master
642  * shifer and timer config, module can't work unless the FLEXIO_I2C_MasterInit is called.
643  *
644  * param base pointer to FLEXIO_I2C_Type structure.
645  */
FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type * base)646 void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base)
647 {
648     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = 0;
649     base->flexioBase->SHIFTCTL[base->shifterIndex[0]] = 0;
650     base->flexioBase->SHIFTCFG[base->shifterIndex[1]] = 0;
651     base->flexioBase->SHIFTCTL[base->shifterIndex[1]] = 0;
652     base->flexioBase->TIMCFG[base->timerIndex[0]]     = 0;
653     base->flexioBase->TIMCMP[base->timerIndex[0]]     = 0;
654     base->flexioBase->TIMCTL[base->timerIndex[0]]     = 0;
655     base->flexioBase->TIMCFG[base->timerIndex[1]]     = 0;
656     base->flexioBase->TIMCMP[base->timerIndex[1]]     = 0;
657     base->flexioBase->TIMCTL[base->timerIndex[1]]     = 0;
658     base->flexioBase->TIMCFG[base->timerIndex[2]]     = 0;
659     base->flexioBase->TIMCMP[base->timerIndex[2]]     = 0;
660     base->flexioBase->TIMCTL[base->timerIndex[2]]     = 0;
661     /* Clear the shifter flag. */
662     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[0]);
663     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[1]);
664     /* Clear the timer flag. */
665     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[0]);
666     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[1]);
667     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[2]);
668 }
669 
670 /*!
671  * brief Gets the default configuration to configure the FlexIO module. The configuration
672  * can be used directly for calling the FLEXIO_I2C_MasterInit().
673  *
674  * Example:
675    code
676    flexio_i2c_master_config_t config;
677    FLEXIO_I2C_MasterGetDefaultConfig(&config);
678    endcode
679  * param masterConfig Pointer to flexio_i2c_master_config_t structure.
680 */
FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t * masterConfig)681 void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig)
682 {
683     assert(masterConfig != NULL);
684 
685     /* Initializes the configure structure to zero. */
686     (void)memset(masterConfig, 0, sizeof(*masterConfig));
687 
688     masterConfig->enableMaster     = true;
689     masterConfig->enableInDoze     = false;
690     masterConfig->enableInDebug    = true;
691     masterConfig->enableFastAccess = false;
692 
693     /* Default baud rate at 100kbps. */
694     masterConfig->baudRate_Bps = 100000U;
695 }
696 
697 /*!
698  * brief Gets the FlexIO I2C master status flags.
699  *
700  * param base Pointer to FLEXIO_I2C_Type structure
701  * return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
702  */
703 
FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type * base)704 uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base)
705 {
706     uint32_t status = 0;
707 
708     status =
709         ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])) >> base->shifterIndex[0]);
710     status |=
711         (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
712          << 1U);
713     status |=
714         (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
715          << 2U);
716 
717     return status;
718 }
719 
720 /*!
721  * brief Clears the FlexIO I2C master status flags.
722  *
723  * param base Pointer to FLEXIO_I2C_Type structure.
724  * param mask Status flag.
725  *      The parameter can be any combination of the following values:
726  *          arg kFLEXIO_I2C_RxFullFlag
727  *          arg kFLEXIO_I2C_ReceiveNakFlag
728  */
729 
FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type * base,uint32_t mask)730 void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask)
731 {
732     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
733     {
734         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[0]);
735     }
736 
737     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
738     {
739         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
740     }
741 
742     if ((mask & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
743     {
744         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
745     }
746 }
747 
748 /*!
749  * brief Enables the FlexIO i2c master interrupt requests.
750  *
751  * param base Pointer to FLEXIO_I2C_Type structure.
752  * param mask Interrupt source.
753  *     Currently only one interrupt request source:
754  *     arg kFLEXIO_I2C_TransferCompleteInterruptEnable
755  */
FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type * base,uint32_t mask)756 void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
757 {
758     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
759     {
760         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
761     }
762     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
763     {
764         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
765     }
766 }
767 
768 /*!
769  * brief Disables the FlexIO I2C master interrupt requests.
770  *
771  * param base Pointer to FLEXIO_I2C_Type structure.
772  * param mask Interrupt source.
773  */
FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type * base,uint32_t mask)774 void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
775 {
776     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
777     {
778         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
779     }
780     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
781     {
782         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
783     }
784 }
785 
786 /*!
787  * brief Sets the FlexIO I2C master transfer baudrate.
788  *
789  * param base Pointer to FLEXIO_I2C_Type structure
790  * param baudRate_Bps the baud rate value in HZ
791  * param srcClock_Hz source clock in HZ
792  */
FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)793 void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
794 {
795     uint16_t timerDiv       = 0;
796     FLEXIO_Type *flexioBase = base->flexioBase;
797 
798     /* Set TIMCMP = (baud rate divider / 2) - 1.*/
799     timerDiv = (uint16_t)((srcClock_Hz / baudRate_Bps) / 2U - 1U);
800 
801     flexioBase->TIMCMP[base->timerIndex[1]] = timerDiv;
802 
803     /* Calculate and assign the actual baudrate. */
804     base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
805 }
806 
807 /*!
808  * brief Sets the number of bytes to be transferred from a start signal to a stop signal.
809  *
810  * note Call this API before a transfer begins because the timer generates a number of clocks according
811  * to the number of bytes that need to be transferred.
812  *
813  * param base Pointer to FLEXIO_I2C_Type structure.
814  * param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
815  * retval kStatus_Success Successfully configured the count.
816  * retval kStatus_InvalidArgument Input argument is invalid.
817  */
FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type * base,uint16_t count)818 status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint16_t count)
819 {
820     /* Calculate whether the transfer count is larger than the max value compare register can achieve */
821     if (count > ((0xFFFFUL - 1UL) / (16UL + 1UL + 1UL)))
822     {
823         return kStatus_InvalidArgument;
824     }
825 
826     uint32_t timerConfig    = 0U;
827     FLEXIO_Type *flexioBase = base->flexioBase;
828 
829     flexioBase->TIMCMP[base->timerIndex[0]] = (uint32_t)count * 18U + 1U;
830     timerConfig                             = flexioBase->TIMCFG[base->timerIndex[0]];
831     timerConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
832     timerConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
833     flexioBase->TIMCFG[base->timerIndex[0]] = timerConfig;
834 
835     return kStatus_Success;
836 }
837 
838 /*!
839  * brief Sends START + 7-bit address to the bus.
840  *
841  * note This API should be called when the transfer configuration is ready to send a START signal
842  * and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
843  * is put into the data register but the address transfer is not finished on the bus. Ensure that
844  * the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
845  * param base Pointer to FLEXIO_I2C_Type structure.
846  * param address 7-bit address.
847  * param direction transfer direction.
848  *     This parameter is one of the values in flexio_i2c_direction_t:
849  *        arg kFLEXIO_I2C_Write: Transmit
850  *        arg kFLEXIO_I2C_Read:  Receive
851  */
852 
FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type * base,uint8_t address,flexio_i2c_direction_t direction)853 void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction)
854 {
855     uint32_t data;
856 
857     data = ((uint32_t)address) << 1U | ((direction == kFLEXIO_I2C_Read) ? 1U : 0U);
858 
859     FLEXIO_I2C_MasterWriteByte(base, data);
860 }
861 
862 /*!
863  * brief Sends the repeated start signal on the bus.
864  *
865  * param base Pointer to FLEXIO_I2C_Type structure.
866  */
FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type * base)867 void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base)
868 {
869     /* Prepare for RESTART condition, no stop.*/
870     FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
871 }
872 
873 /*!
874  * brief Sends the stop signal on the bus.
875  *
876  * param base Pointer to FLEXIO_I2C_Type structure.
877  */
FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type * base)878 void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base)
879 {
880     /* Prepare normal stop. */
881     (void)FLEXIO_I2C_MasterSetTransferCount(base, 0x0U);
882     FLEXIO_I2C_MasterWriteByte(base, 0x0U);
883 }
884 
885 /*!
886  * brief Sends the stop signal when transfer is still on-going.
887  *
888  * param base Pointer to FLEXIO_I2C_Type structure.
889  */
FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type * base)890 void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base)
891 {
892     uint32_t tmpConfig;
893 
894     /* Prepare abort stop. */
895     /* Disable timer 0. */
896     tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[0]];
897     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
898     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
899     base->flexioBase->TIMCFG[base->timerIndex[0]] = tmpConfig;
900 
901     /* Disable timer 1. */
902     tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
903     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
904     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
905     base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
906 }
907 
908 /*!
909  * brief Configures the sent ACK/NAK for the following byte.
910  *
911  * param base Pointer to FLEXIO_I2C_Type structure.
912  * param enable True to configure send ACK, false configure to send NAK.
913  */
FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type * base,bool enable)914 void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable)
915 {
916     uint32_t tmpConfig = 0;
917 
918     tmpConfig = base->flexioBase->SHIFTCFG[base->shifterIndex[0]];
919     tmpConfig &= ~FLEXIO_SHIFTCFG_SSTOP_MASK;
920     if (enable)
921     {
922         tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitLow);
923     }
924     else
925     {
926         tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitHigh);
927     }
928     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = tmpConfig;
929 }
930 
931 /*!
932  * brief Sends a buffer of data in bytes.
933  *
934  * note This function blocks via polling until all bytes have been sent.
935  *
936  * param base Pointer to FLEXIO_I2C_Type structure.
937  * param txBuff The data bytes to send.
938  * param txSize The number of data bytes to send.
939  * retval kStatus_Success Successfully write data.
940  * retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
941  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
942  */
FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type * base,const uint8_t * txBuff,uint8_t txSize)943 status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize)
944 {
945     assert(txBuff != NULL);
946     assert(txSize != 0U);
947 
948     uint32_t status;
949 #if I2C_RETRY_TIMES
950     uint32_t waitTimes = I2C_RETRY_TIMES;
951 #endif
952 
953     while (0U != txSize--)
954     {
955         FLEXIO_I2C_MasterWriteByte(base, *txBuff++);
956 
957         /* Wait until data transfer complete. */
958 #if I2C_RETRY_TIMES
959         waitTimes = I2C_RETRY_TIMES;
960         while ((0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
961                (0U != --waitTimes))
962         {
963         }
964         if (0U == waitTimes)
965         {
966             return kStatus_FLEXIO_I2C_Timeout;
967         }
968 #else
969         while (0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
970         {
971         }
972 #endif
973 
974         if ((status & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
975         {
976             FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
977             return kStatus_FLEXIO_I2C_Nak;
978         }
979     }
980     return kStatus_Success;
981 }
982 
983 /*!
984  * brief Receives a buffer of bytes.
985  *
986  * note This function blocks via polling until all bytes have been received.
987  *
988  * param base Pointer to FLEXIO_I2C_Type structure.
989  * param rxBuff The buffer to store the received bytes.
990  * param rxSize The number of data bytes to be received.
991  * retval kStatus_Success Successfully read data.
992  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
993  */
FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type * base,uint8_t * rxBuff,uint8_t rxSize)994 status_t FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize)
995 {
996     assert(rxBuff != NULL);
997     assert(rxSize != 0U);
998 
999 #if I2C_RETRY_TIMES
1000     uint32_t waitTimes = I2C_RETRY_TIMES;
1001 #endif
1002 
1003     while (0U != rxSize--)
1004     {
1005         /* Wait until data transfer complete. */
1006 #if I2C_RETRY_TIMES
1007         waitTimes = I2C_RETRY_TIMES;
1008         while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
1009                (0U != --waitTimes))
1010         {
1011         }
1012         if (0U == waitTimes)
1013         {
1014             return kStatus_FLEXIO_I2C_Timeout;
1015         }
1016 #else
1017         while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
1018         {
1019         }
1020 #endif
1021         *rxBuff++ = FLEXIO_I2C_MasterReadByte(base);
1022     }
1023     return kStatus_Success;
1024 }
1025 
1026 /*!
1027  * brief Performs a master polling transfer on the I2C bus.
1028  *
1029  * note The API does not return until the transfer succeeds or fails due
1030  * to receiving NAK.
1031  *
1032  * param base pointer to FLEXIO_I2C_Type structure.
1033  * param xfer pointer to flexio_i2c_master_transfer_t structure.
1034  * return status of status_t.
1035  */
FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type * base,flexio_i2c_master_transfer_t * xfer)1036 status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer)
1037 {
1038     assert(xfer != NULL);
1039 
1040 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
1041     /* Return an error if the bus is already in use not by us.*/
1042     status_t status = FLEXIO_I2C_CheckForBusyBus(base);
1043     if (status != kStatus_Success)
1044     {
1045         return status;
1046     }
1047 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
1048 
1049     flexio_i2c_master_handle_t tmpHandle;
1050     uint32_t statusFlags;
1051     status_t result = kStatus_Success;
1052 #if I2C_RETRY_TIMES
1053     uint32_t waitTimes = I2C_RETRY_TIMES;
1054 #endif
1055 
1056     /* Zero the handle. */
1057     (void)memset(&tmpHandle, 0, sizeof(tmpHandle));
1058 
1059     /* Set up transfer machine. */
1060     result = FLEXIO_I2C_MasterTransferInitStateMachine(base, &tmpHandle, xfer);
1061     if (result != kStatus_Success)
1062     {
1063         return result;
1064     }
1065 
1066     do
1067     {
1068         /* Wait either tx empty or rx full flag is asserted. */
1069 #if I2C_RETRY_TIMES
1070         waitTimes = I2C_RETRY_TIMES;
1071         while ((0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
1072                        ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag))) &&
1073                (0U != --waitTimes))
1074         {
1075         }
1076         if (0U == waitTimes)
1077         {
1078             return kStatus_FLEXIO_I2C_Timeout;
1079         }
1080 #else
1081         while (0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
1082                       ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag)))
1083         {
1084         }
1085 #endif
1086         FLEXIO_ClearTimerStatusFlags(base->flexioBase, ((1UL << base->timerIndex[0]) | (1UL << base->timerIndex[1])));
1087         result = FLEXIO_I2C_MasterTransferRunStateMachine(base, &tmpHandle, statusFlags);
1088 
1089     } while ((tmpHandle.state != (uint8_t)kFLEXIO_I2C_Idle) && (result == kStatus_Success));
1090 
1091     /* Timer disable on timer compare, wait until bit clock TSF set, which means timer disable and stop has been sent.
1092      */
1093     while (0U == (FLEXIO_GetTimerStatusFlags(base->flexioBase) & (1UL << base->timerIndex[1])))
1094     {
1095     }
1096 
1097     return result;
1098 }
1099 
1100 /*!
1101  * brief Initializes the I2C handle which is used in transactional functions.
1102  *
1103  * param base Pointer to FLEXIO_I2C_Type structure.
1104  * param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
1105  * param callback Pointer to user callback function.
1106  * param userData User param passed to the callback function.
1107  * retval kStatus_Success Successfully create the handle.
1108  * retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
1109  */
FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_callback_t callback,void * userData)1110 status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
1111                                                flexio_i2c_master_handle_t *handle,
1112                                                flexio_i2c_master_transfer_callback_t callback,
1113                                                void *userData)
1114 {
1115     assert(handle != NULL);
1116 
1117     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
1118 
1119     /* Zero the handle. */
1120     (void)memset(handle, 0, sizeof(*handle));
1121 
1122     /* Register callback and userData. */
1123     handle->completionCallback = callback;
1124     handle->userData           = userData;
1125 
1126     /* Clear pending NVIC IRQ before enable NVIC IRQ. */
1127     NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
1128     (void)EnableIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
1129 
1130     /* Save the context in global variables to support the double weak mechanism. */
1131     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ);
1132 }
1133 
1134 /*!
1135  * brief Performs a master interrupt non-blocking transfer on the I2C bus.
1136  *
1137  * note The API returns immediately after the transfer initiates.
1138  * Call FLEXIO_I2C_MasterTransferGetCount to poll the transfer status to check whether
1139  * the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
1140  * is finished.
1141  *
1142  * param base Pointer to FLEXIO_I2C_Type structure
1143  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
1144  * param xfer pointer to flexio_i2c_master_transfer_t structure
1145  * retval kStatus_Success Successfully start a transfer.
1146  * retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
1147  */
FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_t * xfer)1148 status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
1149                                               flexio_i2c_master_handle_t *handle,
1150                                               flexio_i2c_master_transfer_t *xfer)
1151 {
1152     assert(handle != NULL);
1153     assert(xfer != NULL);
1154 
1155     status_t result = kStatus_Success;
1156 
1157 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
1158     /* Return an error if the bus is already in use not by us.*/
1159     result = FLEXIO_I2C_CheckForBusyBus(base);
1160     if (result != kStatus_Success)
1161     {
1162         return result;
1163     }
1164 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
1165 
1166     if (handle->state != (uint8_t)kFLEXIO_I2C_Idle)
1167     {
1168         return kStatus_FLEXIO_I2C_Busy;
1169     }
1170     else
1171     {
1172         /* Set up transfer machine. */
1173         result = FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer);
1174         if (result != kStatus_Success)
1175         {
1176             return result;
1177         }
1178 
1179         /* Enable both tx empty and rxfull interrupt. */
1180         FLEXIO_I2C_MasterEnableInterrupts(
1181             base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
1182 
1183         return kStatus_Success;
1184     }
1185 }
1186 
1187 /*!
1188  * brief Aborts an interrupt non-blocking transfer early.
1189  *
1190  * note This API can be called at any time when an interrupt non-blocking transfer initiates
1191  * to abort the transfer early.
1192  *
1193  * param base Pointer to FLEXIO_I2C_Type structure
1194  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
1195  */
FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle)1196 void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
1197 {
1198     assert(handle != NULL);
1199 
1200     /* Disable interrupts. */
1201     FLEXIO_I2C_MasterDisableInterrupts(
1202         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
1203 
1204     /* Reset to idle state. */
1205     handle->state = (uint8_t)kFLEXIO_I2C_Idle;
1206 }
1207 
1208 /*!
1209  * brief Gets the master transfer status during a interrupt non-blocking transfer.
1210  *
1211  * param base Pointer to FLEXIO_I2C_Type structure.
1212  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
1213  * param count Number of bytes transferred so far by the non-blocking transaction.
1214  * retval kStatus_InvalidArgument count is Invalid.
1215  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1216  * retval kStatus_Success Successfully return the count.
1217  */
FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,size_t * count)1218 status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count)
1219 {
1220     if (NULL == count)
1221     {
1222         return kStatus_InvalidArgument;
1223     }
1224 
1225     /* Catch when there is not an active transfer. */
1226     if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
1227     {
1228         *count = 0;
1229         return kStatus_NoTransferInProgress;
1230     }
1231 
1232     *count = handle->transferSize - handle->transfer.dataSize;
1233 
1234     return kStatus_Success;
1235 }
1236 
1237 /*!
1238  * brief Master interrupt handler.
1239  *
1240  * param i2cType Pointer to FLEXIO_I2C_Type structure
1241  * param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
1242  */
FLEXIO_I2C_MasterTransferHandleIRQ(void * i2cType,void * i2cHandle)1243 void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle)
1244 {
1245     FLEXIO_I2C_Type *base              = (FLEXIO_I2C_Type *)i2cType;
1246     flexio_i2c_master_handle_t *handle = (flexio_i2c_master_handle_t *)i2cHandle;
1247     uint32_t statusFlags;
1248     status_t result;
1249 
1250     statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base);
1251 
1252     result = FLEXIO_I2C_MasterTransferRunStateMachine(base, handle, statusFlags);
1253 
1254     if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
1255     {
1256         FLEXIO_I2C_MasterTransferComplete(base, handle, result);
1257     }
1258 }
1259