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