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