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