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