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