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 status_t ret = kStatus_Success;
1025 uint16_t commandBuffer[7];
1026 uint32_t cmdCount = 0U;
1027
1028 /* Check transfer data size in read operation. */
1029 if ((transfer->direction == kLPI2C_Read) &&
1030 (transfer->dataSize > ((size_t)256 * (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1031 {
1032 return kStatus_InvalidArgument;
1033 }
1034
1035 /* Enable the master function and disable the slave function. */
1036 LPI2C_MasterEnable(base, true);
1037 LPI2C_SlaveEnable(base, false);
1038
1039 /* Return an error if the bus is already in use not by us. */
1040 result = LPI2C_CheckForBusyBus(base);
1041 /*
1042 * $Branch Coverage Justification$
1043 * $ref fsl_lpi2c_c_ref_2$
1044 */
1045 if (kStatus_Success == result)
1046 {
1047 /* Clear all flags. */
1048 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1049
1050 /* Turn off auto-stop option. */
1051 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1052
1053 lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
1054 if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1055 {
1056 commandBuffer[cmdCount++] =
1057 (uint16_t)kStartCmd |
1058 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
1059 }
1060
1061 /* Subaddress, MSB first. */
1062 if (0U != transfer->subaddressSize)
1063 {
1064 uint32_t subaddressRemaining = transfer->subaddressSize;
1065 while (0U != subaddressRemaining--)
1066 {
1067 uint8_t subaddressByte = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1068 commandBuffer[cmdCount++] = subaddressByte;
1069 }
1070 }
1071
1072 /* Reads need special handling. */
1073 if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
1074 {
1075 /* Need to send repeated start if switching directions to read. */
1076 if (direction == kLPI2C_Write)
1077 {
1078 commandBuffer[cmdCount++] =
1079 (uint16_t)kStartCmd |
1080 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1081 }
1082 }
1083
1084 /* Send command buffer */
1085 uint32_t index = 0U;
1086 while (0U != cmdCount--)
1087 {
1088 /* Wait until there is room in the fifo. This also checks for errors. */
1089 result = LPI2C_MasterWaitForTxReady(base);
1090 if (kStatus_Success != result)
1091 {
1092 break;
1093 }
1094
1095 /* Write byte into LPI2C master data register. */
1096 base->MTDR = commandBuffer[index];
1097 index++;
1098 }
1099
1100 if (kStatus_Success == result)
1101 {
1102 /* Transmit data. */
1103 if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
1104 {
1105 /* Send Data. */
1106 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
1107 }
1108
1109 /* Receive Data. */
1110 if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
1111 {
1112 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
1113 }
1114 /*
1115 * $Branch Coverage Justification$
1116 * Errors cannot be simulated by software during transmission.(will improve)
1117 */
1118 if (kStatus_Success == result)
1119 {
1120 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1121 {
1122 result = LPI2C_MasterStop(base);
1123 }
1124 }
1125 }
1126
1127 /* Transmit fail */
1128 if (kStatus_Success != result)
1129 {
1130 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1131 {
1132 ret = LPI2C_MasterStop(base);
1133 if (kStatus_Success != ret)
1134 {
1135 result = ret;
1136 }
1137 }
1138 }
1139 }
1140
1141 return result;
1142 }
1143
1144 /*!
1145 * brief Creates a new handle for the LPI2C master non-blocking APIs.
1146 *
1147 * The creation of a handle is for use with the non-blocking APIs. Once a handle
1148 * is created, there is not a corresponding destroy handle. If the user wants to
1149 * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
1150 *
1151 *
1152 * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1153 * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1154 * enable the associated INTMUX IRQ in application.
1155 *
1156 * param base The LPI2C peripheral base address.
1157 * param[out] handle Pointer to the LPI2C master driver handle.
1158 * param callback User provided pointer to the asynchronous callback function.
1159 * param userData User provided pointer to the application callback data.
1160 */
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)1161 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1162 lpi2c_master_handle_t *handle,
1163 lpi2c_master_transfer_callback_t callback,
1164 void *userData)
1165 {
1166 uint32_t instance;
1167
1168 assert(NULL != handle);
1169
1170 /* Clear out the handle. */
1171 (void)memset(handle, 0, sizeof(*handle));
1172
1173 /* Look up instance number */
1174 instance = LPI2C_GetInstance(base);
1175
1176 /* Save base and instance. */
1177 handle->completionCallback = callback;
1178 handle->userData = userData;
1179
1180 /* Save this handle for IRQ use. */
1181 s_lpi2cMasterHandle[instance] = handle;
1182
1183 /* Set irq handler. */
1184 s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1185
1186 /* Clear internal IRQ enables and enable NVIC IRQ. */
1187 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1188
1189 /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1190 In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1191 INTMUX IRQ in application code. */
1192 (void)EnableIRQ(kLpi2cIrqs[instance]);
1193 }
1194
LPI2C_TransferStateMachineSendCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1195 static void LPI2C_TransferStateMachineSendCommand(LPI2C_Type *base,
1196 lpi2c_master_handle_t *handle,
1197 lpi2c_state_machine_param_t *stateParams)
1198 {
1199 assert(stateParams != NULL);
1200 uint16_t sendval;
1201
1202 /* Make sure there is room in the tx fifo for the next command. */
1203 if (0U == (stateParams->txCount)--)
1204 {
1205 stateParams->state_complete = true;
1206 return;
1207 }
1208
1209 /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1210 sendval = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1211 base->MTDR = sendval;
1212 handle->buf++;
1213 handle->buf++;
1214
1215 /* Count down until all commands are sent. */
1216 if (--handle->remainingBytes == 0U)
1217 {
1218 /* Choose next state and set up buffer pointer and count. */
1219 if (0U != handle->transfer.dataSize)
1220 {
1221 /* Either a send or receive transfer is next. */
1222 handle->state = (uint8_t)kTransferDataState;
1223 handle->buf = (uint8_t *)handle->transfer.data;
1224 handle->remainingBytes = (uint16_t)handle->transfer.dataSize;
1225 if (handle->transfer.direction == kLPI2C_Read)
1226 {
1227 /* Disable TX interrupt */
1228 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1229 /* Issue command to receive data. A single write to MTDR can issue read operation of
1230 0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1231 multiple read commands to MTDR until dataSize is reached. */
1232 size_t tmpRxSize = handle->transfer.dataSize;
1233 while (tmpRxSize != 0U)
1234 {
1235 LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1236 /*
1237 * $Branch Coverage Justification$
1238 * The transmission commands will not exceed FIFO SIZE.(will improve)
1239 */
1240 while ((size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) == stateParams->txCount)
1241 {
1242 LPI2C_MasterGetFifoCounts(base, NULL, &stateParams->txCount);
1243 }
1244
1245 if (tmpRxSize > 256U)
1246 {
1247 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1248 tmpRxSize -= 256U;
1249 }
1250 else
1251 {
1252 base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1253 tmpRxSize = 0U;
1254 }
1255 }
1256 }
1257 }
1258 else
1259 {
1260 /* No transfer, so move to stop state. */
1261 handle->state = (uint8_t)kStopState;
1262 }
1263 }
1264 }
1265
LPI2C_TransferStateMachineReadCommand(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1266 static void LPI2C_TransferStateMachineReadCommand(LPI2C_Type *base,
1267 lpi2c_master_handle_t *handle,
1268 lpi2c_state_machine_param_t *stateParams)
1269 {
1270 assert(stateParams != NULL);
1271
1272 /* Make sure there is room in the tx fifo for the read command. */
1273 if (0U == (stateParams->txCount)--)
1274 {
1275 stateParams->state_complete = true;
1276 return;
1277 }
1278
1279 base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(handle->transfer.dataSize - 1U);
1280
1281 /* Move to transfer state. */
1282 handle->state = (uint8_t)kTransferDataState;
1283 if (handle->transfer.direction == kLPI2C_Read)
1284 {
1285 /* Disable TX interrupt */
1286 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1287 }
1288 }
1289
LPI2C_TransferStateMachineTransferData(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams)1290 static void LPI2C_TransferStateMachineTransferData(LPI2C_Type *base,
1291 lpi2c_master_handle_t *handle,
1292 lpi2c_state_machine_param_t *stateParams)
1293 {
1294 assert(stateParams != NULL);
1295
1296 if (handle->transfer.direction == kLPI2C_Write)
1297 {
1298 /* Make sure there is room in the tx fifo. */
1299 if (0U == stateParams->txCount--)
1300 {
1301 stateParams->state_complete = true;
1302 return;
1303 }
1304
1305 /* Put byte to send in fifo. */
1306 base->MTDR = *(handle->buf)++;
1307 }
1308 else
1309 {
1310 /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1311 /* Make sure there is data in the rx fifo. */
1312 if (0U == stateParams->rxCount--)
1313 {
1314 stateParams->state_complete = true;
1315 return;
1316 }
1317
1318 /* Read byte from fifo. */
1319 *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1320 }
1321
1322 /* Move to stop when the transfer is done. */
1323 if (--handle->remainingBytes == 0U)
1324 {
1325 if (handle->transfer.direction == kLPI2C_Write)
1326 {
1327 stateParams->state_complete = true;
1328 }
1329 handle->state = (uint8_t)kStopState;
1330 }
1331 }
1332
LPI2C_TransferStateMachineStopState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1333 static void LPI2C_TransferStateMachineStopState(LPI2C_Type *base,
1334 lpi2c_master_handle_t *handle,
1335 lpi2c_state_machine_param_t *stateParams,
1336 bool *isDone)
1337 {
1338 assert(stateParams != NULL);
1339
1340 /* Only issue a stop transition if the caller requested it. */
1341 if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1342 {
1343 /* Make sure there is room in the tx fifo for the stop command. */
1344 if (0U == (stateParams->txCount)--)
1345 {
1346 stateParams->state_complete = true;
1347 return;
1348 }
1349
1350 base->MTDR = (uint32_t)kStopCmd;
1351 }
1352 else
1353 {
1354 /* If all data is read and no stop flag is required to send, we are done. */
1355 if (handle->transfer.direction == kLPI2C_Read)
1356 {
1357 *isDone = true;
1358 }
1359 stateParams->state_complete = true;
1360 }
1361 handle->state = (uint8_t)kWaitForCompletionState;
1362 }
1363
LPI2C_TransferStateMachineWaitState(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_state_machine_param_t * stateParams,bool * isDone)1364 static void LPI2C_TransferStateMachineWaitState(LPI2C_Type *base,
1365 lpi2c_master_handle_t *handle,
1366 lpi2c_state_machine_param_t *stateParams,
1367 bool *isDone)
1368 {
1369 assert(stateParams != NULL);
1370
1371 if ((handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1372 {
1373 /* We stay in this state until the stop state is detected. */
1374 if (0U != ((stateParams->status) & (uint32_t)kLPI2C_MasterStopDetectFlag))
1375 {
1376 *isDone = true;
1377 }
1378 }
1379 else
1380 {
1381 /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1382 are all send out to bus. */
1383 if ((handle->transfer.direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1384 {
1385 /* We stay in this state until the data is sent out to bus. */
1386 *isDone = true;
1387 }
1388 }
1389 stateParams->state_complete = true;
1390 }
1391
1392 /*!
1393 * @brief Execute states until FIFOs are exhausted.
1394 * @param handle Master nonblocking driver handle.
1395 * @param[out] isDone Set to true if the transfer has completed.
1396 * @retval #kStatus_Success
1397 * @retval #kStatus_LPI2C_PinLowTimeout
1398 * @retval #kStatus_LPI2C_ArbitrationLost
1399 * @retval #kStatus_LPI2C_Nak
1400 * @retval #kStatus_LPI2C_FifoError
1401 */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)1402 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1403 {
1404 assert(NULL != base && NULL != handle && NULL != isDone);
1405
1406 status_t result = kStatus_Success;
1407 lpi2c_state_machine_param_t stateParams;
1408 (void)memset(&stateParams, 0, sizeof(stateParams));
1409
1410 stateParams.state_complete = false;
1411
1412 /* Set default isDone return value. */
1413 *isDone = false;
1414
1415 /* Check for errors. */
1416 stateParams.status = LPI2C_MasterGetStatusFlags(base);
1417
1418 /* Get fifo counts. */
1419 LPI2C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
1420
1421 /* For the last byte, nack flag is expected.
1422 Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1423 in case FIFO is emptied when stop command has not been sent. */
1424 if (handle->remainingBytes == 0U)
1425 {
1426 /* When data size is not zero which means it is not only one byte of address is sent, and */
1427 /* when the txfifo is empty, or have one byte which is the stop command, then the nack status can be ignored. */
1428 if (((handle->transfer).dataSize != 0U) &&
1429 ((stateParams.txCount == 0U) ||
1430 (((stateParams.txCount) == 1U) && (handle->state == (uint8_t)kWaitForCompletionState) &&
1431 (((handle->transfer).flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U))))
1432 {
1433 (stateParams.status) &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1434 }
1435 }
1436
1437 result = LPI2C_MasterCheckAndClearError(base, stateParams.status);
1438
1439 if (kStatus_Success == result)
1440 {
1441 /* Compute room in tx fifo */
1442 stateParams.txCount = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base) - stateParams.txCount;
1443
1444 while (!stateParams.state_complete)
1445 {
1446 /* Execute the state. */
1447 /*
1448 * $Branch Coverage Justification$
1449 * $ref fsl_lpi2c_c_ref_1$
1450 */
1451 switch (handle->state)
1452 {
1453 case (uint8_t)kSendCommandState:
1454 LPI2C_TransferStateMachineSendCommand(base, handle, &stateParams);
1455 break;
1456
1457 case (uint8_t)kIssueReadCommandState:
1458 LPI2C_TransferStateMachineReadCommand(base, handle, &stateParams);
1459 break;
1460
1461 case (uint8_t)kTransferDataState:
1462 LPI2C_TransferStateMachineTransferData(base, handle, &stateParams);
1463 break;
1464
1465 case (uint8_t)kStopState:
1466 LPI2C_TransferStateMachineStopState(base, handle, &stateParams, isDone);
1467 break;
1468
1469 case (uint8_t)kWaitForCompletionState:
1470 LPI2C_TransferStateMachineWaitState(base, handle, &stateParams, isDone);
1471 break;
1472 default:
1473 assert(false);
1474 break;
1475 }
1476 }
1477 }
1478 return result;
1479 }
1480
1481 /*!
1482 * @brief Prepares the transfer state machine and fills in the command buffer.
1483 * @param handle Master nonblocking driver handle.
1484 */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)1485 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1486 {
1487 lpi2c_master_transfer_t *xfer = &handle->transfer;
1488
1489 /* Handle no start option. */
1490 if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1491 {
1492 if (xfer->direction == kLPI2C_Read)
1493 {
1494 /* Need to issue read command first. */
1495 handle->state = (uint8_t)kIssueReadCommandState;
1496 }
1497 else
1498 {
1499 /* Start immediately in the data transfer state. */
1500 handle->state = (uint8_t)kTransferDataState;
1501 }
1502
1503 handle->buf = (uint8_t *)xfer->data;
1504 handle->remainingBytes = (uint16_t)xfer->dataSize;
1505 }
1506 else
1507 {
1508 uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
1509 uint32_t cmdCount = 0U;
1510
1511 /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1512 /* data transfer direction. */
1513 lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1514
1515 /* Start command. */
1516 cmd[cmdCount++] =
1517 (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1518
1519 /* Subaddress, MSB first. */
1520 if (0U != xfer->subaddressSize)
1521 {
1522 uint32_t subaddressRemaining = xfer->subaddressSize;
1523 while (0U != (subaddressRemaining--))
1524 {
1525 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1526 cmd[cmdCount++] = subaddressByte;
1527 }
1528 }
1529
1530 /* Reads need special handling. */
1531 if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1532 {
1533 /* Need to send repeated start if switching directions to read. */
1534 if (direction == kLPI2C_Write)
1535 {
1536 cmd[cmdCount++] = (uint16_t)kStartCmd |
1537 (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1538 }
1539 }
1540
1541 /* Set up state machine for transferring the commands. */
1542 handle->state = (uint8_t)kSendCommandState;
1543 handle->remainingBytes = (uint16_t)cmdCount;
1544 handle->buf = (uint8_t *)&handle->commandBuffer;
1545 }
1546 }
1547
1548 /*!
1549 * brief Performs a non-blocking transaction on the I2C bus.
1550 *
1551 * param base The LPI2C peripheral base address.
1552 * param handle Pointer to the LPI2C master driver handle.
1553 * param transfer The pointer to the transfer descriptor.
1554 * retval #kStatus_Success The transaction was started successfully.
1555 * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1556 * transaction is already in progress.
1557 */
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)1558 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1559 lpi2c_master_handle_t *handle,
1560 lpi2c_master_transfer_t *transfer)
1561 {
1562 assert(NULL != handle);
1563 assert(NULL != transfer);
1564 assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1565
1566 status_t result;
1567
1568 /* Check transfer data size in read operation. */
1569 if ((transfer->direction == kLPI2C_Read) &&
1570 (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1571 {
1572 return kStatus_InvalidArgument;
1573 }
1574
1575 /* Return busy if another transaction is in progress. */
1576 if (handle->state != (uint8_t)kIdleState)
1577 {
1578 result = kStatus_LPI2C_Busy;
1579 }
1580 else
1581 {
1582 result = LPI2C_CheckForBusyBus(base);
1583 }
1584
1585 if ((status_t)kStatus_Success == result)
1586 {
1587 /* Enable the master function and disable the slave function. */
1588 LPI2C_MasterEnable(base, true);
1589 LPI2C_SlaveEnable(base, false);
1590
1591 /* Disable LPI2C IRQ sources while we configure stuff. */
1592 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1593
1594 /* Reset FIFO in case there are data. */
1595 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1596
1597 /* Save transfer into handle. */
1598 handle->transfer = *transfer;
1599
1600 /* Generate commands to send. */
1601 LPI2C_InitTransferStateMachine(handle);
1602
1603 /* Clear all flags. */
1604 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1605
1606 /* Turn off auto-stop option. */
1607 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1608
1609 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1610 LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1611 }
1612
1613 return result;
1614 }
1615
1616 /*!
1617 * brief Returns number of bytes transferred so far.
1618 * param base The LPI2C peripheral base address.
1619 * param handle Pointer to the LPI2C master driver handle.
1620 * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1621 * retval #kStatus_Success
1622 * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1623 */
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)1624 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1625 {
1626 status_t result = kStatus_Success;
1627
1628 assert(NULL != handle);
1629
1630 if (NULL == count)
1631 {
1632 result = kStatus_InvalidArgument;
1633 }
1634
1635 /* Catch when there is not an active transfer. */
1636 else if (handle->state == (uint8_t)kIdleState)
1637 {
1638 *count = 0;
1639 result = kStatus_NoTransferInProgress;
1640 }
1641 else
1642 {
1643 uint8_t state;
1644 uint16_t remainingBytes;
1645 uint32_t dataSize;
1646
1647 /* Cache some fields with IRQs disabled. This ensures all field values */
1648 /* are synchronized with each other during an ongoing transfer. */
1649 uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1650 LPI2C_MasterDisableInterrupts(base, irqs);
1651 state = handle->state;
1652 remainingBytes = handle->remainingBytes;
1653 dataSize = handle->transfer.dataSize;
1654 LPI2C_MasterEnableInterrupts(base, irqs);
1655
1656 /* Get transfer count based on current transfer state. */
1657 switch (state)
1658 {
1659 case (uint8_t)kIdleState:
1660 case (uint8_t)kSendCommandState:
1661 case (uint8_t)
1662 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1663 *count = 0;
1664 break;
1665
1666 case (uint8_t)kTransferDataState:
1667 *count = dataSize - remainingBytes;
1668 break;
1669
1670 case (uint8_t)kStopState:
1671 case (uint8_t)kWaitForCompletionState:
1672 default:
1673 *count = dataSize;
1674 break;
1675 }
1676 }
1677
1678 return result;
1679 }
1680
1681 /*!
1682 * brief Terminates a non-blocking LPI2C master transmission early.
1683 *
1684 * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1685 * LPI2C peripheral's IRQ priority.
1686 *
1687 * param base The LPI2C peripheral base address.
1688 * param handle Pointer to the LPI2C master driver handle.
1689 */
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1690 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1691 {
1692 if (handle->state != (uint8_t)kIdleState)
1693 {
1694 /* Disable internal IRQ enables. */
1695 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1696
1697 /* Reset fifos. */
1698 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1699
1700 /* If master is still busy and has not send out stop signal yet. */
1701 if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1702 (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1703 {
1704 /* Send a stop command to finalize the transfer. */
1705 base->MTDR = (uint32_t)kStopCmd;
1706 }
1707
1708 /* Reset handle. */
1709 handle->state = (uint8_t)kIdleState;
1710 }
1711 }
1712
1713 /*!
1714 * brief Reusable routine to handle master interrupts.
1715 * note This function does not need to be called unless you are reimplementing the
1716 * nonblocking API's interrupt handler routines to add special functionality.
1717 * param base The LPI2C peripheral base address.
1718 * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1719 */
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,void * lpi2cMasterHandle)1720 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, void *lpi2cMasterHandle)
1721 {
1722 assert(lpi2cMasterHandle != NULL);
1723
1724 lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1725 bool isDone = false;
1726 status_t result;
1727
1728 /* Don't do anything if we don't have a valid handle. */
1729 if (NULL != handle)
1730 {
1731 if (handle->state != (uint8_t)kIdleState)
1732 {
1733 result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1734
1735 if ((result != kStatus_Success) || isDone)
1736 {
1737 /* Handle error, terminate xfer */
1738 if (result != kStatus_Success)
1739 {
1740 LPI2C_MasterTransferAbort(base, handle);
1741 }
1742
1743 /* Disable internal IRQ enables. */
1744 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1745
1746 /* Set handle to idle state. */
1747 handle->state = (uint8_t)kIdleState;
1748
1749 /* Invoke callback. */
1750 if (NULL != handle->completionCallback)
1751 {
1752 handle->completionCallback(base, handle, result, handle->userData);
1753 }
1754 }
1755 }
1756 }
1757 }
1758
1759 /*!
1760 * brief Provides a default configuration for the LPI2C slave peripheral.
1761 *
1762 * This function provides the following default configuration for the LPI2C slave peripheral:
1763 * code
1764 * slaveConfig->enableSlave = true;
1765 * slaveConfig->address0 = 0U;
1766 * slaveConfig->address1 = 0U;
1767 * slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1768 * slaveConfig->filterDozeEnable = true;
1769 * slaveConfig->filterEnable = true;
1770 * slaveConfig->enableGeneralCall = false;
1771 * slaveConfig->sclStall.enableAck = false;
1772 * slaveConfig->sclStall.enableTx = true;
1773 * slaveConfig->sclStall.enableRx = true;
1774 * slaveConfig->sclStall.enableAddress = true;
1775 * slaveConfig->ignoreAck = false;
1776 * slaveConfig->enableReceivedAddressRead = false;
1777 * slaveConfig->sdaGlitchFilterWidth_ns = 0;
1778 * slaveConfig->sclGlitchFilterWidth_ns = 0;
1779 * slaveConfig->dataValidDelay_ns = 0;
1780 * slaveConfig->clockHoldTime_ns = 0;
1781 * endcode
1782 *
1783 * After calling this function, override any settings to customize the configuration,
1784 * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1785 * address0 member of the configuration structure with the desired slave address.
1786 *
1787 * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1788 * #lpi2c_slave_config_t.
1789 */
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1790 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1791 {
1792 /* Initializes the configure structure to zero. */
1793 (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1794
1795 slaveConfig->enableSlave = true;
1796 slaveConfig->address0 = 0U;
1797 slaveConfig->address1 = 0U;
1798 slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1799 slaveConfig->filterDozeEnable = true;
1800 slaveConfig->filterEnable = true;
1801 slaveConfig->enableGeneralCall = false;
1802 slaveConfig->sclStall.enableAck = false;
1803 slaveConfig->sclStall.enableTx = true;
1804 slaveConfig->sclStall.enableRx = true;
1805 slaveConfig->sclStall.enableAddress = false;
1806 slaveConfig->ignoreAck = false;
1807 slaveConfig->enableReceivedAddressRead = false;
1808 slaveConfig->sdaGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
1809 slaveConfig->sclGlitchFilterWidth_ns = 0U; /* Set to 0 to disable the function */
1810 slaveConfig->dataValidDelay_ns = 0U;
1811 /* When enabling the slave tx SCL stall, set the default clock hold time to 250ns according
1812 to I2C spec for standard mode baudrate(100k). User can manually change it to 100ns or 50ns
1813 for fast-mode(400k) or fast-mode+(1m). */
1814 slaveConfig->clockHoldTime_ns = 250U;
1815 }
1816
1817 /*!
1818 * brief Initializes the LPI2C slave peripheral.
1819 *
1820 * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1821 * provided configuration.
1822 *
1823 * param base The LPI2C peripheral base address.
1824 * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1825 * that you can override.
1826 * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1827 * data valid delay, and clock hold time.
1828 */
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1829 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1830 {
1831 uint32_t tmpReg;
1832 uint32_t tmpCycle;
1833
1834 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1835
1836 uint32_t instance = LPI2C_GetInstance(base);
1837
1838 /* Ungate the clock. */
1839 (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1840 #if defined(LPI2C_PERIPH_CLOCKS)
1841 /* Ungate the functional clock in initialize function. */
1842 CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1843 #endif
1844
1845 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1846
1847 #if defined(LPI2C_RESETS_ARRAY)
1848 RESET_ReleasePeripheralReset(s_lpi2cResets[LPI2C_GetInstance(base)]);
1849 #endif
1850
1851 /* Restore to reset conditions. */
1852 LPI2C_SlaveReset(base);
1853
1854 /* Configure peripheral. */
1855 base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1856
1857 base->SCFGR1 =
1858 LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1859 LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1860 LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1861 LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1862 LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1863
1864 /* Calculate SDA filter width. The width is equal to FILTSDA+3 cycles of functional clock.
1865 And set FILTSDA to 0 disables the fileter, so the min value is 4. */
1866 tmpReg = LPI2C_SCFGR2_FILTSDA(
1867 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns, 4U,
1868 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT) + 3U, 0U) -
1869 3U);
1870
1871 /* Calculate SDL filter width. The width is equal to FILTSCL+3 cycles of functional clock.
1872 And set FILTSCL to 0 disables the fileter, so the min value is 4. */
1873 tmpCycle = LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns, 4U,
1874 (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT) + 3U, 0U);
1875 tmpReg |= LPI2C_SCFGR2_FILTSCL(tmpCycle - 3U);
1876
1877 /* Calculate data valid time. The time is equal to FILTSCL+DATAVD+3 cycles of functional clock.
1878 So the min value is FILTSCL+3. */
1879 tmpReg |= LPI2C_SCFGR2_DATAVD(
1880 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns, tmpCycle,
1881 tmpCycle + (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 0U) -
1882 tmpCycle);
1883
1884 /* Calculate clock hold time. The time is equal to CLKHOLD+3 cycles of functional clock.
1885 So the min value is 3. */
1886 base->SCFGR2 =
1887 tmpReg | LPI2C_SCFGR2_CLKHOLD(
1888 LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns, 3U,
1889 (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT) + 3U, 0U) -
1890 3U);
1891
1892 /* Save SCR to last so we don't enable slave until it is configured */
1893 base->SCR = LPI2C_SCR_FILTDZ(!slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1894 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1895 }
1896
1897 /*!
1898 * brief Deinitializes the LPI2C slave peripheral.
1899 *
1900 * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1901 * reset to restore the peripheral to reset conditions.
1902 *
1903 * param base The LPI2C peripheral base address.
1904 */
LPI2C_SlaveDeinit(LPI2C_Type * base)1905 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1906 {
1907 LPI2C_SlaveReset(base);
1908
1909 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1910
1911 uint32_t instance = LPI2C_GetInstance(base);
1912
1913 /* Gate the clock. */
1914 (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1915
1916 #if defined(LPI2C_PERIPH_CLOCKS)
1917 /* Gate the functional clock. */
1918 CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1919 #endif
1920
1921 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1922 }
1923
1924 /*!
1925 * @brief Convert provided flags to status code, and clear any errors if present.
1926 * @param base The LPI2C peripheral base address.
1927 * @param status Current status flags value that will be checked.
1928 * @retval #kStatus_Success
1929 * @retval #kStatus_LPI2C_BitError
1930 * @retval #kStatus_LPI2C_FifoError
1931 */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1932 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1933 {
1934 status_t result = kStatus_Success;
1935
1936 flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1937 if (0U != flags)
1938 {
1939 /*
1940 * $Branch Coverage Justification$
1941 * It is hard to simulate bitError in automation test environment, need interference on bus.(will improve)
1942 */
1943 if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1944 {
1945 result = kStatus_LPI2C_BitError;
1946 }
1947 else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1948 {
1949 result = kStatus_LPI2C_FifoError;
1950 }
1951 else
1952 {
1953 ; /* Intentional empty */
1954 }
1955
1956 /* Clear the errors. */
1957 LPI2C_SlaveClearStatusFlags(base, flags);
1958 }
1959 else
1960 {
1961 ; /* Intentional empty */
1962 }
1963
1964 return result;
1965 }
1966
1967 /*!
1968 * brief Performs a polling send transfer on the I2C bus.
1969 *
1970 * param base The LPI2C peripheral base address.
1971 * param txBuff The pointer to the data to be transferred.
1972 * param txSize The length in bytes of the data to be transferred.
1973 * param[out] actualTxSize
1974 * return Error or success status returned by API.
1975 */
LPI2C_SlaveSend(LPI2C_Type * base,void * txBuff,size_t txSize,size_t * actualTxSize)1976 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1977 {
1978 status_t result = kStatus_Success;
1979 uint8_t *buf = (uint8_t *)txBuff;
1980 size_t remaining = txSize;
1981
1982 assert(NULL != txBuff);
1983
1984 #if I2C_RETRY_TIMES != 0U
1985 uint32_t waitTimes = I2C_RETRY_TIMES;
1986 #endif
1987
1988 /* Clear stop flag. */
1989 LPI2C_SlaveClearStatusFlags(base,
1990 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1991
1992 while (0U != remaining)
1993 {
1994 uint32_t flags;
1995
1996 /* Wait until we can transmit. */
1997 do
1998 {
1999 /* Check for errors */
2000 flags = LPI2C_SlaveGetStatusFlags(base);
2001 result = LPI2C_SlaveCheckAndClearError(base, flags);
2002 if (kStatus_Success != result)
2003 {
2004 if (NULL != actualTxSize)
2005 {
2006 *actualTxSize = txSize - remaining;
2007 }
2008 break;
2009 }
2010 #if I2C_RETRY_TIMES != 0U
2011 waitTimes--;
2012 } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2013 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2014 (0U != waitTimes));
2015 if (0U == waitTimes)
2016 {
2017 result = kStatus_LPI2C_Timeout;
2018 }
2019 #else
2020 } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2021 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2022 #endif
2023
2024 if (kStatus_Success != result)
2025 {
2026 break;
2027 }
2028
2029 /* Send a byte. */
2030 if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2031 {
2032 base->STDR = *buf++;
2033 --remaining;
2034 }
2035
2036 /* Exit loop if we see a stop or restart in transfer*/
2037 /*
2038 * $Branch Coverage Justification$
2039 * $ref fsl_lpi2c_c_ref_3$
2040 */
2041 if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2042 (remaining != 0U))
2043 {
2044 LPI2C_SlaveClearStatusFlags(
2045 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2046 break;
2047 }
2048 }
2049
2050 if (NULL != actualTxSize)
2051 {
2052 *actualTxSize = txSize - remaining;
2053 }
2054
2055 return result;
2056 }
2057
2058 /*!
2059 * brief Performs a polling receive transfer on the I2C bus.
2060 *
2061 * param base The LPI2C peripheral base address.
2062 * param rxBuff The pointer to the data to be transferred.
2063 * param rxSize The length in bytes of the data to be transferred.
2064 * param[out] actualRxSize
2065 * return Error or success status returned by API.
2066 */
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)2067 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
2068 {
2069 status_t result = kStatus_Success;
2070 uint8_t *buf = (uint8_t *)rxBuff;
2071 size_t remaining = rxSize;
2072
2073 assert(NULL != rxBuff);
2074
2075 #if I2C_RETRY_TIMES != 0U
2076 uint32_t waitTimes = I2C_RETRY_TIMES;
2077 #endif
2078
2079 /* Clear stop flag. */
2080 LPI2C_SlaveClearStatusFlags(base,
2081 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2082
2083 while (0U != remaining)
2084 {
2085 uint32_t flags;
2086
2087 /* Wait until we can receive. */
2088 do
2089 {
2090 /* Check for errors */
2091 flags = LPI2C_SlaveGetStatusFlags(base);
2092 result = LPI2C_SlaveCheckAndClearError(base, flags);
2093 if (kStatus_Success != result)
2094 {
2095 if (NULL != actualRxSize)
2096 {
2097 *actualRxSize = rxSize - remaining;
2098 }
2099 break;
2100 }
2101 #if I2C_RETRY_TIMES != 0U
2102 waitTimes--;
2103 } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2104 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2105 (0U != waitTimes));
2106 if (0U == waitTimes)
2107 {
2108 result = kStatus_LPI2C_Timeout;
2109 }
2110 #else
2111 } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
2112 (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
2113 #endif
2114
2115 if ((status_t)kStatus_Success != result)
2116 {
2117 break;
2118 }
2119
2120 /* Receive a byte. */
2121 if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2122 {
2123 *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
2124 --remaining;
2125 }
2126
2127 /* Exit loop if we see a stop or restart */
2128 /*
2129 * $Branch Coverage Justification$
2130 * $ref fsl_lpi2c_c_ref_3$
2131 */
2132 if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
2133 (remaining != 0U))
2134 {
2135 LPI2C_SlaveClearStatusFlags(
2136 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
2137 break;
2138 }
2139 }
2140
2141 if (NULL != actualRxSize)
2142 {
2143 *actualRxSize = rxSize - remaining;
2144 }
2145
2146 return result;
2147 }
2148
2149 /*!
2150 * brief Creates a new handle for the LPI2C slave non-blocking APIs.
2151 *
2152 * The creation of a handle is for use with the non-blocking APIs. Once a handle
2153 * is created, there is not a corresponding destroy handle. If the user wants to
2154 * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
2155 *
2156 * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
2157 * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
2158 * enable the associated INTMUX IRQ in application.
2159
2160 * param base The LPI2C peripheral base address.
2161 * param[out] handle Pointer to the LPI2C slave driver handle.
2162 * param callback User provided pointer to the asynchronous callback function.
2163 * param userData User provided pointer to the application callback data.
2164 */
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)2165 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
2166 lpi2c_slave_handle_t *handle,
2167 lpi2c_slave_transfer_callback_t callback,
2168 void *userData)
2169 {
2170 uint32_t instance;
2171
2172 assert(NULL != handle);
2173
2174 /* Clear out the handle. */
2175 (void)memset(handle, 0, sizeof(*handle));
2176
2177 /* Look up instance number */
2178 instance = LPI2C_GetInstance(base);
2179
2180 /* Save base and instance. */
2181 handle->callback = callback;
2182 handle->userData = userData;
2183
2184 /* Save this handle for IRQ use. */
2185 s_lpi2cSlaveHandle[instance] = handle;
2186
2187 /* Set irq handler. */
2188 s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
2189
2190 /* Clear internal IRQ enables and enable NVIC IRQ. */
2191 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2192 (void)EnableIRQ(kLpi2cIrqs[instance]);
2193
2194 /* Nack by default. */
2195 base->STAR = LPI2C_STAR_TXNACK_MASK;
2196 }
2197
2198 /*!
2199 * brief Starts accepting slave transfers.
2200 *
2201 * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
2202 * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2203 * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
2204 * from the interrupt context.
2205 *
2206 * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
2207 * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
2208 * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
2209 * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
2210 * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
2211 * a convenient way to enable all events.
2212 *
2213 * param base The LPI2C peripheral base address.
2214 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2215 * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
2216 * which events to send to the callback. Other accepted values are 0 to get a default set of
2217 * only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
2218 *
2219 * retval #kStatus_Success Slave transfers were successfully started.
2220 * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
2221 */
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)2222 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
2223 {
2224 status_t result = kStatus_Success;
2225
2226 assert(NULL != handle);
2227
2228 /* Return busy if another transaction is in progress. */
2229 if (handle->isBusy)
2230 {
2231 result = kStatus_LPI2C_Busy;
2232 }
2233 else
2234 {
2235 /* Enable the slave function and disable the master function. */
2236 LPI2C_MasterEnable(base, false);
2237 LPI2C_SlaveEnable(base, true);
2238 /* Return an error if the bus is already in use not by us. */
2239 uint32_t status = LPI2C_SlaveGetStatusFlags(base);
2240 /*
2241 * $Branch Coverage Justification$
2242 * $ref fsl_lpi2c_c_ref_2$
2243 */
2244 if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
2245 {
2246 result = kStatus_LPI2C_Busy;
2247 }
2248 }
2249
2250 if ((status_t)kStatus_Success == result)
2251 {
2252 /* Disable LPI2C IRQ sources while we configure stuff. */
2253 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2254
2255 /* Clear transfer in handle. */
2256 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2257
2258 /* Record that we're busy. */
2259 handle->isBusy = true;
2260
2261 /* Set up event mask. tx and rx are always enabled. */
2262 handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
2263
2264 /* Ack by default. */
2265 base->STAR = 0U;
2266
2267 /* Clear all flags. */
2268 LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2269
2270 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2271 LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2272 }
2273
2274 return result;
2275 }
2276
2277 /*!
2278 * brief Gets the slave transfer status during a non-blocking transfer.
2279 * param base The LPI2C peripheral base address.
2280 * param handle Pointer to i2c_slave_handle_t structure.
2281 * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2282 * required.
2283 * retval #kStatus_Success
2284 * retval #kStatus_NoTransferInProgress
2285 */
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)2286 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2287 {
2288 status_t status = kStatus_Success;
2289
2290 assert(NULL != handle);
2291
2292 if (count == NULL)
2293 {
2294 status = kStatus_InvalidArgument;
2295 }
2296
2297 /* Catch when there is not an active transfer. */
2298 else if (!handle->isBusy)
2299 {
2300 *count = 0;
2301 status = kStatus_NoTransferInProgress;
2302 }
2303
2304 /* For an active transfer, just return the count from the handle. */
2305 else
2306 {
2307 *count = handle->transferredCount;
2308 }
2309
2310 return status;
2311 }
2312
2313 /*!
2314 * brief Aborts the slave non-blocking transfers.
2315 * note This API could be called at any time to stop slave for handling the bus events.
2316 * param base The LPI2C peripheral base address.
2317 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2318 */
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2319 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2320 {
2321 assert(NULL != handle);
2322
2323 /* Return idle if no transaction is in progress. */
2324 if (handle->isBusy)
2325 {
2326 /* Disable LPI2C IRQ sources. */
2327 LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2328
2329 /* Nack by default. */
2330 base->STAR = LPI2C_STAR_TXNACK_MASK;
2331
2332 /* Reset transfer info. */
2333 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2334
2335 /* We're no longer busy. */
2336 handle->isBusy = false;
2337 }
2338 }
2339
2340 /*!
2341 * brief Reusable routine to handle slave interrupts.
2342 * note This function does not need to be called unless you are reimplementing the
2343 * non blocking API's interrupt handler routines to add special functionality.
2344 * param base The LPI2C peripheral base address.
2345 * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2346 */
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2347 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2348 {
2349 uint32_t flags;
2350 lpi2c_slave_transfer_t *xfer;
2351
2352 /* Check for a valid handle in case of a spurious interrupt. */
2353 if (NULL != handle)
2354 {
2355 xfer = &handle->transfer;
2356
2357 /* Get status flags. */
2358 flags = LPI2C_SlaveGetStatusFlags(base);
2359
2360 if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2361 {
2362 xfer->event = kLPI2C_SlaveCompletionEvent;
2363 xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2364
2365 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2366 {
2367 handle->callback(base, xfer, handle->userData);
2368 }
2369 }
2370 else
2371 {
2372 if (0U !=
2373 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2374 {
2375 xfer->event = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2376 kLPI2C_SlaveRepeatedStartEvent :
2377 kLPI2C_SlaveCompletionEvent;
2378 xfer->receivedAddress = 0U;
2379 xfer->completionStatus = kStatus_Success;
2380 xfer->transferredCount = handle->transferredCount;
2381
2382 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2383 {
2384 handle->isBusy = false;
2385 }
2386
2387 if (handle->wasTransmit)
2388 {
2389 /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2390 /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2391 /* count that the master actually receives. */
2392 --xfer->transferredCount;
2393 handle->wasTransmit = false;
2394 }
2395
2396 /* Clear the flag. */
2397 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2398 (uint32_t)kLPI2C_SlaveStopDetectFlag));
2399
2400 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2401 base->STAR = 0U;
2402
2403 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2404 {
2405 handle->callback(base, xfer, handle->userData);
2406 }
2407
2408 if (0U != (flags & (uint32_t)kLPI2C_SlaveStopDetectFlag))
2409 {
2410 /* Clean up transfer info on completion, after the callback has been invoked. */
2411 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2412 }
2413 }
2414 if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2415 {
2416 xfer->event = kLPI2C_SlaveAddressMatchEvent;
2417 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2418
2419 /* Update handle status to busy because slave is addressed. */
2420 handle->isBusy = true;
2421 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2422 {
2423 handle->callback(base, xfer, handle->userData);
2424 }
2425 }
2426 if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2427 {
2428 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2429
2430 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2431 {
2432 handle->callback(base, xfer, handle->userData);
2433 }
2434 }
2435
2436 /* Handle transmit and receive. */
2437 if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2438 {
2439 handle->wasTransmit = true;
2440
2441 /* If we're out of data, invoke callback to get more. */
2442 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2443 {
2444 xfer->event = kLPI2C_SlaveTransmitEvent;
2445 if (NULL != handle->callback)
2446 {
2447 handle->callback(base, xfer, handle->userData);
2448 }
2449
2450 /* Clear the transferred count now that we have a new buffer. */
2451 handle->transferredCount = 0U;
2452 }
2453
2454 /* Transmit a byte. */
2455 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2456 {
2457 base->STDR = *xfer->data++;
2458 --xfer->dataSize;
2459 ++handle->transferredCount;
2460 }
2461 }
2462 if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2463 {
2464 /* If we're out of room in the buffer, invoke callback to get another. */
2465 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2466 {
2467 xfer->event = kLPI2C_SlaveReceiveEvent;
2468 if (NULL != handle->callback)
2469 {
2470 handle->callback(base, xfer, handle->userData);
2471 }
2472
2473 /* Clear the transferred count now that we have a new buffer. */
2474 handle->transferredCount = 0U;
2475 }
2476
2477 /* Receive a byte. */
2478 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2479 {
2480 *xfer->data++ = (uint8_t)base->SRDR;
2481 --xfer->dataSize;
2482 ++handle->transferredCount;
2483 }
2484 else
2485 {
2486 /* We don't have any room to receive more data, so send a nack. */
2487 base->STAR = LPI2C_STAR_TXNACK_MASK;
2488 }
2489 }
2490 }
2491 }
2492 }
2493
2494 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2495 /*!
2496 * @brief Shared IRQ handler that can call both master and slave ISRs.
2497 *
2498 * The master and slave ISRs are called through function pointers in order to decouple
2499 * this code from the ISR functions. Without this, the linker would always pull in both
2500 * ISRs and every function they call, even if only the functional API was used.
2501 *
2502 * @param base The LPI2C peripheral base address.
2503 * @param instance The LPI2C peripheral instance number.
2504 */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)2505 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2506 {
2507 /* Check for master IRQ. */
2508 if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2509 {
2510 /* Master mode. */
2511 s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
2512 }
2513
2514 /* Check for slave IRQ. */
2515 if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2516 {
2517 /* Slave mode. */
2518 s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
2519 }
2520 SDK_ISR_EXIT_BARRIER;
2521 }
2522 #endif
2523
2524 #if defined(LPI2C0)
2525 /* Implementation of LPI2C0 handler named in startup code. */
2526 void LPI2C0_DriverIRQHandler(void);
LPI2C0_DriverIRQHandler(void)2527 void LPI2C0_DriverIRQHandler(void)
2528 {
2529 LPI2C_CommonIRQHandler(LPI2C0, 0U);
2530 }
2531 #endif
2532
2533 #if defined(LPI2C1)
2534 /* Implementation of LPI2C1 handler named in startup code. */
2535 void LPI2C1_DriverIRQHandler(void);
LPI2C1_DriverIRQHandler(void)2536 void LPI2C1_DriverIRQHandler(void)
2537 {
2538 LPI2C_CommonIRQHandler(LPI2C1, 1U);
2539 }
2540 #endif
2541
2542 #if defined(LPI2C2)
2543 /* Implementation of LPI2C2 handler named in startup code. */
2544 void LPI2C2_DriverIRQHandler(void);
LPI2C2_DriverIRQHandler(void)2545 void LPI2C2_DriverIRQHandler(void)
2546 {
2547 LPI2C_CommonIRQHandler(LPI2C2, 2U);
2548 }
2549 #endif
2550
2551 #if defined(LPI2C3)
2552 /* Implementation of LPI2C3 handler named in startup code. */
2553 void LPI2C3_DriverIRQHandler(void);
LPI2C3_DriverIRQHandler(void)2554 void LPI2C3_DriverIRQHandler(void)
2555 {
2556 LPI2C_CommonIRQHandler(LPI2C3, 3U);
2557 }
2558 #endif
2559
2560 #if defined(LPI2C4)
2561 /* Implementation of LPI2C4 handler named in startup code. */
2562 void LPI2C4_DriverIRQHandler(void);
LPI2C4_DriverIRQHandler(void)2563 void LPI2C4_DriverIRQHandler(void)
2564 {
2565 LPI2C_CommonIRQHandler(LPI2C4, 4U);
2566 }
2567 #endif
2568
2569 #if defined(LPI2C5)
2570 /* Implementation of LPI2C5 handler named in startup code. */
2571 void LPI2C5_DriverIRQHandler(void);
LPI2C5_DriverIRQHandler(void)2572 void LPI2C5_DriverIRQHandler(void)
2573 {
2574 LPI2C_CommonIRQHandler(LPI2C5, 5U);
2575 }
2576 #endif
2577
2578 #if defined(LPI2C6)
2579 /* Implementation of LPI2C6 handler named in startup code. */
2580 void LPI2C6_DriverIRQHandler(void);
LPI2C6_DriverIRQHandler(void)2581 void LPI2C6_DriverIRQHandler(void)
2582 {
2583 LPI2C_CommonIRQHandler(LPI2C6, 6U);
2584 }
2585 #endif
2586
2587 #if defined(CM4_0__LPI2C)
2588 /* Implementation of CM4_0__LPI2C handler named in startup code. */
2589 void M4_0_LPI2C_DriverIRQHandler(void);
M4_0_LPI2C_DriverIRQHandler(void)2590 void M4_0_LPI2C_DriverIRQHandler(void)
2591 {
2592 LPI2C_CommonIRQHandler(CM4_0__LPI2C, LPI2C_GetInstance(CM4_0__LPI2C));
2593 }
2594 #endif
2595
2596 #if defined(CM4__LPI2C)
2597 /* Implementation of CM4__LPI2C handler named in startup code. */
2598 void M4_LPI2C_DriverIRQHandler(void);
M4_LPI2C_DriverIRQHandler(void)2599 void M4_LPI2C_DriverIRQHandler(void)
2600 {
2601 LPI2C_CommonIRQHandler(CM4__LPI2C, LPI2C_GetInstance(CM4__LPI2C));
2602 }
2603 #endif
2604
2605 #if defined(CM4_1__LPI2C)
2606 /* Implementation of CM4_1__LPI2C handler named in startup code. */
2607 void M4_1_LPI2C_DriverIRQHandler(void);
M4_1_LPI2C_DriverIRQHandler(void)2608 void M4_1_LPI2C_DriverIRQHandler(void)
2609 {
2610 LPI2C_CommonIRQHandler(CM4_1__LPI2C, LPI2C_GetInstance(CM4_1__LPI2C));
2611 }
2612 #endif
2613
2614 #if defined(DMA__LPI2C0)
2615 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2616 void DMA_I2C0_INT_DriverIRQHandler(void);
DMA_I2C0_INT_DriverIRQHandler(void)2617 void DMA_I2C0_INT_DriverIRQHandler(void)
2618 {
2619 LPI2C_CommonIRQHandler(DMA__LPI2C0, LPI2C_GetInstance(DMA__LPI2C0));
2620 }
2621 #endif
2622
2623 #if defined(DMA__LPI2C1)
2624 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2625 void DMA_I2C1_INT_DriverIRQHandler(void);
DMA_I2C1_INT_DriverIRQHandler(void)2626 void DMA_I2C1_INT_DriverIRQHandler(void)
2627 {
2628 LPI2C_CommonIRQHandler(DMA__LPI2C1, LPI2C_GetInstance(DMA__LPI2C1));
2629 }
2630 #endif
2631
2632 #if defined(DMA__LPI2C2)
2633 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2634 void DMA_I2C2_INT_DriverIRQHandler(void);
DMA_I2C2_INT_DriverIRQHandler(void)2635 void DMA_I2C2_INT_DriverIRQHandler(void)
2636 {
2637 LPI2C_CommonIRQHandler(DMA__LPI2C2, LPI2C_GetInstance(DMA__LPI2C2));
2638 }
2639 #endif
2640
2641 #if defined(DMA__LPI2C3)
2642 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2643 void DMA_I2C3_INT_DriverIRQHandler(void);
DMA_I2C3_INT_DriverIRQHandler(void)2644 void DMA_I2C3_INT_DriverIRQHandler(void)
2645 {
2646 LPI2C_CommonIRQHandler(DMA__LPI2C3, LPI2C_GetInstance(DMA__LPI2C3));
2647 }
2648 #endif
2649
2650 #if defined(DMA__LPI2C4)
2651 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2652 void DMA_I2C4_INT_DriverIRQHandler(void);
DMA_I2C4_INT_DriverIRQHandler(void)2653 void DMA_I2C4_INT_DriverIRQHandler(void)
2654 {
2655 LPI2C_CommonIRQHandler(DMA__LPI2C4, LPI2C_GetInstance(DMA__LPI2C4));
2656 }
2657 #endif
2658
2659 #if defined(ADMA__LPI2C0)
2660 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2661 void ADMA_I2C0_INT_DriverIRQHandler(void);
ADMA_I2C0_INT_DriverIRQHandler(void)2662 void ADMA_I2C0_INT_DriverIRQHandler(void)
2663 {
2664 LPI2C_CommonIRQHandler(ADMA__LPI2C0, LPI2C_GetInstance(ADMA__LPI2C0));
2665 }
2666 #endif
2667
2668 #if defined(ADMA__LPI2C1)
2669 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2670 void ADMA_I2C1_INT_DriverIRQHandler(void);
ADMA_I2C1_INT_DriverIRQHandler(void)2671 void ADMA_I2C1_INT_DriverIRQHandler(void)
2672 {
2673 LPI2C_CommonIRQHandler(ADMA__LPI2C1, LPI2C_GetInstance(ADMA__LPI2C1));
2674 }
2675 #endif
2676
2677 #if defined(ADMA__LPI2C2)
2678 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2679 void ADMA_I2C2_INT_DriverIRQHandler(void);
ADMA_I2C2_INT_DriverIRQHandler(void)2680 void ADMA_I2C2_INT_DriverIRQHandler(void)
2681 {
2682 LPI2C_CommonIRQHandler(ADMA__LPI2C2, LPI2C_GetInstance(ADMA__LPI2C2));
2683 }
2684 #endif
2685
2686 #if defined(ADMA__LPI2C3)
2687 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2688 void ADMA_I2C3_INT_DriverIRQHandler(void);
ADMA_I2C3_INT_DriverIRQHandler(void)2689 void ADMA_I2C3_INT_DriverIRQHandler(void)
2690 {
2691 LPI2C_CommonIRQHandler(ADMA__LPI2C3, LPI2C_GetInstance(ADMA__LPI2C3));
2692 }
2693 #endif
2694
2695 #if defined(ADMA__LPI2C4)
2696 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2697 void ADMA_I2C4_INT_DriverIRQHandler(void);
ADMA_I2C4_INT_DriverIRQHandler(void)2698 void ADMA_I2C4_INT_DriverIRQHandler(void)
2699 {
2700 LPI2C_CommonIRQHandler(ADMA__LPI2C4, LPI2C_GetInstance(ADMA__LPI2C4));
2701 }
2702 #endif
2703