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