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_lpi2c.h"
10 #include <stdlib.h>
11 #include <string.h>
12
13 /*
14 * $Coverage Justification Reference$
15 *
16 * $Justification fsl_lpi2c_c_ref_1$
17 * The default branch cannot be executed in any circumstances, it is only added to avoid MISRA violation.
18 *
19 * $Justification fsl_lpi2c_c_ref_2$
20 * Two instances failed to simulate #kStatus_LPI2C_Busy.
21 *
22 * $Justification fsl_lpi2c_c_ref_3$
23 * When the transmission is completed (remaining == 0), the SDF and RSF will be set, and the flags are get before
24 * that(get before set), it will be over when the next cycle occurs, the first condition cannot be verified, and the
25 * remaining will not be verified.(will improve)
26 *
27 */
28
29 /*******************************************************************************
30 * Definitions
31 ******************************************************************************/
32
33 /* Component ID definition, used by tools. */
34 #ifndef FSL_COMPONENT_ID
35 #define FSL_COMPONENT_ID "platform.drivers.lpi2c"
36 #endif
37
38 #if defined(LPI2C_RSTS)
39 #define LPI2C_RESETS_ARRAY LPI2C_RSTS
40 #endif
41
42 /*! @brief LPI2C master fifo commands. */
43 enum
44 {
45 kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
46 kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
47 kStopCmd = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
48 kStartCmd = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
49 };
50
51 /*!
52 * @brief Default watermark values.
53 *
54 * The default watermarks are set to zero.
55 */
56 enum
57 {
58 kDefaultTxWatermark = 0,
59 kDefaultRxWatermark = 0,
60 };
61
62 /*! @brief States for the state machine used by transactional APIs. */
63 enum
64 {
65 kIdleState = 0,
66 kSendCommandState,
67 kIssueReadCommandState,
68 kTransferDataState,
69 kStopState,
70 kWaitForCompletionState,
71 };
72
73 /*!
74 * @brief Structure definition for variables that passed as parameters in LPI2C_RunTransferStateMachine.
75 * The structure is private.
76 */
77 typedef struct _lpi2c_state_machine_param
78 {
79 bool state_complete; /*!< status of complete */
80 size_t rxCount; /*!< rx count */
81 size_t txCount; /*!< tx count */
82 uint32_t status; /*!< machine status */
83 } lpi2c_state_machine_param_t;
84
85 /*! @brief Typedef for slave interrupt handler. */
86 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
87
88 /*******************************************************************************
89 * Prototypes
90 ******************************************************************************/
91 static uint32_t LPI2C_GetCyclesForWidth(
92 uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler);
93
94 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
95
96 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
97
98 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
99
100 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
101
102 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
103
104 /*!
105 * @brief introduce function LPI2C_TransferStateMachineSendCommandState.
106 * This function was deal with Send Command State.
107 *
108 * @param base The I2C peripheral base address.
109 * @param handle Master nonblocking driver handle.
110 * @param variable_set Pass the address of the parent function variable.
111 */
112 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
113 lpi2c_master_handle_t *handle,
114 lpi2c_state_machine_param_t *stateParams);
115
116 /*!
117 * @brief introduce function LPI2C_TransferStateMachineIssueReadCommandState.
118 * This function was deal with Issue Read Command State.
119 *
120 * @param base The I2C peripheral base address.
121 * @param handle Master nonblocking driver handle.
122 * @param stateParams Pass the address of the parent function variable.
123 */
124 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
125 lpi2c_master_handle_t *handle,
126 lpi2c_state_machine_param_t *stateParams);
127
128 /*!
129 * @brief introduce function LPI2C_TransferStateMachineTransferDataState.
130 * This function was deal with init Transfer Data State.
131 *
132 * @param base The I2C peripheral base address.
133 * @param handle Master nonblocking driver handle.
134 * @param stateParams Pass the address of the parent function variable.
135 */
136 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
137 lpi2c_master_handle_t *handle,
138 lpi2c_state_machine_param_t *stateParams);
139
140 /*!
141 * @brief introduce function LPI2C_TransferStateMachineStopState.
142 * This function was deal with Stop State.
143 *
144 * @param base The I2C peripheral base address.
145 * @param handle Master nonblocking driver handle.
146 * @param stateParams Pass the address of the parent function variable.
147 * @param[out] isDone Set to true if the transfer has completed.
148 */
149 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
150 lpi2c_master_handle_t *handle,
151 lpi2c_state_machine_param_t *stateParams,
152 bool *isDone);
153
154 /*!
155 * @brief introduce function LPI2C_TransferStateMachineWaitState.
156 * This function was deal with Wait For Completion State.
157 *
158 * @param base The I2C peripheral base address.
159 * @param handle Master nonblocking driver handle.
160 * @param stateParams Pass the address of the parent function variable.
161 * @param[out] isDone Set to true if the transfer has completed.
162 */
163 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
164 lpi2c_master_handle_t *handle,
165 lpi2c_state_machine_param_t *stateParams,
166 bool *isDone);
167
168 /*******************************************************************************
169 * Variables
170 ******************************************************************************/
171
172 /*! @brief Array to map LPI2C instance number to base pointer. */
173 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
174
175 /*! @brief Array to map LPI2C instance number to IRQ number, used internally for LPI2C master interrupt and EDMA
176 transactional APIs. */
177 IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
178
179 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
180 /*! @brief Array to map LPI2C instance number to clock gate enum. */
181 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
182
183 #if defined(LPI2C_PERIPH_CLOCKS)
184 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
185 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
186 #endif
187
188 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
189
190 /*! @brief Pointer to master IRQ handler for each instance, used internally for LPI2C master interrupt and EDMA
191 transactional APIs. */
192 lpi2c_master_isr_t s_lpi2cMasterIsr;
193
194 /*! @brief Pointers to master handles for each instance, used internally for LPI2C master interrupt and EDMA
195 transactional APIs. */
196 void *s_lpi2cMasterHandle[ARRAY_SIZE(kLpi2cBases)];
197
198 /*! @brief Pointer to slave IRQ handler for each instance. */
199 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
200
201 /*! @brief Pointers to slave handles for each instance. */
202 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[ARRAY_SIZE(kLpi2cBases)];
203
204 #if defined(LPI2C_RESETS_ARRAY)
205 /* Reset array */
206 static const reset_ip_name_t s_lpi2cResets[] = LPI2C_RESETS_ARRAY;
207 #endif
208
209 /*******************************************************************************
210 * Code
211 ******************************************************************************/
212
213 /*!
214 * brief Returns an instance number given a base address.
215 *
216 * If an invalid base address is passed, debug builds will assert. Release builds will just return
217 * instance number 0.
218 *
219 * param base The LPI2C peripheral base address.
220 * return LPI2C instance number starting from 0.
221 */
LPI2C_GetInstance(LPI2C_Type * base)222 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
223 {
224 uint32_t instance;
225 for (instance = 0U; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
226 {
227 if (kLpi2cBases[instance] == base)
228 {
229 break;
230 }
231 }
232
233 assert(instance < ARRAY_SIZE(kLpi2cBases));
234 return instance;
235 }
236
237 /*!
238 * @brief Computes a cycle count for a given time in nanoseconds.
239 * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
240 * @param width_ns Desired with in nanoseconds.
241 * @param minCycles Minimum cycle count.
242 * @param maxCycles Maximum cycle count.
243 * @param prescaler LPI2C prescaler setting. If the cycle period is not affected by the prescaler value, set it to 0.
244 */
LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,uint32_t width_ns,uint32_t minCycles,uint32_t maxCycles,uint32_t prescaler)245 static uint32_t LPI2C_GetCyclesForWidth(
246 uint32_t sourceClock_Hz, uint32_t width_ns, uint32_t minCycles, uint32_t maxCycles, uint32_t prescaler)
247 {
248 assert(sourceClock_Hz > 0U);
249
250 uint32_t divider = 1U;
251
252 while (prescaler != 0U)
253 {
254 divider *= 2U;
255 prescaler--;
256 }
257
258 uint32_t busCycle_ns = 1000000U / (sourceClock_Hz / divider / 1000U);
259 /* Calculate the cycle count, round up the calculated value. */
260 uint32_t cycles = (width_ns * 10U / busCycle_ns + 5U) / 10U;
261
262 /* If the calculated value is smaller than the minimum value, use the minimum value */
263 if (cycles < minCycles)
264 {
265 cycles = minCycles;
266 }
267 /* If the calculated value is larger than the maximum value, use the maxmum value */
268 if (cycles > maxCycles)
269 {
270 cycles = maxCycles;
271 }
272
273 return cycles;
274 }
275
276 /*!
277 * brief Convert provided flags to status code, and clear any errors if present.
278 * param base The LPI2C peripheral base address.
279 * param status Current status flags value that will be checked.
280 * retval #kStatus_Success
281 * retval #kStatus_LPI2C_PinLowTimeout
282 * retval #kStatus_LPI2C_ArbitrationLost
283 * retval #kStatus_LPI2C_Nak
284 * retval #kStatus_LPI2C_FifoError
285 */
LPI2C_MasterCheckAndClearError(LPI2C_Type * base,uint32_t status)286 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
287 {
288 status_t result = kStatus_Success;
289
290 /* Check for error. These errors cause a stop to automatically be sent. We must */
291 /* clear the errors before a new transfer can start. */
292 status &= (uint32_t)kLPI2C_MasterErrorFlags;
293 if (0U != status)
294 {
295 /* Select the correct error code. Ordered by severity, with bus issues first. */
296 if (0U != (status & (uint32_t)kLPI2C_MasterPinLowTimeoutFlag))
297 {
298 result = kStatus_LPI2C_PinLowTimeout;
299 }
300 else if (0U != (status & (uint32_t)kLPI2C_MasterArbitrationLostFlag))
301 {
302 result = kStatus_LPI2C_ArbitrationLost;
303 }
304 else if (0U != (status & (uint32_t)kLPI2C_MasterNackDetectFlag))
305 {
306 result = kStatus_LPI2C_Nak;
307 }
308 /*
309 * $Branch Coverage Justification$
310 * Before that, the state was stripped of other attributes, and it only contained the four brother flags.(will
311 * improve)
312 */
313 else if (0U != (status & (uint32_t)kLPI2C_MasterFifoErrFlag))
314 {
315 result = kStatus_LPI2C_FifoError;
316 }
317 else
318 {
319 ; /* Intentional empty */
320 }
321
322 /* Clear the flags. */
323 LPI2C_MasterClearStatusFlags(base, status);
324
325 if (((base->MCFGR1 & LPI2C_MCFGR1_IGNACK_MASK) != 0x00U) && (result == kStatus_LPI2C_Nak))
326 {
327 /* ERR051119: If IGNACK was set and nak detect , we will ignore the Nak status */
328 result = kStatus_Success;
329 }
330 else
331 {
332 /* Reset fifos. These flags clear automatically.*/
333 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
334 }
335 }
336 else
337 {
338 ; /* Intentional empty */
339 }
340
341 return result;
342 }
343
344 /*!
345 * @brief Wait until there is room in the tx fifo.
346 * @param base The LPI2C peripheral base address.
347 * @retval #kStatus_Success
348 * @retval #kStatus_LPI2C_PinLowTimeout
349 * @retval #kStatus_LPI2C_ArbitrationLost
350 * @retval #kStatus_LPI2C_Nak
351 * @retval #kStatus_LPI2C_FifoError
352 */
LPI2C_MasterWaitForTxReady(LPI2C_Type * base)353 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
354 {
355 status_t result = kStatus_Success;
356 uint32_t status;
357 size_t txCount;
358 size_t txFifoSize = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
359
360 #if I2C_RETRY_TIMES != 0U
361 uint32_t waitTimes = I2C_RETRY_TIMES;
362 #endif
363 do
364 {
365 /* Get the number of words in the tx fifo and compute empty slots. */
366 LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
367 txCount = txFifoSize - txCount;
368
369 /* Check for error flags. */
370 status = LPI2C_MasterGetStatusFlags(base);
371 result = LPI2C_MasterCheckAndClearError(base, status);
372 if (kStatus_Success != result)
373 {
374 break;
375 }
376 #if I2C_RETRY_TIMES != 0U
377 waitTimes--;
378 } while ((0U == txCount) && (0U != waitTimes));
379
380 if (0U == waitTimes)
381 {
382 result = kStatus_LPI2C_Timeout;
383 }
384 #else
385 } while (0U == txCount);
386 #endif
387
388 return result;
389 }
390
391 /*!
392 * brief Make sure the bus isn't already busy.
393 *
394 * A busy bus is allowed if we are the one driving it.
395 *
396 * param base The LPI2C peripheral base address.
397 * retval #kStatus_Success
398 * retval #kStatus_LPI2C_Busy
399 */
400 /* Not static so it can be used from fsl_lpi2c_edma.c. */
LPI2C_CheckForBusyBus(LPI2C_Type * base)401 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
402 {
403 status_t ret = kStatus_Success;
404
405 uint32_t status = LPI2C_MasterGetStatusFlags(base);
406 /*
407 * $Branch Coverage Justification$
408 * $ref fsl_lpi2c_c_ref_2$
409 */
410 if ((0U != (status & (uint32_t)kLPI2C_MasterBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_MasterBusyFlag)))
411 {
412 ret = kStatus_LPI2C_Busy;
413 }
414
415 return ret;
416 }
417
418 /*!
419 * brief Provides a default configuration for the LPI2C master peripheral.
420 *
421 * This function provides the following default configuration for the LPI2C master peripheral:
422 * code
423 * masterConfig->enableMaster = true;
424 * masterConfig->debugEnable = false;
425 * masterConfig->ignoreAck = false;
426 * masterConfig->pinConfig = kLPI2C_2PinOpenDrain;
427 * masterConfig->baudRate_Hz = 100000U;
428 * masterConfig->busIdleTimeout_ns = 0U;
429 * masterConfig->pinLowTimeout_ns = 0U;
430 * masterConfig->sdaGlitchFilterWidth_ns = 0U;
431 * masterConfig->sclGlitchFilterWidth_ns = 0U;
432 * masterConfig->hostRequest.enable = false;
433 * masterConfig->hostRequest.source = kLPI2C_HostRequestExternalPin;
434 * masterConfig->hostRequest.polarity = kLPI2C_HostRequestPinActiveHigh;
435 * endcode
436 *
437 * After calling this function, you can override any settings in order to customize the configuration,
438 * prior to initializing the master driver with LPI2C_MasterInit().
439 *
440 * param[out] masterConfig User provided configuration structure for default values. Refer to #lpi2c_master_config_t.
441 */
LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t * masterConfig)442 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
443 {
444 /* Initializes the configure structure to zero. */
445 (void)memset(masterConfig, 0, sizeof(*masterConfig));
446
447 masterConfig->enableMaster = true;
448 masterConfig->debugEnable = false;
449 masterConfig->enableDoze = true;
450 masterConfig->ignoreAck = false;
451 masterConfig->pinConfig = kLPI2C_2PinOpenDrain;
452 masterConfig->baudRate_Hz = 100000U;
453 masterConfig->busIdleTimeout_ns = 0U; /* Set to 0 to disable the function */
454 masterConfig->pinLowTimeout_ns = 0U; /* Set to 0 to disable the function */
455 masterConfig->sdaGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
456 masterConfig->sclGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
457 masterConfig->hostRequest.enable = false;
458 masterConfig->hostRequest.source = kLPI2C_HostRequestExternalPin;
459 masterConfig->hostRequest.polarity = kLPI2C_HostRequestPinActiveHigh;
460 }
461
462 /*!
463 * brief Initializes the LPI2C master peripheral.
464 *
465 * This function enables the peripheral clock and initializes the LPI2C master peripheral as described by the user
466 * provided configuration. A software reset is performed prior to configuration.
467 *
468 * param base The LPI2C peripheral base address.
469 * param masterConfig User provided peripheral configuration. Use LPI2C_MasterGetDefaultConfig() to get a set of
470 * defaults
471 * that you can override.
472 * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the baud rate divisors,
473 * filter widths, and timeout periods.
474 */
LPI2C_MasterInit(LPI2C_Type * base,const lpi2c_master_config_t * masterConfig,uint32_t sourceClock_Hz)475 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
476 {
477 uint32_t prescaler;
478 uint32_t cycles;
479 uint32_t cfgr2;
480 uint32_t value;
481
482 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
483
484 uint32_t instance = LPI2C_GetInstance(base);
485
486 /* Ungate the clock. */
487 (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
488 #if defined(LPI2C_PERIPH_CLOCKS)
489 /* Ungate the functional clock in initialize function. */
490 CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
491 #endif
492
493 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
494
495 #if defined(LPI2C_RESETS_ARRAY)
496 RESET_ReleasePeripheralReset(s_lpi2cResets[LPI2C_GetInstance(base)]);
497 #endif
498
499 /* Reset peripheral before configuring it. */
500 LPI2C_MasterReset(base);
501
502 /* Doze bit: 0 is enable, 1 is disable */
503 base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
504
505 /* host request */
506 value = base->MCFGR0;
507 value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
508 value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
509 LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
510 LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
511 base->MCFGR0 = value;
512
513 /* pin config and ignore ack */
514 value = base->MCFGR1;
515 value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
516 value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
517 value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
518 base->MCFGR1 = value;
519
520 LPI2C_MasterSetWatermarks(base, (size_t)kDefaultTxWatermark, (size_t)kDefaultRxWatermark);
521
522 /* Configure glitch filters. */
523 cfgr2 = base->MCFGR2;
524 if (0U != (masterConfig->sdaGlitchFilterWidth_ns))
525 {
526 /* Calculate SDA filter width. The width is equal to FILTSDA cycles of functional clock.
527 And set FILTSDA to 0 disables the fileter, so the min value is 1. */
528 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns, 1U,
529 (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 0U);
530 cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
531 cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
532 }
533 if (0U != masterConfig->sclGlitchFilterWidth_ns)
534 {
535 /* Calculate SDL filter width. The width is equal to FILTSCL cycles of functional clock.
536 And set FILTSCL to 0 disables the fileter, so the min value is 1. */
537 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns, 1U,
538 (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 0U);
539 cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
540 cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
541 }
542 base->MCFGR2 = cfgr2;
543
544 /* Configure baudrate after the SDA/SCL glitch filter setting,
545 since the baudrate calculation needs them as parameter. */
546 LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
547
548 /* Configure bus idle and pin low timeouts after baudrate setting,
549 since the timeout calculation needs prescaler as parameter. */
550 prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
551
552 if (0U != (masterConfig->busIdleTimeout_ns))
553 {
554 /* Calculate bus idle timeout value. The value is equal to BUSIDLE cycles of functional clock divided by
555 prescaler. And set BUSIDLE to 0 disables the fileter, so the min value is 1. */
556 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns, 1U,
557 (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
558 base->MCFGR2 = (base->MCFGR2 & (~LPI2C_MCFGR2_BUSIDLE_MASK)) | LPI2C_MCFGR2_BUSIDLE(cycles);
559 }
560 if (0U != masterConfig->pinLowTimeout_ns)
561 {
562 /* Calculate bus pin low timeout value. The value is equal to PINLOW cycles of functional clock divided by
563 prescaler. And set PINLOW to 0 disables the fileter, so the min value is 1. */
564 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256U, 1U,
565 (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
566 base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
567 }
568
569 LPI2C_MasterEnable(base, masterConfig->enableMaster);
570 }
571
572 /*!
573 * brief Deinitializes the LPI2C master peripheral.
574 *
575 * This function disables the LPI2C master peripheral and gates the clock. It also performs a software
576 * reset to restore the peripheral to reset conditions.
577 *
578 * param base The LPI2C peripheral base address.
579 */
LPI2C_MasterDeinit(LPI2C_Type * base)580 void LPI2C_MasterDeinit(LPI2C_Type *base)
581 {
582 /* Restore to reset state. */
583 LPI2C_MasterReset(base);
584
585 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
586
587 uint32_t instance = LPI2C_GetInstance(base);
588
589 /* Gate clock. */
590 (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
591 #if defined(LPI2C_PERIPH_CLOCKS)
592 /* Gate the functional clock. */
593 CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
594 #endif
595
596 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
597 }
598
599 /*!
600 * brief Configures LPI2C master data match feature.
601 *
602 * param base The LPI2C peripheral base address.
603 * param matchConfig Settings for the data match feature.
604 */
LPI2C_MasterConfigureDataMatch(LPI2C_Type * base,const lpi2c_data_match_config_t * matchConfig)605 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *matchConfig)
606 {
607 /* Disable master mode. */
608 bool wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
609 LPI2C_MasterEnable(base, false);
610
611 base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(matchConfig->matchMode);
612 base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(matchConfig->rxDataMatchOnly);
613 base->MDMR = LPI2C_MDMR_MATCH0(matchConfig->match0) | LPI2C_MDMR_MATCH1(matchConfig->match1);
614
615 /* Restore master mode. */
616 if (wasEnabled)
617 {
618 LPI2C_MasterEnable(base, true);
619 }
620 }
621
622 /*!
623 * brief Sets the I2C bus frequency for master transactions.
624 *
625 * The LPI2C master is automatically disabled and re-enabled as necessary to configure the baud
626 * rate. Do not call this function during a transfer, or the transfer is aborted.
627 *
628 * note Please note that the second parameter is the clock frequency of LPI2C module, the third
629 * parameter means user configured bus baudrate, this implementation is different from other I2C drivers
630 * which use baudrate configuration as second parameter and source clock frequency as third parameter.
631 *
632 * param base The LPI2C peripheral base address.
633 * param sourceClock_Hz LPI2C functional clock frequency in Hertz.
634 * param baudRate_Hz Requested bus frequency in Hertz.
635 */
LPI2C_MasterSetBaudRate(LPI2C_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Hz)636 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
637 {
638 bool wasEnabled;
639 uint8_t filtScl = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSCL_MASK) >> LPI2C_MCFGR2_FILTSCL_SHIFT);
640
641 uint8_t divider = 1U;
642 uint8_t bestDivider = 1U;
643 uint8_t prescale = 0U;
644 uint8_t bestPre = 0U;
645
646 uint8_t clkCycle;
647 uint8_t bestclkCycle = 0U;
648
649 uint32_t absError = 0U;
650 uint32_t bestError = 0xffffffffu;
651 uint32_t computedRate;
652
653 uint32_t tmpReg = 0U;
654
655 /* Disable master mode. */
656 wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
657 LPI2C_MasterEnable(base, false);
658
659 /* Baud rate = (sourceClock_Hz / 2 ^ prescale) / (CLKLO + 1 + CLKHI + 1 + SCL_LATENCY)
660 * SCL_LATENCY = ROUNDDOWN((2 + FILTSCL) / (2 ^ prescale))
661 */
662 for (prescale = 0U; prescale <= 7U; prescale++)
663 {
664 /* Calculate the clkCycle, clkCycle = CLKLO + CLKHI, divider = 2 ^ prescale */
665 clkCycle = (uint8_t)((10U * sourceClock_Hz / divider / baudRate_Hz + 5U) / 10U - (2U + filtScl) / divider - 2U);
666 /* According to register description, The max value for CLKLO and CLKHI is 63.
667 however to meet the I2C specification of tBUF, CLKHI should be less than
668 clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U. Refer to the comment of the tmpHigh's
669 calculation for details. So we have:
670 CLKHI < clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U,
671 clkCycle = CLKHI + CLKLO and
672 sourceClock_Hz / baudRate_Hz / divider = clkCycle + 2 + ROUNDDOWN((2 + FILTSCL) / divider),
673 we can come up with: CLKHI < 0.92 x CLKLO - ROUNDDOWN(2 + FILTSCL) / divider
674 so the max boundary of CLKHI should be 0.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider,
675 and the max boundary of clkCycle is 1.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider. */
676 if (clkCycle > (120U - (2U + filtScl) / divider))
677 {
678 divider *= 2U;
679 continue;
680 }
681 /* Calculate the computed baudrate and compare it with the desired baudrate */
682 computedRate = (sourceClock_Hz / (uint32_t)divider) /
683 ((uint32_t)clkCycle + 2U + (2U + (uint32_t)filtScl) / (uint32_t)divider);
684 absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
685 if (absError < bestError)
686 {
687 bestPre = prescale;
688 bestDivider = divider;
689 bestclkCycle = clkCycle;
690 bestError = absError;
691
692 /* If the error is 0, then we can stop searching because we won't find a better match. */
693 if (absError == 0U)
694 {
695 break;
696 }
697 }
698 divider *= 2U;
699 }
700
701 /* SCL low time tLO should be larger than or equal to SCL high time tHI:
702 tLO = ((CLKLO + 1) x (2 ^ PRESCALE)) >= tHI = ((CLKHI + 1 + SCL_LATENCY) x (2 ^ PRESCALE)),
703 which is CLKLO >= CLKHI + (2U + filtScl) / bestDivider.
704 Also since bestclkCycle = CLKLO + CLKHI, bestDivider = 2 ^ PRESCALE
705 which makes CLKHI <= (bestclkCycle - (2U + filtScl) / bestDivider) / 2U.
706
707 The max tBUF should be at least 0.52 times of the SCL clock cycle:
708 tBUF = ((CLKLO + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.52 / baudRate_Hz),
709 plus bestDivider = 2 ^ PRESCALE, bestclkCycle = CLKLO + CLKHI we can come up with
710 CLKHI <= (bestclkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / bestDivider + 1U).
711 In this case to get a safe CLKHI calculation, we can assume:
712 */
713 uint8_t tmpHigh = (bestclkCycle - (2U + filtScl) / bestDivider) / 2U;
714 while (tmpHigh > (bestclkCycle - 52U * sourceClock_Hz / baudRate_Hz / bestDivider / 100U + 1U))
715 {
716 tmpHigh = tmpHigh - 1U;
717 }
718
719 /* Calculate DATAVD and SETHOLD.
720 To meet the timing requirement of I2C spec for standard mode, fast mode and fast mode plus: */
721 /* The min tHD:STA/tSU:STA/tSU:STO should be at least 0.4 times of the SCL clock cycle, use 0.5 to be safe:
722 tHD:STA = ((SETHOLD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.5 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
723 uint8_t tmpHold = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 2U) - 1U;
724
725 /* The max tVD:DAT/tVD:ACK/tHD:DAT should be at most 0.345 times of the SCL clock cycle, use 0.25 to be safe:
726 tVD:DAT = ((DATAVD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) < (0.25 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
727 uint8_t tmpDataVd = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 4U) - 1U;
728
729 /* The min tSU:DAT should be at least 0.05 times of the SCL clock cycle:
730 tSU:DAT = ((2 + FILTSDA + 2 ^ PRESCALE) / sourceClock_Hz) >= (0.05 / baud),
731 plus bestDivider = 2 ^ PRESCALE, we can come up with:
732 FILTSDA >= (0.05 x sourceClock_Hz / baudRate_Hz - bestDivider - 2) */
733 if ((sourceClock_Hz / baudRate_Hz / 20U) > (bestDivider + 2U))
734 {
735 /* Read out the FILTSDA configuration, if it is smaller than expected, change the setting. */
736 uint8_t filtSda = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSDA_MASK) >> LPI2C_MCFGR2_FILTSDA_SHIFT);
737 if (filtSda < (sourceClock_Hz / baudRate_Hz / 20U - bestDivider - 2U))
738 {
739 filtSda = (uint8_t)(sourceClock_Hz / baudRate_Hz / 20U) - bestDivider - 2U;
740 }
741 base->MCFGR2 = (base->MCFGR2 & ~LPI2C_MCFGR2_FILTSDA_MASK) | LPI2C_MCFGR2_FILTSDA(filtSda);
742 }
743
744 /* Set CLKHI, CLKLO, SETHOLD, DATAVD value. */
745 tmpReg = LPI2C_MCCR0_CLKHI((uint32_t)tmpHigh) |
746 LPI2C_MCCR0_CLKLO((uint32_t)((uint32_t)bestclkCycle - (uint32_t)tmpHigh)) |
747 LPI2C_MCCR0_SETHOLD((uint32_t)tmpHold) | LPI2C_MCCR0_DATAVD((uint32_t)tmpDataVd);
748 base->MCCR0 = tmpReg;
749
750 /* Set PRESCALE value. */
751 base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
752
753 /* Restore master mode. */
754 if (wasEnabled)
755 {
756 LPI2C_MasterEnable(base, true);
757 }
758 }
759
760 /*!
761 * brief Sends a START signal and slave address on the I2C bus.
762 *
763 * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
764 * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
765 * 7-bit address specified in the a address parameter. Note that this function does not actually wait
766 * until the START and address are successfully sent on the bus before returning.
767 *
768 * param base The LPI2C peripheral base address.
769 * param address 7-bit slave device address, in bits [6:0].
770 * param dir Master transfer direction, either #kLPI2C_Read or #kLPI2C_Write. This parameter is used to set
771 * the R/w bit (bit 0) in the transmitted slave address.
772 * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
773 * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
774 */
LPI2C_MasterStart(LPI2C_Type * base,uint8_t address,lpi2c_direction_t dir)775 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
776 {
777 /* Return an error if the bus is already in use not by us. */
778 status_t result = LPI2C_CheckForBusyBus(base);
779 /*
780 * $Branch Coverage Justification$
781 * $ref fsl_lpi2c_c_ref_2$
782 */
783 if (kStatus_Success == result)
784 {
785 /* Clear all flags. */
786 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
787
788 /* Turn off auto-stop option. */
789 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
790
791 /* Wait until there is room in the fifo. */
792 result = LPI2C_MasterWaitForTxReady(base);
793 if (kStatus_Success == result)
794 {
795 /* Issue start command. */
796 base->MTDR = (uint32_t)kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
797 }
798 }
799
800 return result;
801 }
802
803 /*!
804 * brief Sends a STOP signal on the I2C bus.
805 *
806 * This function does not return until the STOP signal is seen on the bus, or an error occurs.
807 *
808 * param base The LPI2C peripheral base address.
809 * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
810 * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
811 * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
812 * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
813 * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
814 * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
815 */
LPI2C_MasterStop(LPI2C_Type * base)816 status_t LPI2C_MasterStop(LPI2C_Type *base)
817 {
818 /* Wait until there is room in the fifo. */
819 status_t result = LPI2C_MasterWaitForTxReady(base);
820 if (kStatus_Success == result)
821 {
822 /* Send the STOP signal */
823 base->MTDR = (uint32_t)kStopCmd;
824
825 /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
826 /* Also check for errors while waiting. */
827 #if I2C_RETRY_TIMES != 0U
828 uint32_t waitTimes = I2C_RETRY_TIMES;
829 #endif
830
831 #if I2C_RETRY_TIMES != 0U
832 while ((result == kStatus_Success) && (0U != waitTimes))
833 {
834 waitTimes--;
835 #else
836 while (result == kStatus_Success)
837 {
838 #endif
839 uint32_t status = LPI2C_MasterGetStatusFlags(base);
840
841 /* Check for error flags. */
842 result = LPI2C_MasterCheckAndClearError(base, status);
843
844 /* Check if the stop was sent successfully. */
845 if ((0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag)) &&
846 (0U != (status & (uint32_t)kLPI2C_MasterTxReadyFlag)))
847 {
848 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterStopDetectFlag);
849 break;
850 }
851 }
852
853 #if I2C_RETRY_TIMES != 0U
854 if (0U == waitTimes)
855 {
856 result = kStatus_LPI2C_Timeout;
857 }
858 #endif
859 }
860
861 return result;
862 }
863
864 /*!
865 * brief Performs a polling receive transfer on the I2C bus.
866 *
867 * param base The LPI2C peripheral base address.
868 * param rxBuff The pointer to the data to be transferred.
869 * param rxSize The length in bytes of the data to be transferred.
870 * retval #kStatus_Success Data was received successfully.
871 * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
872 * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
873 * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
874 * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
875 * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
876 */
877 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
878 {
879 assert(NULL != rxBuff);
880
881 status_t result = kStatus_Success;
882 uint8_t *buf;
883 size_t tmpRxSize = rxSize;
884 #if I2C_RETRY_TIMES != 0U
885 uint32_t waitTimes;
886 #endif
887
888 /* Check transfer data size. */
889 if (rxSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base)))
890 {
891 return kStatus_InvalidArgument;
892 }
893
894 /* Handle empty read. */
895 if (rxSize != 0U)
896 {
897 /* Wait until there is room in the command fifo. */
898 result = LPI2C_MasterWaitForTxReady(base);
899 if (kStatus_Success == result)
900 {
901 /* Issue command to receive data. A single write to MTDR can issue read operation of 0xFFU + 1 byte of data
902 at most, so when the rxSize is larger than 0x100U, push multiple read commands to MTDR until rxSize is
903 reached. */
904 while (tmpRxSize != 0U)
905 {
906 if (tmpRxSize > 256U)
907 {
908 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
909 tmpRxSize -= 256U;
910 }
911 else
912 {
913 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
914 tmpRxSize = 0U;
915 }
916 }
917
918 /* Receive data */
919 buf = (uint8_t *)rxBuff;
920 while (0U != (rxSize--))
921 {
922 #if I2C_RETRY_TIMES != 0U
923 waitTimes = I2C_RETRY_TIMES;
924 #endif
925 /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
926 /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
927 /* using a single register read. */
928 uint32_t value = 0U;
929 do
930 {
931 /* Check for errors. */
932 result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
933 if (kStatus_Success != result)
934 {
935 break;
936 }
937
938 value = base->MRDR;
939 #if I2C_RETRY_TIMES != 0U
940 waitTimes--;
941 } while ((0U != (value & LPI2C_MRDR_RXEMPTY_MASK)) && (0U != waitTimes));
942 if (0U == waitTimes)
943 {
944 result = kStatus_LPI2C_Timeout;
945 }
946 #else
947 } while (0U != (value & LPI2C_MRDR_RXEMPTY_MASK));
948 #endif
949 if ((status_t)kStatus_Success != result)
950 {
951 break;
952 }
953
954 *buf++ = (uint8_t)(value & LPI2C_MRDR_DATA_MASK);
955 }
956 }
957 }
958
959 return result;
960 }
961
962 /*!
963 * brief Performs a polling send transfer on the I2C bus.
964 *
965 * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
966 * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
967 * function returns #kStatus_LPI2C_Nak.
968 *
969 * param base The LPI2C peripheral base address.
970 * param txBuff The pointer to the data to be transferred.
971 * param txSize The length in bytes of the data to be transferred.
972 * retval #kStatus_Success Data was sent successfully.
973 * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
974 * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
975 * retval #kStatus_LPI2C_FifoError FIFO under run or over run.
976 * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
977 * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
978 */
LPI2C_MasterSend(LPI2C_Type * base,void * txBuff,size_t txSize)979 status_t LPI2C_MasterSend(LPI2C_Type *base, void *txBuff, size_t txSize)
980 {
981 status_t result = kStatus_Success;
982 uint8_t *buf = (uint8_t *)txBuff;
983
984 assert(NULL != txBuff);
985
986 /* Send data buffer */
987 while (0U != (txSize--))
988 {
989 /* Wait until there is room in the fifo. This also checks for errors. */
990 result = LPI2C_MasterWaitForTxReady(base);
991 if (kStatus_Success != result)
992 {
993 break;
994 }
995
996 /* Write byte into LPI2C master data register. */
997 base->MTDR = *buf++;
998 }
999
1000 return result;
1001 }
1002
1003 /*!
1004 * brief Performs a master polling transfer on the I2C bus.
1005 *
1006 * note The API does not return until the transfer succeeds or fails due
1007 * to error happens during transfer.
1008 *
1009 * param base The LPI2C peripheral base address.
1010 * param transfer Pointer to the transfer structure.
1011 * retval #kStatus_Success Data was received successfully.
1012 * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
1013 * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
1014 * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
1015 * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
1016 * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1017 */
LPI2C_MasterTransferBlocking(LPI2C_Type * base,lpi2c_master_transfer_t * transfer)1018 status_t LPI2C_MasterTransferBlocking(LPI2C_Type *base, lpi2c_master_transfer_t *transfer)
1019 {
1020 assert(NULL != transfer);
1021 assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1022
1023 status_t result = kStatus_Success;
1024 uint16_t commandBuffer[7];
1025 uint32_t cmdCount = 0U;
1026
1027 /* Check transfer data size in read operation. */
1028 if ((transfer->direction == kLPI2C_Read) &&
1029 (transfer->dataSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1030 {
1031 return kStatus_InvalidArgument;
1032 }
1033
1034 /* Enable the master function and disable the slave function. */
1035 LPI2C_MasterEnable(base, true);
1036 LPI2C_SlaveEnable(base, false);
1037
1038 /* Return an error if the bus is already in use not by us. */
1039 result = LPI2C_CheckForBusyBus(base);
1040 /*
1041 * $Branch Coverage Justification$
1042 * $ref fsl_lpi2c_c_ref_2$
1043 */
1044 if (kStatus_Success == result)
1045 {
1046 /* Clear all flags. */
1047 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1048
1049 /* Turn off auto-stop option. */
1050 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1051
1052 lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
1053 if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1054 {
1055 commandBuffer[cmdCount++] =
1056 (uint16_t)kStartCmd |
1057 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
1058 }
1059
1060 /* Subaddress, MSB first. */
1061 if (0U != transfer->subaddressSize)
1062 {
1063 uint32_t subaddressRemaining = transfer->subaddressSize;
1064 while (0U != subaddressRemaining--)
1065 {
1066 uint8_t subaddressByte = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1067 commandBuffer[cmdCount++] = subaddressByte;
1068 }
1069 }
1070
1071 /* Reads need special handling. */
1072 if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
1073 {
1074 /* Need to send repeated start if switching directions to read. */
1075 if (direction == kLPI2C_Write)
1076 {
1077 commandBuffer[cmdCount++] =
1078 (uint16_t)kStartCmd |
1079 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1080 }
1081 }
1082
1083 /* Send command buffer */
1084 uint32_t index = 0U;
1085 while (0U != cmdCount--)
1086 {
1087 /* Wait until there is room in the fifo. This also checks for errors. */
1088 result = LPI2C_MasterWaitForTxReady(base);
1089 if (kStatus_Success != result)
1090 {
1091 break;
1092 }
1093
1094 /* Write byte into LPI2C master data register. */
1095 base->MTDR = commandBuffer[index];
1096 index++;
1097 }
1098
1099 if (kStatus_Success == result)
1100 {
1101 /* Transmit data. */
1102 if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
1103 {
1104 /* Send Data. */
1105 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
1106 }
1107
1108 /* Receive Data. */
1109 if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
1110 {
1111 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
1112 }
1113 /*
1114 * $Branch Coverage Justification$
1115 * Errors cannot be simulated by software during transmission.(will improve)
1116 */
1117 if (kStatus_Success == result)
1118 {
1119 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1120 {
1121 result = LPI2C_MasterStop(base);
1122 }
1123 }
1124 }
1125
1126 /* Transmit fail */
1127 if (kStatus_Success != result)
1128 {
1129 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1130 {
1131 (void)LPI2C_MasterStop(base);
1132 }
1133 }
1134 }
1135
1136 return result;
1137 }
1138
1139 /*!
1140 * brief Creates a new handle for the LPI2C master non-blocking APIs.
1141 *
1142 * The creation of a handle is for use with the non-blocking APIs. Once a handle
1143 * is created, there is not a corresponding destroy handle. If the user wants to
1144 * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
1145 *
1146 *
1147 * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1148 * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1149 * enable the associated INTMUX IRQ in application.
1150 *
1151 * param base The LPI2C peripheral base address.
1152 * param[out] handle Pointer to the LPI2C master driver handle.
1153 * param callback User provided pointer to the asynchronous callback function.
1154 * param userData User provided pointer to the application callback data.
1155 */
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)1156 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1157 lpi2c_master_handle_t *handle,
1158 lpi2c_master_transfer_callback_t callback,
1159 void *userData)
1160 {
1161 uint32_t instance;
1162
1163 assert(NULL != handle);
1164
1165 /* Clear out the handle. */
1166 (void)memset(handle, 0, sizeof(*handle));
1167
1168 /* Look up instance number */
1169 instance = LPI2C_GetInstance(base);
1170
1171 /* Save base and instance. */
1172 handle->completionCallback = callback;
1173 handle->userData = userData;
1174
1175 /* Save this handle for IRQ use. */
1176 s_lpi2cMasterHandle[instance] = handle;
1177
1178 /* Set irq handler. */
1179 s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1180
1181 /* Clear internal IRQ enables and enable NVIC IRQ. */
1182 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1183
1184 /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1185 In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1186 INTMUX IRQ in application code. */
1187 (void)EnableIRQ(kLpi2cIrqs[instance]);
1188 }
1189
LPI2C_TransferStateMachineSendCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1190 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
1191 lpi2c_master_handle_t *handle,
1192 lpi2c_state_machine_param_t *stateParams)
1193 {
1194 assert(stateParams != NULL);
1195 uint16_t sendval;
1196
1197 /* Make sure there is room in the tx fifo for the next command. */
1198 if (0U == (stateParams->txCount)--)
1199 {
1200 stateParams->state_complete = true;
1201 return;
1202 }
1203
1204 /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1205 sendval = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1206 base->MTDR = sendval;
1207 handle->buf++;
1208 handle->buf++;
1209
1210 /* Count down until all commands are sent. */
1211 if (--handle->remainingBytes == 0U)
1212 {
1213 /* Choose next state and set up buffer pointer and count. */
1214 if (0U != handle->transfer.dataSize)
1215 {
1216 /* Either a send or receive transfer is next. */
1217 handle->state = (uint8_t)kTransferDataState;
1218 handle->buf = (uint8_t *)handle->transfer.data;
1219 handle->remainingBytes = (uint16_t)handle->transfer.dataSize;
1220 if (handle->transfer.direction == kLPI2C_Read)
1221 {
1222 /* Disable TX interrupt */
1223 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1224 /* Issue command to receive data. A single write to MTDR can issue read operation of
1225 0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1226 multiple read commands to MTDR until dataSize is reached. */
1227 size_t tmpRxSize = handle->transfer.dataSize;
1228 while (tmpRxSize != 0U)
1229 {
1230 LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1231 /*
1232 * $Branch Coverage Justification$
1233 * The transmission commands will not exceed FIFO SIZE.(will improve)
1234 */
1235 while ((size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) == stateParams->txCount)
1236 {
1237 LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1238 }
1239
1240 if (tmpRxSize > 256U)
1241 {
1242 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1243 tmpRxSize -= 256U;
1244 }
1245 else
1246 {
1247 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1248 tmpRxSize = 0U;
1249 }
1250 }
1251 }
1252 }
1253 else
1254 {
1255 /* No transfer, so move to stop state. */
1256 handle->state = (uint8_t)kStopState;
1257 }
1258 }
1259 }
1260
LPI2C_TransferStateMachineReadCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1261 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
1262 lpi2c_master_handle_t *handle,
1263 lpi2c_state_machine_param_t *stateParams)
1264 {
1265 assert(stateParams != NULL);
1266
1267 /* Make sure there is room in the tx fifo for the read command. */
1268 if (0U == (stateParams->txCount)--)
1269 {
1270 stateParams->state_complete = true;
1271 return;
1272 }
1273
1274 base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(handle->transfer.dataSize - 1U);
1275
1276 /* Move to transfer state. */
1277 handle->state = (uint8_t)kTransferDataState;
1278 if (handle->transfer.direction == kLPI2C_Read)
1279 {
1280 /* Disable TX interrupt */
1281 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1282 }
1283 }
1284
LPI2C_TransferStateMachineTransferData(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1285 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
1286 lpi2c_master_handle_t *handle,
1287 lpi2c_state_machine_param_t *stateParams)
1288 {
1289 assert(stateParams != NULL);
1290
1291 if (handle->transfer.direction == kLPI2C_Write)
1292 {
1293 /* Make sure there is room in the tx fifo. */
1294 if (0U == stateParams->txCount--)
1295 {
1296 stateParams->state_complete = true;
1297 return;
1298 }
1299
1300 /* Put byte to send in fifo. */
1301 base->MTDR = *(handle->buf)++;
1302 }
1303 else
1304 {
1305 /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1306 /* Make sure there is data in the rx fifo. */
1307 if (0U == stateParams->rxCount--)
1308 {
1309 stateParams->state_complete = true;
1310 return;
1311 }
1312
1313 /* Read byte from fifo. */
1314 *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1315 }
1316
1317 /* Move to stop when the transfer is done. */
1318 if (--handle->remainingBytes == 0U)
1319 {
1320 if (handle->transfer.direction == kLPI2C_Write)
1321 {
1322 stateParams->state_complete = true;
1323 }
1324 handle->state = (uint8_t)kStopState;
1325 }
1326 }
1327
LPI2C_TransferStateMachineStopState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1328 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
1329 lpi2c_master_handle_t *handle,
1330 lpi2c_state_machine_param_t *stateParams,
1331 bool *isDone)
1332 {
1333 assert(stateParams != NULL);
1334
1335 /* Only issue a stop transition if the caller requested it. */
1336 if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1337 {
1338 /* Make sure there is room in the tx fifo for the stop command. */
1339 if (0U == (stateParams->txCount)--)
1340 {
1341 stateParams->state_complete = true;
1342 return;
1343 }
1344
1345 base->MTDR = (uint32_t)kStopCmd;
1346 }
1347 else
1348 {
1349 /* If all data is read and no stop flag is required to send, we are done. */
1350 if (handle->transfer.direction == kLPI2C_Read)
1351 {
1352 *isDone = true;
1353 }
1354 stateParams->state_complete = true;
1355 }
1356 handle->state = (uint8_t)kWaitForCompletionState;
1357 }
1358
LPI2C_TransferStateMachineWaitState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1359 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
1360 lpi2c_master_handle_t *handle,
1361 lpi2c_state_machine_param_t *stateParams,
1362 bool *isDone)
1363 {
1364 assert(stateParams != NULL);
1365
1366 if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1367 {
1368 /* We stay in this state until the stop state is detected. */
1369 if (0U != ((stateParams->status) & (uint32_t)kLPI2C_MasterStopDetectFlag))
1370 {
1371 *isDone = true;
1372 }
1373 }
1374 else
1375 {
1376 /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1377 are all send out to bus. */
1378 if ((handle->transfer.direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1379 {
1380 /* We stay in this state until the data is sent out to bus. */
1381 *isDone = true;
1382 }
1383 }
1384 stateParams->state_complete = true;
1385 }
1386
1387 /*!
1388 * @brief Execute states until FIFOs are exhausted.
1389 * @param handle Master nonblocking driver handle.
1390 * @param[out] isDone Set to true if the transfer has completed.
1391 * @retval #kStatus_Success
1392 * @retval #kStatus_LPI2C_PinLowTimeout
1393 * @retval #kStatus_LPI2C_ArbitrationLost
1394 * @retval #kStatus_LPI2C_Nak
1395 * @retval #kStatus_LPI2C_FifoError
1396 */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)1397 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1398 {
1399 assert(NULL != base && NULL != handle && NULL != isDone);
1400
1401 status_t result = kStatus_Success;
1402 lpi2c_state_machine_param_t stateParams;
1403 (void)memset(&stateParams, 0, sizeof(stateParams));
1404
1405 stateParams.state_complete = false;
1406
1407 /* Set default isDone return value. */
1408 *isDone = false;
1409
1410 /* Check for errors. */
1411 stateParams.status = LPI2C_MasterGetStatusFlags(base);
1412
1413 /* Get fifo counts. */
1414 LPI2C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
1415
1416 /* For the last byte, nack flag is expected.
1417 Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1418 in case FIFO is emptied when stop command has not been sent. */
1419 if (handle->remainingBytes == 0U)
1420 {
1421 /* When data size is not zero which means it is not only one byte of address is sent, and */
1422 /* when the txfifo is empty, or have one byte which is the stop command, then the nack status can be ignored. */
1423 if (((handle->transfer).dataSize != 0U) &&
1424 ((stateParams.txCount == 0U) ||
1425 (((stateParams.txCount) == 1U) && (handle->state == (uint8_t)kWaitForCompletionState) &&
1426 (((handle->transfer).flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U))))
1427 {
1428 (stateParams.status) &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1429 }
1430 }
1431
1432 result = LPI2C_MasterCheckAndClearError(base, stateParams.status);
1433
1434 if (kStatus_Success == result)
1435 {
1436 /* Compute room in tx fifo */
1437 stateParams.txCount = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) - stateParams.txCount;
1438
1439 while (!stateParams.state_complete)
1440 {
1441 /* Execute the state. */
1442 /*
1443 * $Branch Coverage Justification$
1444 * $ref fsl_lpi2c_c_ref_1$
1445 */
1446 switch (handle->state)
1447 {
1448 case (uint8_t)kSendCommandState:
1449 LPI2C_TransferStateMachineSendCommand(base, handle, &stateParams);
1450 break;
1451
1452 case (uint8_t)kIssueReadCommandState:
1453 LPI2C_TransferStateMachineReadCommand(base, handle, &stateParams);
1454 break;
1455
1456 case (uint8_t)kTransferDataState:
1457 LPI2C_TransferStateMachineTransferData(base, handle, &stateParams);
1458 break;
1459
1460 case (uint8_t)kStopState:
1461 LPI2C_TransferStateMachineStopState(base, handle, &stateParams, isDone);
1462 break;
1463
1464 case (uint8_t)kWaitForCompletionState:
1465 LPI2C_TransferStateMachineWaitState(base, handle, &stateParams, isDone);
1466 break;
1467 default:
1468 assert(false);
1469 break;
1470 }
1471 }
1472 }
1473 return result;
1474 }
1475
1476 /*!
1477 * @brief Prepares the transfer state machine and fills in the command buffer.
1478 * @param handle Master nonblocking driver handle.
1479 */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)1480 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1481 {
1482 lpi2c_master_transfer_t *xfer = &handle->transfer;
1483
1484 /* Handle no start option. */
1485 if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1486 {
1487 if (xfer->direction == kLPI2C_Read)
1488 {
1489 /* Need to issue read command first. */
1490 handle->state = (uint8_t)kIssueReadCommandState;
1491 }
1492 else
1493 {
1494 /* Start immediately in the data transfer state. */
1495 handle->state = (uint8_t)kTransferDataState;
1496 }
1497
1498 handle->buf = (uint8_t *)xfer->data;
1499 handle->remainingBytes = (uint16_t)xfer->dataSize;
1500 }
1501 else
1502 {
1503 uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
1504 uint32_t cmdCount = 0U;
1505
1506 /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1507 /* data transfer direction. */
1508 lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1509
1510 /* Start command. */
1511 cmd[cmdCount++] =
1512 (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1513
1514 /* Subaddress, MSB first. */
1515 if (0U != xfer->subaddressSize)
1516 {
1517 uint32_t subaddressRemaining = xfer->subaddressSize;
1518 while (0U != (subaddressRemaining--))
1519 {
1520 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1521 cmd[cmdCount++] = subaddressByte;
1522 }
1523 }
1524
1525 /* Reads need special handling. */
1526 if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1527 {
1528 /* Need to send repeated start if switching directions to read. */
1529 if (direction == kLPI2C_Write)
1530 {
1531 cmd[cmdCount++] = (uint16_t)kStartCmd |
1532 (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1533 }
1534 }
1535
1536 /* Set up state machine for transferring the commands. */
1537 handle->state = (uint8_t)kSendCommandState;
1538 handle->remainingBytes = (uint16_t)cmdCount;
1539 handle->buf = (uint8_t *)&handle->commandBuffer;
1540 }
1541 }
1542
1543 /*!
1544 * brief Performs a non-blocking transaction on the I2C bus.
1545 *
1546 * param base The LPI2C peripheral base address.
1547 * param handle Pointer to the LPI2C master driver handle.
1548 * param transfer The pointer to the transfer descriptor.
1549 * retval #kStatus_Success The transaction was started successfully.
1550 * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1551 * transaction is already in progress.
1552 */
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)1553 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1554 lpi2c_master_handle_t *handle,
1555 lpi2c_master_transfer_t *transfer)
1556 {
1557 assert(NULL != handle);
1558 assert(NULL != transfer);
1559 assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1560
1561 status_t result;
1562
1563 /* Check transfer data size in read operation. */
1564 if ((transfer->direction == kLPI2C_Read) &&
1565 (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1566 {
1567 return kStatus_InvalidArgument;
1568 }
1569
1570 /* Return busy if another transaction is in progress. */
1571 if (handle->state != (uint8_t)kIdleState)
1572 {
1573 result = kStatus_LPI2C_Busy;
1574 }
1575 else
1576 {
1577 result = LPI2C_CheckForBusyBus(base);
1578 }
1579
1580 if ((status_t)kStatus_Success == result)
1581 {
1582 /* Enable the master function and disable the slave function. */
1583 LPI2C_MasterEnable(base, true);
1584 LPI2C_SlaveEnable(base, false);
1585
1586 /* Disable LPI2C IRQ sources while we configure stuff. */
1587 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1588
1589 /* Reset FIFO in case there are data. */
1590 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1591
1592 /* Save transfer into handle. */
1593 handle->transfer = *transfer;
1594
1595 /* Generate commands to send. */
1596 LPI2C_InitTransferStateMachine(handle);
1597
1598 /* Clear all flags. */
1599 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1600
1601 /* Turn off auto-stop option. */
1602 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1603
1604 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1605 LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1606 }
1607
1608 return result;
1609 }
1610
1611 /*!
1612 * brief Returns number of bytes transferred so far.
1613 * param base The LPI2C peripheral base address.
1614 * param handle Pointer to the LPI2C master driver handle.
1615 * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1616 * retval #kStatus_Success
1617 * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1618 */
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)1619 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1620 {
1621 status_t result = kStatus_Success;
1622
1623 assert(NULL != handle);
1624
1625 if (NULL == count)
1626 {
1627 result = kStatus_InvalidArgument;
1628 }
1629
1630 /* Catch when there is not an active transfer. */
1631 else if (handle->state == (uint8_t)kIdleState)
1632 {
1633 *count = 0;
1634 result = kStatus_NoTransferInProgress;
1635 }
1636 else
1637 {
1638 uint8_t state;
1639 uint16_t remainingBytes;
1640 uint32_t dataSize;
1641
1642 /* Cache some fields with IRQs disabled. This ensures all field values */
1643 /* are synchronized with each other during an ongoing transfer. */
1644 uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1645 LPI2C_MasterDisableInterrupts(base, irqs);
1646 state = handle->state;
1647 remainingBytes = handle->remainingBytes;
1648 dataSize = handle->transfer.dataSize;
1649 LPI2C_MasterEnableInterrupts(base, irqs);
1650
1651 /* Get transfer count based on current transfer state. */
1652 switch (state)
1653 {
1654 case (uint8_t)kIdleState:
1655 case (uint8_t)kSendCommandState:
1656 case (uint8_t)
1657 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1658 *count = 0;
1659 break;
1660
1661 case (uint8_t)kTransferDataState:
1662 *count = dataSize - remainingBytes;
1663 break;
1664
1665 case (uint8_t)kStopState:
1666 case (uint8_t)kWaitForCompletionState:
1667 default:
1668 *count = dataSize;
1669 break;
1670 }
1671 }
1672
1673 return result;
1674 }
1675
1676 /*!
1677 * brief Terminates a non-blocking LPI2C master transmission early.
1678 *
1679 * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1680 * LPI2C peripheral's IRQ priority.
1681 *
1682 * param base The LPI2C peripheral base address.
1683 * param handle Pointer to the LPI2C master driver handle.
1684 */
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1685 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1686 {
1687 if (handle->state != (uint8_t)kIdleState)
1688 {
1689 /* Disable internal IRQ enables. */
1690 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1691
1692 /* Reset fifos. */
1693 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1694
1695 /* If master is still busy and has not send out stop signal yet. */
1696 if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1697 (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1698 {
1699 /* Send a stop command to finalize the transfer. */
1700 base->MTDR = (uint32_t)kStopCmd;
1701 }
1702
1703 /* Reset handle. */
1704 handle->state = (uint8_t)kIdleState;
1705 }
1706 }
1707
1708 /*!
1709 * brief Reusable routine to handle master interrupts.
1710 * note This function does not need to be called unless you are reimplementing the
1711 * nonblocking API's interrupt handler routines to add special functionality.
1712 * param base The LPI2C peripheral base address.
1713 * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1714 */
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,void * lpi2cMasterHandle)1715 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, void *lpi2cMasterHandle)
1716 {
1717 assert(lpi2cMasterHandle != NULL);
1718
1719 lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1720 bool isDone = false;
1721 status_t result;
1722
1723 /* Don't do anything if we don't have a valid handle. */
1724 if (NULL != handle)
1725 {
1726 if (handle->state != (uint8_t)kIdleState)
1727 {
1728 result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1729
1730 if ((result != kStatus_Success) || isDone)
1731 {
1732 /* Handle error, terminate xfer */
1733 if (result != kStatus_Success)
1734 {
1735 LPI2C_MasterTransferAbort(base, handle);
1736 }
1737
1738 /* Disable internal IRQ enables. */
1739 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1740
1741 /* Set handle to idle state. */
1742 handle->state = (uint8_t)kIdleState;
1743
1744 /* Invoke callback. */
1745 if (NULL != handle->completionCallback)
1746 {
1747 handle->completionCallback(base, handle, result, handle->userData);
1748 }
1749 }
1750 }
1751 }
1752 }
1753
1754 /*!
1755 * brief Provides a default configuration for the LPI2C slave peripheral.
1756 *
1757 * This function provides the following default configuration for the LPI2C slave peripheral:
1758 * code
1759 * slaveConfig->enableSlave = true;
1760 * slaveConfig->address0 = 0U;
1761 * slaveConfig->address1 = 0U;
1762 * slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1763 * slaveConfig->filterDozeEnable = true;
1764 * slaveConfig->filterEnable = true;
1765 * slaveConfig->enableGeneralCall = false;
1766 * slaveConfig->sclStall.enableAck = false;
1767 * slaveConfig->sclStall.enableTx = true;
1768 * slaveConfig->sclStall.enableRx = true;
1769 * slaveConfig->sclStall.enableAddress = true;
1770 * slaveConfig->ignoreAck = false;
1771 * slaveConfig->enableReceivedAddressRead = false;
1772 * slaveConfig->sdaGlitchFilterWidth_ns = 0;
1773 * slaveConfig->sclGlitchFilterWidth_ns = 0;
1774 * slaveConfig->dataValidDelay_ns = 0;
1775 * slaveConfig->clockHoldTime_ns = 0;
1776 * endcode
1777 *
1778 * After calling this function, override any settings to customize the configuration,
1779 * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1780 * address0 member of the configuration structure with the desired slave address.
1781 *
1782 * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1783 * #lpi2c_slave_config_t.
1784 */
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1785 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1786 {
1787 /* Initializes the configure structure to zero. */
1788 (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1789
1790 slaveConfig->enableSlave = true;
1791 slaveConfig->address0 = 0U;
1792 slaveConfig->address1 = 0U;
1793 slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1794 slaveConfig->filterDozeEnable = true;
1795 slaveConfig->filterEnable = true;
1796 slaveConfig->enableGeneralCall = false;
1797 slaveConfig->sclStall.enableAck = false;
1798 slaveConfig->sclStall.enableTx = true;
1799 slaveConfig->sclStall.enableRx = true;
1800 slaveConfig->sclStall.enableAddress = false;
1801 slaveConfig->ignoreAck = false;
1802 slaveConfig->enableReceivedAddressRead = false;
1803 slaveConfig->sdaGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
1804 slaveConfig->sclGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
1805 slaveConfig->dataValidDelay_ns = 0U;
1806 /* When enabling the slave tx SCL stall, set the default clock hold time to 250ns according
1807 to I2C spec for standard mode baudrate(100k). User can manually change it to 100ns or 50ns
1808 for fast-mode(400k) or fast-mode+(1m). */
1809 slaveConfig->clockHoldTime_ns = 250U;
1810 }
1811
1812 /*!
1813 * brief Initializes the LPI2C slave peripheral.
1814 *
1815 * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1816 * provided configuration.
1817 *
1818 * param base The LPI2C peripheral base address.
1819 * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1820 * that you can override.
1821 * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1822 * data valid delay, and clock hold time.
1823 */
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1824 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1825 {
1826 uint32_t tmpReg;
1827 uint32_t tmpCycle;
1828
1829 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1830
1831 uint32_t instance = LPI2C_GetInstance(base);
1832
1833 /* Ungate the clock. */
1834 (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1835 #if defined(LPI2C_PERIPH_CLOCKS)
1836 /* Ungate the functional clock in initialize function. */
1837 CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1838 #endif
1839
1840 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1841
1842 #if defined(LPI2C_RESETS_ARRAY)
1843 RESET_ReleasePeripheralReset(s_lpi2cResets[LPI2C_GetInstance(base)]);
1844 #endif
1845
1846 /* Restore to reset conditions. */
1847 LPI2C_SlaveReset(base);
1848
1849 /* Configure peripheral. */
1850 base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1851
1852 base->SCFGR1 =
1853 LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1854 LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1855 LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1856 LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1857 LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1858
1859 /* Calculate SDA filter width. The width is equal to FILTSDA+3 cycles of functional clock.
1860 And set FILTSDA to 0 disables the fileter, so the min value is 4. */
1861 tmpReg = LPI2C_SCFGR2_FILTSDA(
1862 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns, 4U,
1863 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT) + 3U, 0U) -
1864 3U);
1865
1866 /* Calculate SDL filter width. The width is equal to FILTSCL+3 cycles of functional clock.
1867 And set FILTSCL to 0 disables the fileter, so the min value is 4. */
1868 tmpCycle = LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns, 4U,
1869 (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT) + 3U, 0U);
1870 tmpReg |= LPI2C_SCFGR2_FILTSCL(tmpCycle - 3U);
1871
1872 /* Calculate data valid time. The time is equal to FILTSCL+DATAVD+3 cycles of functional clock.
1873 So the min value is FILTSCL+3. */
1874 tmpReg |= LPI2C_SCFGR2_DATAVD(
1875 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns, tmpCycle,
1876 tmpCycle + (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 0U) -
1877 tmpCycle);
1878
1879 /* Calculate clock hold time. The time is equal to CLKHOLD+3 cycles of functional clock.
1880 So the min value is 3. */
1881 base->SCFGR2 =
1882 tmpReg | LPI2C_SCFGR2_CLKHOLD(
1883 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns, 3U,
1884 (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT) + 3U, 0U) -
1885 3U);
1886
1887 /* Save SCR to last so we don't enable slave until it is configured */
1888 base->SCR = LPI2C_SCR_FILTDZ(!slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1889 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1890 }
1891
1892 /*!
1893 * brief Deinitializes the LPI2C slave peripheral.
1894 *
1895 * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1896 * reset to restore the peripheral to reset conditions.
1897 *
1898 * param base The LPI2C peripheral base address.
1899 */
LPI2C_SlaveDeinit(LPI2C_Type * base)1900 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1901 {
1902 LPI2C_SlaveReset(base);
1903
1904 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1905
1906 uint32_t instance = LPI2C_GetInstance(base);
1907
1908 /* Gate the clock. */
1909 (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1910
1911 #if defined(LPI2C_PERIPH_CLOCKS)
1912 /* Gate the functional clock. */
1913 CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1914 #endif
1915
1916 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1917 }
1918
1919 /*!
1920 * @brief Convert provided flags to status code, and clear any errors if present.
1921 * @param base The LPI2C peripheral base address.
1922 * @param status Current status flags value that will be checked.
1923 * @retval #kStatus_Success
1924 * @retval #kStatus_LPI2C_BitError
1925 * @retval #kStatus_LPI2C_FifoError
1926 */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1927 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1928 {
1929 status_t result = kStatus_Success;
1930
1931 flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1932 if (0U != flags)
1933 {
1934 /*
1935 * $Branch Coverage Justification$
1936 * It is hard to simulate bitError in automation test environment, need interference on bus.(will improve)
1937 */
1938 if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1939 {
1940 result = kStatus_LPI2C_BitError;
1941 }
1942 else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1943 {
1944 result = kStatus_LPI2C_FifoError;
1945 }
1946 else
1947 {
1948 ; /* Intentional empty */
1949 }
1950
1951 /* Clear the errors. */
1952 LPI2C_SlaveClearStatusFlags(base, flags);
1953 }
1954 else
1955 {
1956 ; /* Intentional empty */
1957 }
1958
1959 return result;
1960 }
1961
1962 /*!
1963 * brief Performs a polling send transfer on the I2C bus.
1964 *
1965 * param base The LPI2C peripheral base address.
1966 * param txBuff The pointer to the data to be transferred.
1967 * param txSize The length in bytes of the data to be transferred.
1968 * param[out] actualTxSize
1969 * return Error or success status returned by API.
1970 */
LPI2C_SlaveSend(LPI2C_Type * base,void * txBuff,size_t txSize,size_t * actualTxSize)1971 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1972 {
1973 status_t result = kStatus_Success;
1974 uint8_t *buf = (uint8_t *)txBuff;
1975 size_t remaining = txSize;
1976
1977 assert(NULL != txBuff);
1978
1979 #if I2C_RETRY_TIMES != 0U
1980 uint32_t waitTimes = I2C_RETRY_TIMES;
1981 #endif
1982
1983 /* Clear stop flag. */
1984 LPI2C_SlaveClearStatusFlags(base,
1985 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1986
1987 while (0U != remaining)
1988 {
1989 uint32_t flags;
1990
1991 /* Wait until we can transmit. */
1992 do
1993 {
1994 /* Check for errors */
1995 flags = LPI2C_SlaveGetStatusFlags(base);
1996 result = LPI2C_SlaveCheckAndClearError(base, flags);
1997 if (kStatus_Success != result)
1998 {
1999 if (NULL != actualTxSize)
2000 {
2001 *actualTxSize = txSize - remaining;
2002 }
2003 break;
2004 }
2005 #if I2C_RETRY_TIMES != 0U
2006 waitTimes--;
2007 } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2008 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2009 (0U != waitTimes));
2010 if (0U == waitTimes)
2011 {
2012 result = kStatus_LPI2C_Timeout;
2013 }
2014 #else
2015 } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2016 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2017 #endif
2018
2019 if (kStatus_Success != result)
2020 {
2021 break;
2022 }
2023
2024 /* Send a byte. */
2025 if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2026 {
2027 base->STDR = *buf++;
2028 --remaining;
2029 }
2030
2031 /* Exit loop if we see a stop or restart in transfer*/
2032 /*
2033 * $Branch Coverage Justification$
2034 * $ref fsl_lpi2c_c_ref_3$
2035 */
2036 if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2037 (remaining != 0U))
2038 {
2039 LPI2C_SlaveClearStatusFlags(
2040 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2041 break;
2042 }
2043 }
2044
2045 if (NULL != actualTxSize)
2046 {
2047 *actualTxSize = txSize - remaining;
2048 }
2049
2050 return result;
2051 }
2052
2053 /*!
2054 * brief Performs a polling receive transfer on the I2C bus.
2055 *
2056 * param base The LPI2C peripheral base address.
2057 * param rxBuff The pointer to the data to be transferred.
2058 * param rxSize The length in bytes of the data to be transferred.
2059 * param[out] actualRxSize
2060 * return Error or success status returned by API.
2061 */
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)2062 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
2063 {
2064 status_t result = kStatus_Success;
2065 uint8_t *buf = (uint8_t *)rxBuff;
2066 size_t remaining = rxSize;
2067
2068 assert(NULL != rxBuff);
2069
2070 #if I2C_RETRY_TIMES != 0U
2071 uint32_t waitTimes = I2C_RETRY_TIMES;
2072 #endif
2073
2074 /* Clear stop flag. */
2075 LPI2C_SlaveClearStatusFlags(base,
2076 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2077
2078 while (0U != remaining)
2079 {
2080 uint32_t flags;
2081
2082 /* Wait until we can receive. */
2083 do
2084 {
2085 /* Check for errors */
2086 flags = LPI2C_SlaveGetStatusFlags(base);
2087 result = LPI2C_SlaveCheckAndClearError(base, flags);
2088 if (kStatus_Success != result)
2089 {
2090 if (NULL != actualRxSize)
2091 {
2092 *actualRxSize = rxSize - remaining;
2093 }
2094 break;
2095 }
2096 #if I2C_RETRY_TIMES != 0U
2097 waitTimes--;
2098 } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2099 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2100 (0U != waitTimes));
2101 if (0U == waitTimes)
2102 {
2103 result = kStatus_LPI2C_Timeout;
2104 }
2105 #else
2106 } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2107 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2108 #endif
2109
2110 if ((status_t)kStatus_Success != result)
2111 {
2112 break;
2113 }
2114
2115 /* Receive a byte. */
2116 if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2117 {
2118 *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
2119 --remaining;
2120 }
2121
2122 /* Exit loop if we see a stop or restart */
2123 /*
2124 * $Branch Coverage Justification$
2125 * $ref fsl_lpi2c_c_ref_3$
2126 */
2127 if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2128 (remaining != 0U))
2129 {
2130 LPI2C_SlaveClearStatusFlags(
2131 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2132 break;
2133 }
2134 }
2135
2136 if (NULL != actualRxSize)
2137 {
2138 *actualRxSize = rxSize - remaining;
2139 }
2140
2141 return result;
2142 }
2143
2144 /*!
2145 * brief Creates a new handle for the LPI2C slave non-blocking APIs.
2146 *
2147 * The creation of a handle is for use with the non-blocking APIs. Once a handle
2148 * is created, there is not a corresponding destroy handle. If the user wants to
2149 * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
2150 *
2151 * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
2152 * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
2153 * enable the associated INTMUX IRQ in application.
2154
2155 * param base The LPI2C peripheral base address.
2156 * param[out] handle Pointer to the LPI2C slave driver handle.
2157 * param callback User provided pointer to the asynchronous callback function.
2158 * param userData User provided pointer to the application callback data.
2159 */
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)2160 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
2161 lpi2c_slave_handle_t *handle,
2162 lpi2c_slave_transfer_callback_t callback,
2163 void *userData)
2164 {
2165 uint32_t instance;
2166
2167 assert(NULL != handle);
2168
2169 /* Clear out the handle. */
2170 (void)memset(handle, 0, sizeof(*handle));
2171
2172 /* Look up instance number */
2173 instance = LPI2C_GetInstance(base);
2174
2175 /* Save base and instance. */
2176 handle->callback = callback;
2177 handle->userData = userData;
2178
2179 /* Save this handle for IRQ use. */
2180 s_lpi2cSlaveHandle[instance] = handle;
2181
2182 /* Set irq handler. */
2183 s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
2184
2185 /* Clear internal IRQ enables and enable NVIC IRQ. */
2186 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2187 (void)EnableIRQ(kLpi2cIrqs[instance]);
2188
2189 /* Nack by default. */
2190 base->STAR = LPI2C_STAR_TXNACK_MASK;
2191 }
2192
2193 /*!
2194 * brief Starts accepting slave transfers.
2195 *
2196 * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
2197 * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2198 * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
2199 * from the interrupt context.
2200 *
2201 * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
2202 * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
2203 * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
2204 * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
2205 * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
2206 * a convenient way to enable all events.
2207 *
2208 * param base The LPI2C peripheral base address.
2209 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2210 * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
2211 * which events to send to the callback. Other accepted values are 0 to get a default set of
2212 * only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
2213 *
2214 * retval #kStatus_Success Slave transfers were successfully started.
2215 * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
2216 */
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)2217 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
2218 {
2219 status_t result = kStatus_Success;
2220
2221 assert(NULL != handle);
2222
2223 /* Return busy if another transaction is in progress. */
2224 if (handle->isBusy)
2225 {
2226 result = kStatus_LPI2C_Busy;
2227 }
2228 else
2229 {
2230 /* Enable the slave function and disable the master function. */
2231 LPI2C_MasterEnable(base, false);
2232 LPI2C_SlaveEnable(base, true);
2233 /* Return an error if the bus is already in use not by us. */
2234 uint32_t status = LPI2C_SlaveGetStatusFlags(base);
2235 /*
2236 * $Branch Coverage Justification$
2237 * $ref fsl_lpi2c_c_ref_2$
2238 */
2239 if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
2240 {
2241 result = kStatus_LPI2C_Busy;
2242 }
2243 }
2244
2245 if ((status_t)kStatus_Success == result)
2246 {
2247 /* Disable LPI2C IRQ sources while we configure stuff. */
2248 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2249
2250 /* Clear transfer in handle. */
2251 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2252
2253 /* Record that we're busy. */
2254 handle->isBusy = true;
2255
2256 /* Set up event mask. tx and rx are always enabled. */
2257 handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
2258
2259 /* Ack by default. */
2260 base->STAR = 0U;
2261
2262 /* Clear all flags. */
2263 LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2264
2265 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2266 LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2267 }
2268
2269 return result;
2270 }
2271
2272 /*!
2273 * brief Gets the slave transfer status during a non-blocking transfer.
2274 * param base The LPI2C peripheral base address.
2275 * param handle Pointer to i2c_slave_handle_t structure.
2276 * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2277 * required.
2278 * retval #kStatus_Success
2279 * retval #kStatus_NoTransferInProgress
2280 */
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)2281 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2282 {
2283 status_t status = kStatus_Success;
2284
2285 assert(NULL != handle);
2286
2287 if (count == NULL)
2288 {
2289 status = kStatus_InvalidArgument;
2290 }
2291
2292 /* Catch when there is not an active transfer. */
2293 else if (!handle->isBusy)
2294 {
2295 *count = 0;
2296 status = kStatus_NoTransferInProgress;
2297 }
2298
2299 /* For an active transfer, just return the count from the handle. */
2300 else
2301 {
2302 *count = handle->transferredCount;
2303 }
2304
2305 return status;
2306 }
2307
2308 /*!
2309 * brief Aborts the slave non-blocking transfers.
2310 * note This API could be called at any time to stop slave for handling the bus events.
2311 * param base The LPI2C peripheral base address.
2312 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2313 */
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2314 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2315 {
2316 assert(NULL != handle);
2317
2318 /* Return idle if no transaction is in progress. */
2319 if (handle->isBusy)
2320 {
2321 /* Disable LPI2C IRQ sources. */
2322 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2323
2324 /* Nack by default. */
2325 base->STAR = LPI2C_STAR_TXNACK_MASK;
2326
2327 /* Reset transfer info. */
2328 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2329
2330 /* We're no longer busy. */
2331 handle->isBusy = false;
2332 }
2333 }
2334
2335 /*!
2336 * brief Reusable routine to handle slave interrupts.
2337 * note This function does not need to be called unless you are reimplementing the
2338 * non blocking API's interrupt handler routines to add special functionality.
2339 * param base The LPI2C peripheral base address.
2340 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2341 */
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2342 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2343 {
2344 uint32_t flags;
2345 lpi2c_slave_transfer_t *xfer;
2346
2347 /* Check for a valid handle in case of a spurious interrupt. */
2348 if (NULL != handle)
2349 {
2350 xfer = &handle->transfer;
2351
2352 /* Get status flags. */
2353 flags = LPI2C_SlaveGetStatusFlags(base);
2354
2355 if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2356 {
2357 xfer->event = kLPI2C_SlaveCompletionEvent;
2358 xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2359
2360 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2361 {
2362 handle->callback(base, xfer, handle->userData);
2363 }
2364 }
2365 else
2366 {
2367 if (0U !=
2368 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2369 {
2370 xfer->event = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2371 kLPI2C_SlaveRepeatedStartEvent :
2372 kLPI2C_SlaveCompletionEvent;
2373 xfer->receivedAddress = 0U;
2374 xfer->completionStatus = kStatus_Success;
2375 xfer->transferredCount = handle->transferredCount;
2376
2377 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2378 {
2379 handle->isBusy = false;
2380 }
2381
2382 if (handle->wasTransmit)
2383 {
2384 /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2385 /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2386 /* count that the master actually receives. */
2387 --xfer->transferredCount;
2388 handle->wasTransmit = false;
2389 }
2390
2391 /* Clear the flag. */
2392 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2393 (uint32_t)kLPI2C_SlaveStopDetectFlag));
2394
2395 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2396 base->STAR = 0U;
2397
2398 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2399 {
2400 handle->callback(base, xfer, handle->userData);
2401 }
2402
2403 if (0U != (flags & (uint32_t)kLPI2C_SlaveStopDetectFlag))
2404 {
2405 /* Clean up transfer info on completion, after the callback has been invoked. */
2406 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2407 }
2408 }
2409 if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2410 {
2411 xfer->event = kLPI2C_SlaveAddressMatchEvent;
2412 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2413
2414 /* Update handle status to busy because slave is addressed. */
2415 handle->isBusy = true;
2416 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2417 {
2418 handle->callback(base, xfer, handle->userData);
2419 }
2420 }
2421 if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2422 {
2423 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2424
2425 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2426 {
2427 handle->callback(base, xfer, handle->userData);
2428 }
2429 }
2430
2431 /* Handle transmit and receive. */
2432 if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2433 {
2434 handle->wasTransmit = true;
2435
2436 /* If we're out of data, invoke callback to get more. */
2437 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2438 {
2439 xfer->event = kLPI2C_SlaveTransmitEvent;
2440 if (NULL != handle->callback)
2441 {
2442 handle->callback(base, xfer, handle->userData);
2443 }
2444
2445 /* Clear the transferred count now that we have a new buffer. */
2446 handle->transferredCount = 0U;
2447 }
2448
2449 /* Transmit a byte. */
2450 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2451 {
2452 base->STDR = *xfer->data++;
2453 --xfer->dataSize;
2454 ++handle->transferredCount;
2455 }
2456 }
2457 if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2458 {
2459 /* If we're out of room in the buffer, invoke callback to get another. */
2460 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2461 {
2462 xfer->event = kLPI2C_SlaveReceiveEvent;
2463 if (NULL != handle->callback)
2464 {
2465 handle->callback(base, xfer, handle->userData);
2466 }
2467
2468 /* Clear the transferred count now that we have a new buffer. */
2469 handle->transferredCount = 0U;
2470 }
2471
2472 /* Receive a byte. */
2473 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2474 {
2475 *xfer->data++ = (uint8_t)base->SRDR;
2476 --xfer->dataSize;
2477 ++handle->transferredCount;
2478 }
2479 else
2480 {
2481 /* We don't have any room to receive more data, so send a nack. */
2482 base->STAR = LPI2C_STAR_TXNACK_MASK;
2483 }
2484 }
2485 }
2486 }
2487 }
2488
2489 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2490 /*!
2491 * @brief Shared IRQ handler that can call both master and slave ISRs.
2492 *
2493 * The master and slave ISRs are called through function pointers in order to decouple
2494 * this code from the ISR functions. Without this, the linker would always pull in both
2495 * ISRs and every function they call, even if only the functional API was used.
2496 *
2497 * @param base The LPI2C peripheral base address.
2498 * @param instance The LPI2C peripheral instance number.
2499 */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)2500 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2501 {
2502 /* Check for master IRQ. */
2503 if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2504 {
2505 /* Master mode. */
2506 s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
2507 }
2508
2509 /* Check for slave IRQ. */
2510 if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2511 {
2512 /* Slave mode. */
2513 s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
2514 }
2515 SDK_ISR_EXIT_BARRIER;
2516 }
2517 #endif
2518
2519 #if defined(LPI2C0)
2520 /* Implementation of LPI2C0 handler named in startup code. */
2521 void LPI2C0_DriverIRQHandler(void);
LPI2C0_DriverIRQHandler(void)2522 void LPI2C0_DriverIRQHandler(void)
2523 {
2524 LPI2C_CommonIRQHandler(LPI2C0, 0U);
2525 }
2526 #endif
2527
2528 #if defined(LPI2C1)
2529 /* Implementation of LPI2C1 handler named in startup code. */
2530 void LPI2C1_DriverIRQHandler(void);
LPI2C1_DriverIRQHandler(void)2531 void LPI2C1_DriverIRQHandler(void)
2532 {
2533 LPI2C_CommonIRQHandler(LPI2C1, 1U);
2534 }
2535 #endif
2536
2537 #if defined(LPI2C2)
2538 /* Implementation of LPI2C2 handler named in startup code. */
2539 void LPI2C2_DriverIRQHandler(void);
LPI2C2_DriverIRQHandler(void)2540 void LPI2C2_DriverIRQHandler(void)
2541 {
2542 LPI2C_CommonIRQHandler(LPI2C2, 2U);
2543 }
2544 #endif
2545
2546 #if defined(LPI2C3)
2547 /* Implementation of LPI2C3 handler named in startup code. */
2548 void LPI2C3_DriverIRQHandler(void);
LPI2C3_DriverIRQHandler(void)2549 void LPI2C3_DriverIRQHandler(void)
2550 {
2551 LPI2C_CommonIRQHandler(LPI2C3, 3U);
2552 }
2553 #endif
2554
2555 #if defined(LPI2C4)
2556 /* Implementation of LPI2C4 handler named in startup code. */
2557 void LPI2C4_DriverIRQHandler(void);
LPI2C4_DriverIRQHandler(void)2558 void LPI2C4_DriverIRQHandler(void)
2559 {
2560 LPI2C_CommonIRQHandler(LPI2C4, 4U);
2561 }
2562 #endif
2563
2564 #if defined(LPI2C5)
2565 /* Implementation of LPI2C5 handler named in startup code. */
2566 void LPI2C5_DriverIRQHandler(void);
LPI2C5_DriverIRQHandler(void)2567 void LPI2C5_DriverIRQHandler(void)
2568 {
2569 LPI2C_CommonIRQHandler(LPI2C5, 5U);
2570 }
2571 #endif
2572
2573 #if defined(LPI2C6)
2574 /* Implementation of LPI2C6 handler named in startup code. */
2575 void LPI2C6_DriverIRQHandler(void);
LPI2C6_DriverIRQHandler(void)2576 void LPI2C6_DriverIRQHandler(void)
2577 {
2578 LPI2C_CommonIRQHandler(LPI2C6, 6U);
2579 }
2580 #endif
2581
2582 #if defined(LPI2C7)
2583 /* Implementation of LPI2C7 handler named in startup code. */
2584 void LPI2C7_DriverIRQHandler(void);
LPI2C7_DriverIRQHandler(void)2585 void LPI2C7_DriverIRQHandler(void)
2586 {
2587 LPI2C_CommonIRQHandler(LPI2C7, 7U);
2588 }
2589 #endif
2590
2591 #if defined(LPI2C8)
2592 /* Implementation of LPI2C8 handler named in startup code. */
2593 void LPI2C8_DriverIRQHandler(void);
LPI2C8_DriverIRQHandler(void)2594 void LPI2C8_DriverIRQHandler(void)
2595 {
2596 LPI2C_CommonIRQHandler(LPI2C8, 8U);
2597 }
2598 #endif
2599
2600 #if defined(CM4_0__LPI2C)
2601 /* Implementation of CM4_0__LPI2C handler named in startup code. */
2602 void M4_0_LPI2C_DriverIRQHandler(void);
M4_0_LPI2C_DriverIRQHandler(void)2603 void M4_0_LPI2C_DriverIRQHandler(void)
2604 {
2605 LPI2C_CommonIRQHandler(CM4_0__LPI2C, LPI2C_GetInstance(CM4_0__LPI2C));
2606 }
2607 #endif
2608
2609 #if defined(CM4__LPI2C)
2610 /* Implementation of CM4__LPI2C handler named in startup code. */
2611 void M4_LPI2C_DriverIRQHandler(void);
M4_LPI2C_DriverIRQHandler(void)2612 void M4_LPI2C_DriverIRQHandler(void)
2613 {
2614 LPI2C_CommonIRQHandler(CM4__LPI2C, LPI2C_GetInstance(CM4__LPI2C));
2615 }
2616 #endif
2617
2618 #if defined(CM4_1__LPI2C)
2619 /* Implementation of CM4_1__LPI2C handler named in startup code. */
2620 void M4_1_LPI2C_DriverIRQHandler(void);
M4_1_LPI2C_DriverIRQHandler(void)2621 void M4_1_LPI2C_DriverIRQHandler(void)
2622 {
2623 LPI2C_CommonIRQHandler(CM4_1__LPI2C, LPI2C_GetInstance(CM4_1__LPI2C));
2624 }
2625 #endif
2626
2627 #if defined(DMA__LPI2C0)
2628 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2629 void DMA_I2C0_INT_DriverIRQHandler(void);
DMA_I2C0_INT_DriverIRQHandler(void)2630 void DMA_I2C0_INT_DriverIRQHandler(void)
2631 {
2632 LPI2C_CommonIRQHandler(DMA__LPI2C0, LPI2C_GetInstance(DMA__LPI2C0));
2633 }
2634 #endif
2635
2636 #if defined(DMA__LPI2C1)
2637 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2638 void DMA_I2C1_INT_DriverIRQHandler(void);
DMA_I2C1_INT_DriverIRQHandler(void)2639 void DMA_I2C1_INT_DriverIRQHandler(void)
2640 {
2641 LPI2C_CommonIRQHandler(DMA__LPI2C1, LPI2C_GetInstance(DMA__LPI2C1));
2642 }
2643 #endif
2644
2645 #if defined(DMA__LPI2C2)
2646 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2647 void DMA_I2C2_INT_DriverIRQHandler(void);
DMA_I2C2_INT_DriverIRQHandler(void)2648 void DMA_I2C2_INT_DriverIRQHandler(void)
2649 {
2650 LPI2C_CommonIRQHandler(DMA__LPI2C2, LPI2C_GetInstance(DMA__LPI2C2));
2651 }
2652 #endif
2653
2654 #if defined(DMA__LPI2C3)
2655 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2656 void DMA_I2C3_INT_DriverIRQHandler(void);
DMA_I2C3_INT_DriverIRQHandler(void)2657 void DMA_I2C3_INT_DriverIRQHandler(void)
2658 {
2659 LPI2C_CommonIRQHandler(DMA__LPI2C3, LPI2C_GetInstance(DMA__LPI2C3));
2660 }
2661 #endif
2662
2663 #if defined(DMA__LPI2C4)
2664 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2665 void DMA_I2C4_INT_DriverIRQHandler(void);
DMA_I2C4_INT_DriverIRQHandler(void)2666 void DMA_I2C4_INT_DriverIRQHandler(void)
2667 {
2668 LPI2C_CommonIRQHandler(DMA__LPI2C4, LPI2C_GetInstance(DMA__LPI2C4));
2669 }
2670 #endif
2671
2672 #if defined(ADMA__LPI2C0)
2673 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2674 void ADMA_I2C0_INT_DriverIRQHandler(void);
ADMA_I2C0_INT_DriverIRQHandler(void)2675 void ADMA_I2C0_INT_DriverIRQHandler(void)
2676 {
2677 LPI2C_CommonIRQHandler(ADMA__LPI2C0, LPI2C_GetInstance(ADMA__LPI2C0));
2678 }
2679 #endif
2680
2681 #if defined(ADMA__LPI2C1)
2682 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2683 void ADMA_I2C1_INT_DriverIRQHandler(void);
ADMA_I2C1_INT_DriverIRQHandler(void)2684 void ADMA_I2C1_INT_DriverIRQHandler(void)
2685 {
2686 LPI2C_CommonIRQHandler(ADMA__LPI2C1, LPI2C_GetInstance(ADMA__LPI2C1));
2687 }
2688 #endif
2689
2690 #if defined(ADMA__LPI2C2)
2691 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2692 void ADMA_I2C2_INT_DriverIRQHandler(void);
ADMA_I2C2_INT_DriverIRQHandler(void)2693 void ADMA_I2C2_INT_DriverIRQHandler(void)
2694 {
2695 LPI2C_CommonIRQHandler(ADMA__LPI2C2, LPI2C_GetInstance(ADMA__LPI2C2));
2696 }
2697 #endif
2698
2699 #if defined(ADMA__LPI2C3)
2700 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2701 void ADMA_I2C3_INT_DriverIRQHandler(void);
ADMA_I2C3_INT_DriverIRQHandler(void)2702 void ADMA_I2C3_INT_DriverIRQHandler(void)
2703 {
2704 LPI2C_CommonIRQHandler(ADMA__LPI2C3, LPI2C_GetInstance(ADMA__LPI2C3));
2705 }
2706 #endif
2707
2708 #if defined(ADMA__LPI2C4)
2709 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2710 void ADMA_I2C4_INT_DriverIRQHandler(void);
ADMA_I2C4_INT_DriverIRQHandler(void)2711 void ADMA_I2C4_INT_DriverIRQHandler(void)
2712 {
2713 LPI2C_CommonIRQHandler(ADMA__LPI2C4, LPI2C_GetInstance(ADMA__LPI2C4));
2714 }
2715 #endif
2716