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