1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_lpi2c.h"
10 #include <stdlib.h>
11 #include <string.h>
12
13 /*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16
17 /*! @brief Common sets of flags used by the driver. */
18 enum _lpi2c_flag_constants
19 {
20 /*! All flags which are cleared by the driver upon starting a transfer. */
21 kMasterClearFlags = kLPI2C_MasterEndOfPacketFlag | kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag |
22 kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag | kLPI2C_MasterPinLowTimeoutFlag |
23 kLPI2C_MasterDataMatchFlag,
24
25 /*! IRQ sources enabled by the non-blocking transactional API. */
26 kMasterIrqFlags = kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterTxReadyFlag | kLPI2C_MasterRxReadyFlag |
27 kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag | kLPI2C_MasterPinLowTimeoutFlag |
28 kLPI2C_MasterFifoErrFlag,
29
30 /*! Errors to check for. */
31 kMasterErrorFlags = kLPI2C_MasterNackDetectFlag | kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag |
32 kLPI2C_MasterPinLowTimeoutFlag,
33
34 /*! All flags which are cleared by the driver upon starting a transfer. */
35 kSlaveClearFlags = kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveBitErrFlag |
36 kLPI2C_SlaveFifoErrFlag,
37
38 /*! IRQ sources enabled by the non-blocking transactional API. */
39 kSlaveIrqFlags = kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag |
40 kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag |
41 kLPI2C_SlaveTransmitAckFlag | kLPI2C_SlaveAddressValidFlag,
42
43 /*! Errors to check for. */
44 kSlaveErrorFlags = kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag,
45 };
46
47 /* ! @brief LPI2C master fifo commands. */
48 enum _lpi2c_master_fifo_cmd
49 {
50 kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
51 kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
52 kStopCmd = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
53 kStartCmd = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
54 };
55
56 /*!
57 * @brief Default watermark values.
58 *
59 * The default watermarks are set to zero.
60 */
61 enum _lpi2c_default_watermarks
62 {
63 kDefaultTxWatermark = 0,
64 kDefaultRxWatermark = 0,
65 };
66
67 /*! @brief States for the state machine used by transactional APIs. */
68 enum _lpi2c_transfer_states
69 {
70 kIdleState = 0,
71 kSendCommandState,
72 kIssueReadCommandState,
73 kTransferDataState,
74 kStopState,
75 kWaitForCompletionState,
76 };
77
78 /*! @brief Typedef for master interrupt handler. */
79 typedef void (*lpi2c_master_isr_t)(LPI2C_Type *base, lpi2c_master_handle_t *handle);
80
81 /*! @brief Typedef for slave interrupt handler. */
82 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
83
84 /*******************************************************************************
85 * Prototypes
86 ******************************************************************************/
87
88 /* Not static so it can be used from fsl_lpi2c_edma.c. */
89 uint32_t LPI2C_GetInstance(LPI2C_Type *base);
90
91 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
92 uint32_t width_ns,
93 uint32_t maxCycles,
94 uint32_t prescaler);
95
96 /* Not static so it can be used from fsl_lpi2c_edma.c. */
97 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status);
98
99 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
100
101 /* Not static so it can be used from fsl_lpi2c_edma.c. */
102 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base);
103
104 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
105
106 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
107
108 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
109
110 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
111
112 /*******************************************************************************
113 * Variables
114 ******************************************************************************/
115
116 /*! @brief Array to map LPI2C instance number to base pointer. */
117 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
118
119 /*! @brief Array to map LPI2C instance number to IRQ number. */
120 static IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
121
122 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
123 /*! @brief Array to map LPI2C instance number to clock gate enum. */
124 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
125
126 #if defined(LPI2C_PERIPH_CLOCKS)
127 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
128 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
129 #endif
130
131 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
132
133 /*! @brief Pointer to master IRQ handler for each instance. */
134 static lpi2c_master_isr_t s_lpi2cMasterIsr;
135
136 /*! @brief Pointers to master handles for each instance. */
137 static lpi2c_master_handle_t *s_lpi2cMasterHandle[FSL_FEATURE_SOC_LPI2C_COUNT];
138
139 /*! @brief Pointer to slave IRQ handler for each instance. */
140 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
141
142 /*! @brief Pointers to slave handles for each instance. */
143 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[FSL_FEATURE_SOC_LPI2C_COUNT];
144
145 /*******************************************************************************
146 * Code
147 ******************************************************************************/
148
149 /*!
150 * @brief Returns an instance number given a base address.
151 *
152 * If an invalid base address is passed, debug builds will assert. Release builds will just return
153 * instance number 0.
154 *
155 * @param base The LPI2C peripheral base address.
156 * @return LPI2C instance number starting from 0.
157 */
LPI2C_GetInstance(LPI2C_Type * base)158 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
159 {
160 uint32_t instance;
161 for (instance = 0; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
162 {
163 if (kLpi2cBases[instance] == base)
164 {
165 return instance;
166 }
167 }
168
169 assert(false);
170 return 0;
171 }
172
173 /*!
174 * @brief Computes a cycle count for a given time in nanoseconds.
175 * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
176 * @param width_ns Desired with in nanoseconds.
177 * @param maxCycles Maximum cycle count, determined by the number of bits wide the cycle count field is.
178 * @param prescaler LPI2C prescaler setting. Pass 1 if the prescaler should not be used, as for slave glitch widths.
179 */
LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,uint32_t width_ns,uint32_t maxCycles,uint32_t prescaler)180 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
181 uint32_t width_ns,
182 uint32_t maxCycles,
183 uint32_t prescaler)
184 {
185 uint32_t busCycle_ns = 1000000 / (sourceClock_Hz / prescaler / 1000);
186 uint32_t cycles = 0;
187
188 /* Search for the cycle count just below the desired glitch width. */
189 while ((((cycles + 1) * busCycle_ns) < width_ns) && (cycles + 1 < maxCycles))
190 {
191 ++cycles;
192 }
193
194 /* If we end up with zero cycles, then set the filter to a single cycle unless the */
195 /* bus clock is greater than 10x the desired glitch width. */
196 if ((cycles == 0) && (busCycle_ns <= (width_ns * 10)))
197 {
198 cycles = 1;
199 }
200
201 return cycles;
202 }
203
204 /*!
205 * @brief Convert provided flags to status code, and clear any errors if present.
206 * @param base The LPI2C peripheral base address.
207 * @param status Current status flags value that will be checked.
208 * @retval #kStatus_Success
209 * @retval #kStatus_LPI2C_PinLowTimeout
210 * @retval #kStatus_LPI2C_ArbitrationLost
211 * @retval #kStatus_LPI2C_Nak
212 * @retval #kStatus_LPI2C_FifoError
213 */
LPI2C_MasterCheckAndClearError(LPI2C_Type * base,uint32_t status)214 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
215 {
216 status_t result = kStatus_Success;
217
218 /* Check for error. These errors cause a stop to automatically be sent. We must */
219 /* clear the errors before a new transfer can start. */
220 status &= kMasterErrorFlags;
221 if (status)
222 {
223 /* Select the correct error code. Ordered by severity, with bus issues first. */
224 if (status & kLPI2C_MasterPinLowTimeoutFlag)
225 {
226 result = kStatus_LPI2C_PinLowTimeout;
227 }
228 else if (status & kLPI2C_MasterArbitrationLostFlag)
229 {
230 result = kStatus_LPI2C_ArbitrationLost;
231 }
232 else if (status & kLPI2C_MasterNackDetectFlag)
233 {
234 result = kStatus_LPI2C_Nak;
235 }
236 else if (status & kLPI2C_MasterFifoErrFlag)
237 {
238 result = kStatus_LPI2C_FifoError;
239 }
240 else
241 {
242 assert(false);
243 }
244
245 /* Clear the flags. */
246 LPI2C_MasterClearStatusFlags(base, status);
247
248 /* Reset fifos. These flags clear automatically. */
249 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
250 }
251
252 return result;
253 }
254
255 /*!
256 * @brief Wait until there is room in the tx fifo.
257 * @param base The LPI2C peripheral base address.
258 * @retval #kStatus_Success
259 * @retval #kStatus_LPI2C_PinLowTimeout
260 * @retval #kStatus_LPI2C_ArbitrationLost
261 * @retval #kStatus_LPI2C_Nak
262 * @retval #kStatus_LPI2C_FifoError
263 */
LPI2C_MasterWaitForTxReady(LPI2C_Type * base)264 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
265 {
266 uint32_t status;
267 size_t txCount;
268 size_t txFifoSize = FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
269 do
270 {
271 status_t result;
272
273 /* Get the number of words in the tx fifo and compute empty slots. */
274 LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
275 txCount = txFifoSize - txCount;
276
277 /* Check for error flags. */
278 status = LPI2C_MasterGetStatusFlags(base);
279 result = LPI2C_MasterCheckAndClearError(base, status);
280 if (result)
281 {
282 return result;
283 }
284 } while (!txCount);
285
286 return kStatus_Success;
287 }
288
289 /*!
290 * @brief Make sure the bus isn't already busy.
291 *
292 * A busy bus is allowed if we are the one driving it.
293 *
294 * @param base The LPI2C peripheral base address.
295 * @retval #kStatus_Success
296 * @retval #kStatus_LPI2C_Busy
297 */
LPI2C_CheckForBusyBus(LPI2C_Type * base)298 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
299 {
300 uint32_t status = LPI2C_MasterGetStatusFlags(base);
301 if ((status & kLPI2C_MasterBusBusyFlag) && (!(status & kLPI2C_MasterBusyFlag)))
302 {
303 return kStatus_LPI2C_Busy;
304 }
305
306 return kStatus_Success;
307 }
308
LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t * masterConfig)309 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
310 {
311 masterConfig->enableMaster = true;
312 masterConfig->debugEnable = false;
313 masterConfig->enableDoze = true;
314 masterConfig->ignoreAck = false;
315 masterConfig->pinConfig = kLPI2C_2PinOpenDrain;
316 masterConfig->baudRate_Hz = 100000U;
317 masterConfig->busIdleTimeout_ns = 0;
318 masterConfig->pinLowTimeout_ns = 0;
319 masterConfig->sdaGlitchFilterWidth_ns = 0;
320 masterConfig->sclGlitchFilterWidth_ns = 0;
321 masterConfig->hostRequest.enable = false;
322 masterConfig->hostRequest.source = kLPI2C_HostRequestExternalPin;
323 masterConfig->hostRequest.polarity = kLPI2C_HostRequestPinActiveHigh;
324 }
325
LPI2C_MasterInit(LPI2C_Type * base,const lpi2c_master_config_t * masterConfig,uint32_t sourceClock_Hz)326 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
327 {
328 uint32_t prescaler;
329 uint32_t cycles;
330 uint32_t cfgr2;
331 uint32_t value;
332
333 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
334
335 uint32_t instance = LPI2C_GetInstance(base);
336
337 /* Ungate the clock. */
338 CLOCK_EnableClock(kLpi2cClocks[instance]);
339 #if defined(LPI2C_PERIPH_CLOCKS)
340 /* Ungate the functional clock in initialize function. */
341 CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
342 #endif
343
344 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
345
346 /* Reset peripheral before configuring it. */
347 LPI2C_MasterReset(base);
348
349 /* Doze bit: 0 is enable, 1 is disable */
350 base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
351
352 /* host request */
353 value = base->MCFGR0;
354 value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
355 value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
356 LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
357 LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
358 base->MCFGR0 = value;
359
360 /* pin config and ignore ack */
361 value = base->MCFGR1;
362 value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
363 value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
364 value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
365 base->MCFGR1 = value;
366
367 LPI2C_MasterSetWatermarks(base, kDefaultTxWatermark, kDefaultRxWatermark);
368
369 LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
370
371 /* Configure glitch filters and bus idle and pin low timeouts. */
372 prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
373 cfgr2 = base->MCFGR2;
374 if (masterConfig->busIdleTimeout_ns)
375 {
376 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns,
377 (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
378 cfgr2 &= ~LPI2C_MCFGR2_BUSIDLE_MASK;
379 cfgr2 |= LPI2C_MCFGR2_BUSIDLE(cycles);
380 }
381 if (masterConfig->sdaGlitchFilterWidth_ns)
382 {
383 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns,
384 (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 1);
385 cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
386 cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
387 }
388 if (masterConfig->sclGlitchFilterWidth_ns)
389 {
390 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns,
391 (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 1);
392 cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
393 cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
394 }
395 base->MCFGR2 = cfgr2;
396 if (masterConfig->pinLowTimeout_ns)
397 {
398 cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256,
399 (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
400 base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
401 }
402
403 LPI2C_MasterEnable(base, masterConfig->enableMaster);
404 }
405
LPI2C_MasterDeinit(LPI2C_Type * base)406 void LPI2C_MasterDeinit(LPI2C_Type *base)
407 {
408 /* Restore to reset state. */
409 LPI2C_MasterReset(base);
410
411 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
412
413 uint32_t instance = LPI2C_GetInstance(base);
414
415 /* Gate clock. */
416 CLOCK_DisableClock(kLpi2cClocks[instance]);
417 #if defined(LPI2C_PERIPH_CLOCKS)
418 /* Gate the functional clock. */
419 CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
420 #endif
421
422 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
423 }
424
LPI2C_MasterConfigureDataMatch(LPI2C_Type * base,const lpi2c_data_match_config_t * config)425 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *config)
426 {
427 /* Disable master mode. */
428 bool wasEnabled = (base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT;
429 LPI2C_MasterEnable(base, false);
430
431 base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(config->matchMode);
432 base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(config->rxDataMatchOnly);
433 base->MDMR = LPI2C_MDMR_MATCH0(config->match0) | LPI2C_MDMR_MATCH1(config->match1);
434
435 /* Restore master mode. */
436 if (wasEnabled)
437 {
438 LPI2C_MasterEnable(base, true);
439 }
440 }
441
LPI2C_MasterSetBaudRate(LPI2C_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Hz)442 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
443 {
444 uint32_t prescale = 0;
445 uint32_t bestPre = 0;
446 uint32_t bestClkHi = 0;
447 uint32_t absError = 0;
448 uint32_t bestError = 0xffffffffu;
449 uint32_t value;
450 uint32_t clkHiCycle;
451 uint32_t computedRate;
452 int i;
453 bool wasEnabled;
454
455 /* Disable master mode. */
456 wasEnabled = (base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT;
457 LPI2C_MasterEnable(base, false);
458
459 /* Baud rate = (sourceClock_Hz/2^prescale)/(CLKLO+1+CLKHI+1 + ROUNDDOWN((2+FILTSCL)/2^prescale) */
460 /* Assume CLKLO = 2*CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2. */
461 for (prescale = 1; (prescale <= 128) && (bestError != 0); prescale = 2 * prescale)
462 {
463 for (clkHiCycle = 1; clkHiCycle < 32; clkHiCycle++)
464 {
465 if (clkHiCycle == 1)
466 {
467 computedRate = (sourceClock_Hz / prescale) / (1 + 3 + 2 + 2 / prescale);
468 }
469 else
470 {
471 computedRate = (sourceClock_Hz / prescale) / (3 * clkHiCycle + 2 + 2 / prescale);
472 }
473
474 absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
475
476 if (absError < bestError)
477 {
478 bestPre = prescale;
479 bestClkHi = clkHiCycle;
480 bestError = absError;
481
482 /* If the error is 0, then we can stop searching because we won't find a better match. */
483 if (absError == 0)
484 {
485 break;
486 }
487 }
488 }
489 }
490
491 /* Standard, fast, fast mode plus and ultra-fast transfers. */
492 value = LPI2C_MCCR0_CLKHI(bestClkHi);
493
494 if (bestClkHi < 2)
495 {
496 value |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) | LPI2C_MCCR0_DATAVD(1);
497 }
498 else
499 {
500 value |= LPI2C_MCCR0_CLKLO(2 * bestClkHi) | LPI2C_MCCR0_SETHOLD(bestClkHi) | LPI2C_MCCR0_DATAVD(bestClkHi / 2);
501 }
502
503 base->MCCR0 = value;
504
505 for (i = 0; i < 8; i++)
506 {
507 if (bestPre == (1U << i))
508 {
509 bestPre = i;
510 break;
511 }
512 }
513 base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
514
515 /* Restore master mode. */
516 if (wasEnabled)
517 {
518 LPI2C_MasterEnable(base, true);
519 }
520 }
521
LPI2C_MasterStart(LPI2C_Type * base,uint8_t address,lpi2c_direction_t dir)522 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
523 {
524 /* Return an error if the bus is already in use not by us. */
525 status_t result = LPI2C_CheckForBusyBus(base);
526 if (result)
527 {
528 return result;
529 }
530
531 /* Clear all flags. */
532 LPI2C_MasterClearStatusFlags(base, kMasterClearFlags);
533
534 /* Turn off auto-stop option. */
535 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
536
537 /* Wait until there is room in the fifo. */
538 result = LPI2C_MasterWaitForTxReady(base);
539 if (result)
540 {
541 return result;
542 }
543
544 /* Issue start command. */
545 base->MTDR = kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
546
547 return kStatus_Success;
548 }
549
LPI2C_MasterStop(LPI2C_Type * base)550 status_t LPI2C_MasterStop(LPI2C_Type *base)
551 {
552 /* Wait until there is room in the fifo. */
553 status_t result = LPI2C_MasterWaitForTxReady(base);
554 if (result)
555 {
556 return result;
557 }
558
559 /* Send the STOP signal */
560 base->MTDR = kStopCmd;
561
562 /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
563 /* Also check for errors while waiting. */
564 while (result == kStatus_Success)
565 {
566 uint32_t status = LPI2C_MasterGetStatusFlags(base);
567
568 /* Check for error flags. */
569 result = LPI2C_MasterCheckAndClearError(base, status);
570
571 /* Check if the stop was sent successfully. */
572 if (status & kLPI2C_MasterStopDetectFlag)
573 {
574 LPI2C_MasterClearStatusFlags(base, kLPI2C_MasterStopDetectFlag);
575 break;
576 }
577 }
578
579 return result;
580 }
581
LPI2C_MasterReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize)582 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
583 {
584 status_t result;
585 uint8_t *buf;
586
587 assert(rxBuff);
588
589 /* Handle empty read. */
590 if (!rxSize)
591 {
592 return kStatus_Success;
593 }
594
595 /* Wait until there is room in the command fifo. */
596 result = LPI2C_MasterWaitForTxReady(base);
597 if (result)
598 {
599 return result;
600 }
601
602 /* Issue command to receive data. */
603 base->MTDR = kRxDataCmd | LPI2C_MTDR_DATA(rxSize - 1);
604
605 /* Receive data */
606 buf = (uint8_t *)rxBuff;
607 while (rxSize--)
608 {
609 /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
610 /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
611 /* using a single register read. */
612 uint32_t value;
613 do
614 {
615 /* Check for errors. */
616 result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
617 if (result)
618 {
619 return result;
620 }
621
622 value = base->MRDR;
623 } while (value & LPI2C_MRDR_RXEMPTY_MASK);
624
625 *buf++ = value & LPI2C_MRDR_DATA_MASK;
626 }
627
628 return kStatus_Success;
629 }
630
LPI2C_MasterSend(LPI2C_Type * base,const void * txBuff,size_t txSize)631 status_t LPI2C_MasterSend(LPI2C_Type *base, const void *txBuff, size_t txSize)
632 {
633 uint8_t *buf = (uint8_t *)((void *)txBuff);
634
635 assert(txBuff);
636
637 /* Send data buffer */
638 while (txSize--)
639 {
640 /* Wait until there is room in the fifo. This also checks for errors. */
641 status_t result = LPI2C_MasterWaitForTxReady(base);
642 if (result)
643 {
644 return result;
645 }
646
647 /* Write byte into LPI2C master data register. */
648 base->MTDR = *buf++;
649 }
650
651 return kStatus_Success;
652 }
653
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)654 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
655 lpi2c_master_handle_t *handle,
656 lpi2c_master_transfer_callback_t callback,
657 void *userData)
658 {
659 uint32_t instance;
660
661 assert(handle);
662
663 /* Clear out the handle. */
664 memset(handle, 0, sizeof(*handle));
665
666 /* Look up instance number */
667 instance = LPI2C_GetInstance(base);
668
669 /* Save base and instance. */
670 handle->completionCallback = callback;
671 handle->userData = userData;
672
673 /* Save this handle for IRQ use. */
674 s_lpi2cMasterHandle[instance] = handle;
675
676 /* Set irq handler. */
677 s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
678
679 /* Clear internal IRQ enables and enable NVIC IRQ. */
680 LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
681 EnableIRQ(kLpi2cIrqs[instance]);
682 }
683
684 /*!
685 * @brief Execute states until FIFOs are exhausted.
686 * @param handle Master nonblocking driver handle.
687 * @param[out] isDone Set to true if the transfer has completed.
688 * @retval #kStatus_Success
689 * @retval #kStatus_LPI2C_PinLowTimeout
690 * @retval #kStatus_LPI2C_ArbitrationLost
691 * @retval #kStatus_LPI2C_Nak
692 * @retval #kStatus_LPI2C_FifoError
693 */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)694 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
695 {
696 uint32_t status;
697 status_t result = kStatus_Success;
698 lpi2c_master_transfer_t *xfer;
699 size_t txCount;
700 size_t rxCount;
701 size_t txFifoSize = FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
702 bool state_complete = false;
703
704 /* Set default isDone return value. */
705 *isDone = false;
706
707 /* Check for errors. */
708 status = LPI2C_MasterGetStatusFlags(base);
709 result = LPI2C_MasterCheckAndClearError(base, status);
710 if (result)
711 {
712 return result;
713 }
714
715 /* Get pointer to private data. */
716 xfer = &handle->transfer;
717
718 /* Get fifo counts and compute room in tx fifo. */
719 LPI2C_MasterGetFifoCounts(base, &rxCount, &txCount);
720 txCount = txFifoSize - txCount;
721
722 while (!state_complete)
723 {
724 /* Execute the state. */
725 switch (handle->state)
726 {
727 case kSendCommandState:
728 {
729 /* Make sure there is room in the tx fifo for the next command. */
730 if (!txCount--)
731 {
732 state_complete = true;
733 break;
734 }
735
736 /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
737 base->MTDR = *(uint16_t *)handle->buf;
738 handle->buf += sizeof(uint16_t);
739
740 /* Count down until all commands are sent. */
741 if (--handle->remainingBytes == 0)
742 {
743 /* Choose next state and set up buffer pointer and count. */
744 if (xfer->dataSize)
745 {
746 /* Either a send or receive transfer is next. */
747 handle->state = kTransferDataState;
748 handle->buf = (uint8_t *)xfer->data;
749 handle->remainingBytes = xfer->dataSize;
750 if (xfer->direction == kLPI2C_Read)
751 {
752 /* Disable TX interrupt */
753 LPI2C_MasterDisableInterrupts(base, kLPI2C_MasterTxReadyFlag);
754 }
755 }
756 else
757 {
758 /* No transfer, so move to stop state. */
759 handle->state = kStopState;
760 }
761 }
762 break;
763 }
764
765 case kIssueReadCommandState:
766 /* Make sure there is room in the tx fifo for the read command. */
767 if (!txCount--)
768 {
769 state_complete = true;
770 break;
771 }
772
773 base->MTDR = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
774
775 /* Move to transfer state. */
776 handle->state = kTransferDataState;
777 if (xfer->direction == kLPI2C_Read)
778 {
779 /* Disable TX interrupt */
780 LPI2C_MasterDisableInterrupts(base, kLPI2C_MasterTxReadyFlag);
781 }
782 break;
783
784 case kTransferDataState:
785 if (xfer->direction == kLPI2C_Write)
786 {
787 /* Make sure there is room in the tx fifo. */
788 if (!txCount--)
789 {
790 state_complete = true;
791 break;
792 }
793
794 /* Put byte to send in fifo. */
795 base->MTDR = *(handle->buf)++;
796 }
797 else
798 {
799 /* XXX handle receive sizes > 256, use kIssueReadCommandState */
800 /* Make sure there is data in the rx fifo. */
801 if (!rxCount--)
802 {
803 state_complete = true;
804 break;
805 }
806
807 /* Read byte from fifo. */
808 *(handle->buf)++ = base->MRDR & LPI2C_MRDR_DATA_MASK;
809 }
810
811 /* Move to stop when the transfer is done. */
812 if (--handle->remainingBytes == 0)
813 {
814 handle->state = kStopState;
815 }
816 break;
817
818 case kStopState:
819 /* Only issue a stop transition if the caller requested it. */
820 if ((xfer->flags & kLPI2C_TransferNoStopFlag) == 0)
821 {
822 /* Make sure there is room in the tx fifo for the stop command. */
823 if (!txCount--)
824 {
825 state_complete = true;
826 break;
827 }
828
829 base->MTDR = kStopCmd;
830 }
831 else
832 {
833 /* Caller doesn't want to send a stop, so we're done now. */
834 *isDone = true;
835 state_complete = true;
836 break;
837 }
838 handle->state = kWaitForCompletionState;
839 break;
840
841 case kWaitForCompletionState:
842 /* We stay in this state until the stop state is detected. */
843 if (status & kLPI2C_MasterStopDetectFlag)
844 {
845 *isDone = true;
846 }
847 state_complete = true;
848 break;
849 default:
850 assert(false);
851 break;
852 }
853 }
854 return result;
855 }
856
857 /*!
858 * @brief Prepares the transfer state machine and fills in the command buffer.
859 * @param handle Master nonblocking driver handle.
860 */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)861 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
862 {
863 lpi2c_master_transfer_t *xfer = &handle->transfer;
864
865 /* Handle no start option. */
866 if (xfer->flags & kLPI2C_TransferNoStartFlag)
867 {
868 if (xfer->direction == kLPI2C_Read)
869 {
870 /* Need to issue read command first. */
871 handle->state = kIssueReadCommandState;
872 }
873 else
874 {
875 /* Start immediately in the data transfer state. */
876 handle->state = kTransferDataState;
877 }
878
879 handle->buf = (uint8_t *)xfer->data;
880 handle->remainingBytes = xfer->dataSize;
881 }
882 else
883 {
884 uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
885 uint32_t cmdCount = 0;
886
887 /* Initial direction depends on whether a subaddress was provided, and of course the actual */
888 /* data transfer direction. */
889 lpi2c_direction_t direction = xfer->subaddressSize ? kLPI2C_Write : xfer->direction;
890
891 /* Start command. */
892 cmd[cmdCount++] =
893 (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
894
895 /* Subaddress, MSB first. */
896 if (xfer->subaddressSize)
897 {
898 uint32_t subaddressRemaining = xfer->subaddressSize;
899 while (subaddressRemaining--)
900 {
901 uint8_t subaddressByte = (xfer->subaddress >> (8 * subaddressRemaining)) & 0xff;
902 cmd[cmdCount++] = subaddressByte;
903 }
904 }
905
906 /* Reads need special handling. */
907 if ((xfer->dataSize) && (xfer->direction == kLPI2C_Read))
908 {
909 /* Need to send repeated start if switching directions to read. */
910 if (direction == kLPI2C_Write)
911 {
912 cmd[cmdCount++] = (uint16_t)kStartCmd |
913 (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
914 }
915
916 /* Read command. */
917 cmd[cmdCount++] = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
918 }
919
920 /* Set up state machine for transferring the commands. */
921 handle->state = kSendCommandState;
922 handle->remainingBytes = cmdCount;
923 handle->buf = (uint8_t *)&handle->commandBuffer;
924 }
925 }
926
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)927 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
928 lpi2c_master_handle_t *handle,
929 lpi2c_master_transfer_t *transfer)
930 {
931 status_t result;
932
933 assert(handle);
934 assert(transfer);
935 assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
936
937 /* Return busy if another transaction is in progress. */
938 if (handle->state != kIdleState)
939 {
940 return kStatus_LPI2C_Busy;
941 }
942
943 /* Return an error if the bus is already in use not by us. */
944 result = LPI2C_CheckForBusyBus(base);
945 if (result)
946 {
947 return result;
948 }
949
950 /* Disable LPI2C IRQ sources while we configure stuff. */
951 LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
952
953 /* Save transfer into handle. */
954 handle->transfer = *transfer;
955
956 /* Generate commands to send. */
957 LPI2C_InitTransferStateMachine(handle);
958
959 /* Clear all flags. */
960 LPI2C_MasterClearStatusFlags(base, kMasterClearFlags);
961
962 /* Turn off auto-stop option. */
963 base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
964
965 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
966 LPI2C_MasterEnableInterrupts(base, kMasterIrqFlags);
967
968 return result;
969 }
970
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)971 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
972 {
973 assert(handle);
974
975 if (!count)
976 {
977 return kStatus_InvalidArgument;
978 }
979
980 /* Catch when there is not an active transfer. */
981 if (handle->state == kIdleState)
982 {
983 *count = 0;
984 return kStatus_NoTransferInProgress;
985 }
986
987 uint8_t state;
988 uint16_t remainingBytes;
989 uint32_t dataSize;
990
991 /* Cache some fields with IRQs disabled. This ensures all field values */
992 /* are synchronized with each other during an ongoing transfer. */
993 uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
994 LPI2C_MasterDisableInterrupts(base, irqs);
995 state = handle->state;
996 remainingBytes = handle->remainingBytes;
997 dataSize = handle->transfer.dataSize;
998 LPI2C_MasterEnableInterrupts(base, irqs);
999
1000 /* Get transfer count based on current transfer state. */
1001 switch (state)
1002 {
1003 case kIdleState:
1004 case kSendCommandState:
1005 case kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1006 *count = 0;
1007 break;
1008
1009 case kTransferDataState:
1010 *count = dataSize - remainingBytes;
1011 break;
1012
1013 case kStopState:
1014 case kWaitForCompletionState:
1015 default:
1016 *count = dataSize;
1017 break;
1018 }
1019
1020 return kStatus_Success;
1021 }
1022
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1023 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1024 {
1025 if (handle->state != kIdleState)
1026 {
1027 /* Disable internal IRQ enables. */
1028 LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
1029
1030 /* Reset fifos. */
1031 base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1032
1033 /* Send a stop command to finalize the transfer. */
1034 base->MTDR = kStopCmd;
1035
1036 /* Reset handle. */
1037 handle->state = kIdleState;
1038 }
1039 }
1040
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,lpi2c_master_handle_t * handle)1041 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1042 {
1043 bool isDone;
1044 status_t result;
1045
1046 /* Don't do anything if we don't have a valid handle. */
1047 if (!handle)
1048 {
1049 return;
1050 }
1051
1052 if (handle->state == kIdleState)
1053 {
1054 return;
1055 }
1056
1057 result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1058
1059 if (isDone || (result != kStatus_Success))
1060 {
1061 /* XXX need to handle data that may be in rx fifo below watermark level? */
1062
1063 /* XXX handle error, terminate xfer */
1064
1065 /* Disable internal IRQ enables. */
1066 LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
1067
1068 /* Set handle to idle state. */
1069 handle->state = kIdleState;
1070
1071 /* Invoke callback. */
1072 if (handle->completionCallback)
1073 {
1074 handle->completionCallback(base, handle, result, handle->userData);
1075 }
1076 }
1077 }
1078
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1079 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1080 {
1081 slaveConfig->enableSlave = true;
1082 slaveConfig->address0 = 0U;
1083 slaveConfig->address1 = 0U;
1084 slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1085 slaveConfig->filterDozeEnable = true;
1086 slaveConfig->filterEnable = true;
1087 slaveConfig->enableGeneralCall = false;
1088 slaveConfig->sclStall.enableAck = false;
1089 slaveConfig->sclStall.enableTx = true;
1090 slaveConfig->sclStall.enableRx = true;
1091 slaveConfig->sclStall.enableAddress = false;
1092 slaveConfig->ignoreAck = false;
1093 slaveConfig->enableReceivedAddressRead = false;
1094 slaveConfig->sdaGlitchFilterWidth_ns = 0; /* TODO determine default width values */
1095 slaveConfig->sclGlitchFilterWidth_ns = 0;
1096 slaveConfig->dataValidDelay_ns = 0;
1097 slaveConfig->clockHoldTime_ns = 0;
1098 }
1099
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1100 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1101 {
1102 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1103
1104 uint32_t instance = LPI2C_GetInstance(base);
1105
1106 /* Ungate the clock. */
1107 CLOCK_EnableClock(kLpi2cClocks[instance]);
1108 #if defined(LPI2C_PERIPH_CLOCKS)
1109 /* Ungate the functional clock in initialize function. */
1110 CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1111 #endif
1112
1113 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1114
1115 /* Restore to reset conditions. */
1116 LPI2C_SlaveReset(base);
1117
1118 /* Configure peripheral. */
1119 base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1120
1121 base->SCFGR1 =
1122 LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1123 LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1124 LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1125 LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1126 LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1127
1128 base->SCFGR2 =
1129 LPI2C_SCFGR2_FILTSDA(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns,
1130 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT), 1)) |
1131 LPI2C_SCFGR2_FILTSCL(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns,
1132 (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT), 1)) |
1133 LPI2C_SCFGR2_DATAVD(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns,
1134 (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 1)) |
1135 LPI2C_SCFGR2_CLKHOLD(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns,
1136 (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT), 1));
1137
1138 /* Save SCR to last so we don't enable slave until it is configured */
1139 base->SCR = LPI2C_SCR_FILTDZ(slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1140 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1141 }
1142
LPI2C_SlaveDeinit(LPI2C_Type * base)1143 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1144 {
1145 LPI2C_SlaveReset(base);
1146
1147 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1148
1149 uint32_t instance = LPI2C_GetInstance(base);
1150
1151 /* Gate the clock. */
1152 CLOCK_DisableClock(kLpi2cClocks[instance]);
1153
1154 #if defined(LPI2C_PERIPH_CLOCKS)
1155 /* Gate the functional clock. */
1156 CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1157 #endif
1158
1159 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1160 }
1161
1162 /*!
1163 * @brief Convert provided flags to status code, and clear any errors if present.
1164 * @param base The LPI2C peripheral base address.
1165 * @param status Current status flags value that will be checked.
1166 * @retval #kStatus_Success
1167 * @retval #kStatus_LPI2C_BitError
1168 * @retval #kStatus_LPI2C_FifoError
1169 */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1170 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1171 {
1172 status_t result = kStatus_Success;
1173
1174 flags &= kSlaveErrorFlags;
1175 if (flags)
1176 {
1177 if (flags & kLPI2C_SlaveBitErrFlag)
1178 {
1179 result = kStatus_LPI2C_BitError;
1180 }
1181 else if (flags & kLPI2C_SlaveFifoErrFlag)
1182 {
1183 result = kStatus_LPI2C_FifoError;
1184 }
1185 else
1186 {
1187 assert(false);
1188 }
1189
1190 /* Clear the errors. */
1191 LPI2C_SlaveClearStatusFlags(base, flags);
1192 }
1193
1194 return result;
1195 }
1196
LPI2C_SlaveSend(LPI2C_Type * base,const void * txBuff,size_t txSize,size_t * actualTxSize)1197 status_t LPI2C_SlaveSend(LPI2C_Type *base, const void *txBuff, size_t txSize, size_t *actualTxSize)
1198 {
1199 uint8_t *buf = (uint8_t *)((void *)txBuff);
1200 size_t remaining = txSize;
1201
1202 assert(txBuff);
1203
1204 while (remaining)
1205 {
1206 uint32_t flags;
1207 status_t result;
1208
1209 /* Wait until we can transmit. */
1210 do
1211 {
1212 /* Check for errors */
1213 flags = LPI2C_SlaveGetStatusFlags(base);
1214 result = LPI2C_SlaveCheckAndClearError(base, flags);
1215 if (result)
1216 {
1217 if (actualTxSize)
1218 {
1219 *actualTxSize = txSize - remaining;
1220 }
1221 return result;
1222 }
1223 } while (
1224 !(flags & (kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag)));
1225
1226 /* Send a byte. */
1227 if (flags & kLPI2C_SlaveTxReadyFlag)
1228 {
1229 base->STDR = *buf++;
1230 --remaining;
1231 }
1232
1233 /* Exit loop if we see a stop or restart */
1234 if (flags & (kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag))
1235 {
1236 LPI2C_SlaveClearStatusFlags(base, kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag);
1237 break;
1238 }
1239 }
1240
1241 if (actualTxSize)
1242 {
1243 *actualTxSize = txSize - remaining;
1244 }
1245
1246 return kStatus_Success;
1247 }
1248
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)1249 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
1250 {
1251 uint8_t *buf = (uint8_t *)rxBuff;
1252 size_t remaining = rxSize;
1253
1254 assert(rxBuff);
1255
1256 while (remaining)
1257 {
1258 uint32_t flags;
1259 status_t result;
1260
1261 /* Wait until we can receive. */
1262 do
1263 {
1264 /* Check for errors */
1265 flags = LPI2C_SlaveGetStatusFlags(base);
1266 result = LPI2C_SlaveCheckAndClearError(base, flags);
1267 if (result)
1268 {
1269 if (actualRxSize)
1270 {
1271 *actualRxSize = rxSize - remaining;
1272 }
1273 return result;
1274 }
1275 } while (
1276 !(flags & (kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag)));
1277
1278 /* Receive a byte. */
1279 if (flags & kLPI2C_SlaveRxReadyFlag)
1280 {
1281 *buf++ = base->SRDR & LPI2C_SRDR_DATA_MASK;
1282 --remaining;
1283 }
1284
1285 /* Exit loop if we see a stop or restart */
1286 if (flags & (kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag))
1287 {
1288 LPI2C_SlaveClearStatusFlags(base, kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag);
1289 break;
1290 }
1291 }
1292
1293 if (actualRxSize)
1294 {
1295 *actualRxSize = rxSize - remaining;
1296 }
1297
1298 return kStatus_Success;
1299 }
1300
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)1301 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
1302 lpi2c_slave_handle_t *handle,
1303 lpi2c_slave_transfer_callback_t callback,
1304 void *userData)
1305 {
1306 uint32_t instance;
1307
1308 assert(handle);
1309
1310 /* Clear out the handle. */
1311 memset(handle, 0, sizeof(*handle));
1312
1313 /* Look up instance number */
1314 instance = LPI2C_GetInstance(base);
1315
1316 /* Save base and instance. */
1317 handle->callback = callback;
1318 handle->userData = userData;
1319
1320 /* Save this handle for IRQ use. */
1321 s_lpi2cSlaveHandle[instance] = handle;
1322
1323 /* Set irq handler. */
1324 s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
1325
1326 /* Clear internal IRQ enables and enable NVIC IRQ. */
1327 LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1328 EnableIRQ(kLpi2cIrqs[instance]);
1329
1330 /* Nack by default. */
1331 base->STAR = LPI2C_STAR_TXNACK_MASK;
1332 }
1333
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)1334 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
1335 {
1336 uint32_t status;
1337
1338 assert(handle);
1339
1340 /* Return busy if another transaction is in progress. */
1341 if (handle->isBusy)
1342 {
1343 return kStatus_LPI2C_Busy;
1344 }
1345
1346 /* Return an error if the bus is already in use not by us. */
1347 status = LPI2C_SlaveGetStatusFlags(base);
1348 if ((status & kLPI2C_SlaveBusBusyFlag) && (!(status & kLPI2C_SlaveBusyFlag)))
1349 {
1350 return kStatus_LPI2C_Busy;
1351 }
1352
1353 /* Disable LPI2C IRQ sources while we configure stuff. */
1354 LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1355
1356 /* Clear transfer in handle. */
1357 memset(&handle->transfer, 0, sizeof(handle->transfer));
1358
1359 /* Record that we're busy. */
1360 handle->isBusy = true;
1361
1362 /* Set up event mask. tx and rx are always enabled. */
1363 handle->eventMask = eventMask | kLPI2C_SlaveTransmitEvent | kLPI2C_SlaveReceiveEvent;
1364
1365 /* Ack by default. */
1366 base->STAR = 0;
1367
1368 /* Clear all flags. */
1369 LPI2C_SlaveClearStatusFlags(base, kSlaveClearFlags);
1370
1371 /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1372 LPI2C_SlaveEnableInterrupts(base, kSlaveIrqFlags);
1373
1374 return kStatus_Success;
1375 }
1376
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)1377 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
1378 {
1379 assert(handle);
1380
1381 if (!count)
1382 {
1383 return kStatus_InvalidArgument;
1384 }
1385
1386 /* Catch when there is not an active transfer. */
1387 if (!handle->isBusy)
1388 {
1389 *count = 0;
1390 return kStatus_NoTransferInProgress;
1391 }
1392
1393 /* For an active transfer, just return the count from the handle. */
1394 *count = handle->transferredCount;
1395
1396 return kStatus_Success;
1397 }
1398
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)1399 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
1400 {
1401 assert(handle);
1402
1403 /* Return idle if no transaction is in progress. */
1404 if (handle->isBusy)
1405 {
1406 /* Disable LPI2C IRQ sources. */
1407 LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1408
1409 /* Nack by default. */
1410 base->STAR = LPI2C_STAR_TXNACK_MASK;
1411
1412 /* Reset transfer info. */
1413 memset(&handle->transfer, 0, sizeof(handle->transfer));
1414
1415 /* We're no longer busy. */
1416 handle->isBusy = false;
1417 }
1418 }
1419
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)1420 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
1421 {
1422 uint32_t flags;
1423 lpi2c_slave_transfer_t *xfer;
1424
1425 /* Check for a valid handle in case of a spurious interrupt. */
1426 if (!handle)
1427 {
1428 return;
1429 }
1430
1431 xfer = &handle->transfer;
1432
1433 /* Get status flags. */
1434 flags = LPI2C_SlaveGetStatusFlags(base);
1435
1436 if (flags & (kLPI2C_SlaveBitErrFlag | kLPI2C_SlaveFifoErrFlag))
1437 {
1438 xfer->event = kLPI2C_SlaveCompletionEvent;
1439 xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
1440
1441 if ((handle->eventMask & kLPI2C_SlaveCompletionEvent) && (handle->callback))
1442 {
1443 handle->callback(base, xfer, handle->userData);
1444 }
1445 return;
1446 }
1447 if (flags & (kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag))
1448 {
1449 xfer->event = (flags & kLPI2C_SlaveRepeatedStartDetectFlag) ? kLPI2C_SlaveRepeatedStartEvent :
1450 kLPI2C_SlaveCompletionEvent;
1451 xfer->receivedAddress = 0;
1452 xfer->completionStatus = kStatus_Success;
1453 xfer->transferredCount = handle->transferredCount;
1454
1455 if (xfer->event == kLPI2C_SlaveCompletionEvent)
1456 {
1457 handle->isBusy = false;
1458 }
1459
1460 if (handle->wasTransmit)
1461 {
1462 /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
1463 /* tx flag before it sees the nack from the master-receiver, thus causing one more */
1464 /* count that the master actually receives. */
1465 --xfer->transferredCount;
1466 handle->wasTransmit = false;
1467 }
1468
1469 /* Clear the flag. */
1470 LPI2C_SlaveClearStatusFlags(base, flags & (kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag));
1471
1472 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
1473 base->STAR = 0;
1474
1475 if ((handle->eventMask & xfer->event) && (handle->callback))
1476 {
1477 handle->callback(base, xfer, handle->userData);
1478 }
1479
1480 /* Clean up transfer info on completion, after the callback has been invoked. */
1481 memset(&handle->transfer, 0, sizeof(handle->transfer));
1482 }
1483 if (flags & kLPI2C_SlaveAddressValidFlag)
1484 {
1485 xfer->event = kLPI2C_SlaveAddressMatchEvent;
1486 xfer->receivedAddress = base->SASR & LPI2C_SASR_RADDR_MASK;
1487
1488 if ((handle->eventMask & kLPI2C_SlaveAddressMatchEvent) && (handle->callback))
1489 {
1490 handle->callback(base, xfer, handle->userData);
1491 }
1492 }
1493 if (flags & kLPI2C_SlaveTransmitAckFlag)
1494 {
1495 xfer->event = kLPI2C_SlaveTransmitAckEvent;
1496
1497 if ((handle->eventMask & kLPI2C_SlaveTransmitAckEvent) && (handle->callback))
1498 {
1499 handle->callback(base, xfer, handle->userData);
1500 }
1501 }
1502
1503 /* Handle transmit and receive. */
1504 if (flags & kLPI2C_SlaveTxReadyFlag)
1505 {
1506 handle->wasTransmit = true;
1507
1508 /* If we're out of data, invoke callback to get more. */
1509 if ((!xfer->data) || (!xfer->dataSize))
1510 {
1511 xfer->event = kLPI2C_SlaveTransmitEvent;
1512 if (handle->callback)
1513 {
1514 handle->callback(base, xfer, handle->userData);
1515 }
1516
1517 /* Clear the transferred count now that we have a new buffer. */
1518 handle->transferredCount = 0;
1519 }
1520
1521 /* Transmit a byte. */
1522 if ((xfer->data) && (xfer->dataSize))
1523 {
1524 base->STDR = *xfer->data++;
1525 --xfer->dataSize;
1526 ++handle->transferredCount;
1527 }
1528 }
1529 if (flags & kLPI2C_SlaveRxReadyFlag)
1530 {
1531 /* If we're out of room in the buffer, invoke callback to get another. */
1532 if ((!xfer->data) || (!xfer->dataSize))
1533 {
1534 xfer->event = kLPI2C_SlaveReceiveEvent;
1535 if (handle->callback)
1536 {
1537 handle->callback(base, xfer, handle->userData);
1538 }
1539
1540 /* Clear the transferred count now that we have a new buffer. */
1541 handle->transferredCount = 0;
1542 }
1543
1544 /* Receive a byte. */
1545 if ((xfer->data) && (xfer->dataSize))
1546 {
1547 *xfer->data++ = base->SRDR;
1548 --xfer->dataSize;
1549 ++handle->transferredCount;
1550 }
1551 else
1552 {
1553 /* We don't have any room to receive more data, so send a nack. */
1554 base->STAR = LPI2C_STAR_TXNACK_MASK;
1555 }
1556 }
1557 }
1558
1559 /*!
1560 * @brief Shared IRQ handler that can call both master and slave ISRs.
1561 *
1562 * The master and slave ISRs are called through function pointers in order to decouple
1563 * this code from the ISR functions. Without this, the linker would always pull in both
1564 * ISRs and every function they call, even if only the functional API was used.
1565 *
1566 * @param base The LPI2C peripheral base address.
1567 * @param instance The LPI2C peripheral instance number.
1568 */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)1569 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
1570 {
1571 /* Check for master IRQ. */
1572 if ((base->MCR & LPI2C_MCR_MEN_MASK) && s_lpi2cMasterIsr)
1573 {
1574 /* Master mode. */
1575 s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
1576 }
1577
1578 /* Check for slave IRQ. */
1579 if ((base->SCR & LPI2C_SCR_SEN_MASK) && s_lpi2cSlaveIsr)
1580 {
1581 /* Slave mode. */
1582 s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
1583 }
1584 }
1585
1586 #if defined(LPI2C0)
1587 /* Implementation of LPI2C0 handler named in startup code. */
LPI2C0_DriverIRQHandler(void)1588 void LPI2C0_DriverIRQHandler(void)
1589 {
1590 LPI2C_CommonIRQHandler(LPI2C0, 0);
1591 }
1592 #endif
1593
1594 #if defined(LPI2C1)
1595 /* Implementation of LPI2C1 handler named in startup code. */
LPI2C1_DriverIRQHandler(void)1596 void LPI2C1_DriverIRQHandler(void)
1597 {
1598 LPI2C_CommonIRQHandler(LPI2C1, 1);
1599 }
1600 #endif
1601
1602 #if defined(LPI2C2)
1603 /* Implementation of LPI2C2 handler named in startup code. */
LPI2C2_DriverIRQHandler(void)1604 void LPI2C2_DriverIRQHandler(void)
1605 {
1606 LPI2C_CommonIRQHandler(LPI2C2, 2);
1607 }
1608 #endif
1609
1610 #if defined(LPI2C3)
1611 /* Implementation of LPI2C3 handler named in startup code. */
LPI2C3_DriverIRQHandler(void)1612 void LPI2C3_DriverIRQHandler(void)
1613 {
1614 LPI2C_CommonIRQHandler(LPI2C3, 3);
1615 }
1616 #endif
1617
1618 #if defined(CM4_0_LPI2C)
1619 /* Implementation of CM4_0_LPI2C handler named in startup code. */
M4_0_LPI2C_IRQHandler(void)1620 void M4_0_LPI2C_IRQHandler(void)
1621 {
1622 LPI2C_CommonIRQHandler(CM4_0_LPI2C, LPI2C_GetInstance(CM4_0_LPI2C));
1623 }
1624 #endif
1625
1626 #if defined(CM4_1_LPI2C)
1627 /* Implementation of CM4_1_LPI2C handler named in startup code. */
M4_1_LPI2C_IRQHandler(void)1628 void M4_1_LPI2C_IRQHandler(void)
1629 {
1630 LPI2C_CommonIRQHandler(CM4_1_LPI2C, LPI2C_GetInstance(CM4_1_LPI2C));
1631 }
1632 #endif
1633
1634 #if defined(DMA_LPI2C0)
1635 /* Implementation of DMA_LPI2C0 handler named in startup code. */
DMA_I2C0_INT_IRQHandler(void)1636 void DMA_I2C0_INT_IRQHandler(void)
1637 {
1638 LPI2C_CommonIRQHandler(DMA_LPI2C0, LPI2C_GetInstance(DMA_LPI2C0));
1639 }
1640 #endif
1641
1642 #if defined(DMA_LPI2C1)
1643 /* Implementation of DMA_LPI2C1 handler named in startup code. */
DMA_I2C1_INT_IRQHandler(void)1644 void DMA_I2C1_INT_IRQHandler(void)
1645 {
1646 LPI2C_CommonIRQHandler(DMA_LPI2C1, LPI2C_GetInstance(DMA_LPI2C1));
1647 }
1648 #endif
1649
1650 #if defined(DMA_LPI2C2)
1651 /* Implementation of DMA_LPI2C2 handler named in startup code. */
DMA_I2C2_INT_IRQHandler(void)1652 void DMA_I2C2_INT_IRQHandler(void)
1653 {
1654 LPI2C_CommonIRQHandler(DMA_LPI2C2, LPI2C_GetInstance(DMA_LPI2C2));
1655 }
1656 #endif
1657
1658 #if defined(DMA_LPI2C3)
1659 /* Implementation of DMA_LPI2C3 handler named in startup code. */
DMA_I2C3_INT_IRQHandler(void)1660 void DMA_I2C3_INT_IRQHandler(void)
1661 {
1662 LPI2C_CommonIRQHandler(DMA_LPI2C3, LPI2C_GetInstance(DMA_LPI2C3));
1663 }
1664 #endif
1665
1666 #if defined(DMA_LPI2C4)
1667 /* Implementation of DMA_LPI2C3 handler named in startup code. */
DMA_I2C4_INT_IRQHandler(void)1668 void DMA_I2C4_INT_IRQHandler(void)
1669 {
1670 LPI2C_CommonIRQHandler(DMA_LPI2C4, LPI2C_GetInstance(DMA_LPI2C4));
1671 }
1672 #endif
1673