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