1 /***************************************************************************//**
2 * \file cy_scb_i2c.c
3 * \version 3.20
4 *
5 * Provides I2C API implementation of the SCB driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2021 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include "cy_device.h"
26
27 #if (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB))
28
29 #include "cy_scb_i2c.h"
30
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34
35 /***************************************
36 * Function Prototypes
37 ***************************************/
38
39 static void SlaveHandleAddress (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
40 static void SlaveHandleDataReceive (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
41 static void SlaveHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
42 static void SlaveHandleStop (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
43
44 static void MasterHandleEvents (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
45 static void MasterHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
46 static void MasterHandleDataReceive (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
47 static void MasterHandleStop (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
48 static void MasterHandleComplete (CySCB_Type *base, cy_stc_scb_i2c_context_t *context);
49
50 static cy_en_scb_i2c_status_t HandleStatus(CySCB_Type *base, uint32_t status,
51 cy_stc_scb_i2c_context_t *context);
52 static uint32_t WaitOneUnit(uint32_t *timeout);
53
54
55 /*******************************************************************************
56 * Function Name: Cy_SCB_I2C_Init
57 ****************************************************************************//**
58 *
59 * Initializes the SCB for the I2C operation.
60 *
61 * \param base
62 * The pointer to the I2C SCB instance.
63 *
64 * \param config
65 * The pointer to the configuration structure \ref cy_stc_scb_i2c_config_t.
66 *
67 * \param context
68 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
69 * by the user. The structure is used during the I2C operation for internal
70 * configuration and data retention. The user must not modify anything
71 * in this structure.
72 *
73 * \return
74 * \ref cy_en_scb_i2c_status_t
75 *
76 * \note
77 * If SCB is already enabled, ensure that the SCB block is disabled \ref Cy_SCB_I2C_Disable
78 * before calling this function.
79 *******************************************************************************/
Cy_SCB_I2C_Init(CySCB_Type * base,cy_stc_scb_i2c_config_t const * config,cy_stc_scb_i2c_context_t * context)80 cy_en_scb_i2c_status_t Cy_SCB_I2C_Init(CySCB_Type *base, cy_stc_scb_i2c_config_t const *config, cy_stc_scb_i2c_context_t *context)
81 {
82 /* Input parameters verification */
83 if ((NULL == base) || (NULL == config) || (NULL == context))
84 {
85 return CY_SCB_I2C_BAD_PARAM;
86 }
87
88 CY_ASSERT_L3(CY_SCB_I2C_IS_MODE_VALID(config->i2cMode));
89 CY_ASSERT_L2((config->useRxFifo) ? (!config->acceptAddrInFifo) : true);
90 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID (config->slaveAddress));
91 CY_ASSERT_L2(CY_SCB_I2C_IS_ADDR_MASK_VALID(config->slaveAddressMask));
92 CY_ASSERT_L2(CY_SCB_I2C_IS_PHASE_OVERSAMPLE_VALID(config->highPhaseDutyCycle));
93 CY_ASSERT_L2(CY_SCB_I2C_IS_PHASE_OVERSAMPLE_VALID(config->lowPhaseDutyCycle));
94
95 /* Configure the I2C interface */
96 SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, config->acceptAddrInFifo) |
97 _BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep);
98 #if(defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION==1))
99 SCB_CTRL(base) |= SCB_CTRL_BYTE_MODE_Msk;
100 #endif /* CY_IP_MXSCB_VERSION */
101
102 SCB_I2C_CTRL(base) = _BOOL2FLD(SCB_I2C_CTRL_S_GENERAL_IGNORE, !config->ackGeneralAddr) |
103 _VAL2FLD(SCB_I2C_CTRL_HIGH_PHASE_OVS, (config->highPhaseDutyCycle - 1U)) |
104 _VAL2FLD(SCB_I2C_CTRL_LOW_PHASE_OVS, (config->lowPhaseDutyCycle - 1U)) |
105 _VAL2FLD(CY_SCB_I2C_CTRL_MODE, (uint32_t) config->i2cMode);
106
107 {
108 /* Enable digital filter for only for master modes */
109 bool enableDigFilter = (CY_SCB_I2C_SLAVE != config->i2cMode) && (config->enableDigitalFilter);
110
111 /* Configure the RX direction */
112 SCB_RX_CTRL(base) = _BOOL2FLD(SCB_RX_CTRL_MEDIAN, enableDigFilter) |
113 CY_SCB_I2C_RX_CTRL;
114
115 /* Configure an analog filter */
116 SCB_I2C_CFG(base) = (enableDigFilter) ? CY_SCB_I2C_DISABLE_ANALOG_FITLER : CY_SCB_I2C_ENABLE_ANALOG_FITLER;
117 }
118
119 SCB_RX_FIFO_CTRL(base) = (config->useRxFifo ? (CY_SCB_I2C_FIFO_SIZE - 1UL) : 0UL);
120
121 /* Set the default address and mask */
122 SCB_RX_MATCH(base) = _VAL2FLD(SCB_RX_MATCH_ADDR, ((uint32_t) config->slaveAddress << 1UL)) |
123 _VAL2FLD(SCB_RX_MATCH_MASK, (uint32_t) config->slaveAddressMask);
124
125 /* Configure the TX direction */
126 SCB_TX_CTRL(base) = CY_SCB_I2C_TX_CTRL;
127 SCB_TX_FIFO_CTRL(base) = (config->useTxFifo ? CY_SCB_I2C_HALF_FIFO_SIZE : 1UL);
128
129 /* Configure interrupt sources */
130 SCB_INTR_SPI_EC_MASK(base) = 0UL;
131 SCB_INTR_I2C_EC_MASK(base) = 0UL;
132 SCB_INTR_RX_MASK(base) = 0UL;
133 SCB_INTR_TX_MASK(base) = 0UL;
134 SCB_INTR_M_MASK(base) = 0UL;
135
136 SCB_INTR_S_MASK(base) = (CY_SCB_I2C_MASTER != config->i2cMode) ? CY_SCB_I2C_SLAVE_INTR : 0UL;
137
138 /* Initialize the context */
139 context->useRxFifo = config->useRxFifo;
140 context->useTxFifo = config->useTxFifo;
141
142 context->state = CY_SCB_I2C_IDLE;
143
144 /* Master-specific */
145 context->masterStatus = 0UL;
146 context->masterBufferIdx = 0UL;
147
148 /* Slave-specific */
149 context->slaveStatus = 0UL;
150
151 context->slaveRxBufferIdx = 0UL;
152 context->slaveRxBufferSize = 0UL;
153
154 context->slaveTxBufferIdx = 0UL;
155 context->slaveTxBufferSize = 0UL;
156
157 /* Unregister callbacks */
158 context->cbEvents = NULL;
159 context->cbAddr = NULL;
160
161 return CY_SCB_I2C_SUCCESS;
162 }
163
164
165 /*******************************************************************************
166 * Function Name: Cy_SCB_I2C_DeInit
167 ****************************************************************************//**
168 *
169 * De-initializes the SCB block and returns register values to default.
170 *
171 * \param base
172 * The pointer to the I2C SCB instance.
173 *
174 * \note
175 * Ensure that the SCB block is disabled \ref Cy_SCB_I2C_Disable before calling this function.
176 *
177 *******************************************************************************/
Cy_SCB_I2C_DeInit(CySCB_Type * base)178 void Cy_SCB_I2C_DeInit(CySCB_Type *base)
179 {
180 /* Returns block registers into the default state */
181 SCB_CTRL(base) = CY_SCB_CTRL_DEF_VAL;
182 SCB_I2C_CTRL(base) = CY_SCB_I2C_CTRL_DEF_VAL;
183 SCB_I2C_CFG(base) = CY_SCB_I2C_CFG_DEF_VAL;
184
185 SCB_RX_CTRL(base) = CY_SCB_RX_CTRL_DEF_VAL;
186 SCB_RX_FIFO_CTRL(base) = 0UL;
187 SCB_RX_MATCH(base) = 0UL;
188
189 SCB_TX_CTRL(base) = CY_SCB_TX_CTRL_DEF_VAL;
190 SCB_TX_FIFO_CTRL(base) = 0UL;
191
192 SCB_INTR_SPI_EC_MASK(base) = 0UL;
193 SCB_INTR_I2C_EC_MASK(base) = 0UL;
194 SCB_INTR_RX_MASK(base) = 0UL;
195 SCB_INTR_TX_MASK(base) = 0UL;
196 SCB_INTR_M_MASK(base) = 0UL;
197 SCB_INTR_S_MASK(base) = 0UL;
198 }
199
200
201 /*******************************************************************************
202 * Function Name: Cy_SCB_I2C_Disable
203 ****************************************************************************//**
204 *
205 * Disables the SCB block and clears context statuses.
206 * Note that after the block is disabled, the TX and RX FIFOs and hardware
207 * statuses are cleared. Also, the hardware stops driving the output and
208 * ignores the input.
209 *
210 * \param base
211 * The pointer to the I2C SCB instance.
212 *
213 * \param context
214 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
215 * by the user. The structure is used during the I2C operation for internal
216 * configuration and data retention. The user must not modify anything
217 * in this structure.
218 *
219 * \note
220 * Calling this function when I2C is busy (master preforms transaction or slave
221 * was addressed and is communicating with master) may cause transaction corruption
222 * because the hardware stops driving the outputs and ignores the inputs.
223 * Ensure that I2C is not busy before calling this function.
224 *
225 *******************************************************************************/
Cy_SCB_I2C_Disable(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)226 void Cy_SCB_I2C_Disable(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
227 {
228 SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
229
230 /* Set the state to default and clear statuses */
231 context->state = CY_SCB_I2C_IDLE;
232 context->masterStatus = 0UL;
233 context->slaveStatus = 0UL;
234 }
235
236
237 /*******************************************************************************
238 * Function Name: Cy_SCB_I2C_DeepSleepCallback
239 ****************************************************************************//**
240 *
241 * This function handles the transition of the I2C SCB into and out of
242 * Deep Sleep mode. It prevents the device from entering Deep Sleep
243 * mode if the I2C slave or master is actively communicating.
244 * The behavior of the I2C SCB in Deep Sleep depends on whether the SCB block is
245 * wakeup-capable or not:
246 * * <b>Wakeup-capable</b>: during Deep Sleep mode on incoming I2C slave address
247 * the slave receives address and stretches the clock until the device is
248 * awoken from Deep Sleep mode. If the slave address occurs before the device
249 * enters Deep Sleep mode, the device will not enter Deep Sleep mode.
250 * Only the I2C slave can be configured to be a wakeup source from Deep Sleep
251 * mode.
252 * * <b>Not wakeup-capable</b>: the SCB is disabled in Deep Sleep mode.
253 * It is re-enabled if the device fails to enter Deep Sleep mode or when the
254 * device is awoken from Deep Sleep mode. While the SCB is disabled it stops
255 * driving the outputs and ignores the inputs. The slave NACKs all incoming
256 * addresses.
257 *
258 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep.
259 * To do it, register this function as a callback before calling
260 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
261 * type and call \ref Cy_SysPm_RegisterCallback.
262 *
263 * \param callbackParams
264 * The pointer to the callback parameters structure
265 * \ref cy_stc_syspm_callback_params_t.
266 *
267 * \param mode
268 * Callback mode, see \ref cy_en_syspm_callback_mode_t
269 *
270 * \return
271 * \ref cy_en_syspm_status_t
272 *
273 * \note
274 * Only applicable for <b>rev-08 of the CY8CKIT-062-BLE</b>.
275 * For proper operation, when the I2C slave is configured to be a wakeup source
276 * from Deep Sleep mode, this function must be copied and modified by the user.
277 * The I2C clock disable code must be inserted in the \ref CY_SYSPM_BEFORE_TRANSITION
278 * and clock enable code in the \ref CY_SYSPM_AFTER_TRANSITION mode processing.
279 *
280 * Please refer to the section \ref group_scb_i2c_mclk_sync for more information.
281 *
282 *******************************************************************************/
Cy_SCB_I2C_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)283 cy_en_syspm_status_t Cy_SCB_I2C_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
284 {
285 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
286 cy_stc_scb_i2c_context_t *locContext = (cy_stc_scb_i2c_context_t *) callbackParams->context;
287
288 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
289
290 switch(mode)
291 {
292 case CY_SYSPM_CHECK_READY:
293 {
294 /* Disable the slave interrupt sources to protect the state */
295 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
296
297 /* If the I2C is in the IDLE state, it is ready for Deep Sleep mode
298 * (either the master or the slave is not busy),
299 * otherwise return fail and restore the slave interrupt sources.
300 */
301 if (CY_SCB_I2C_IDLE == locContext->state)
302 {
303 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
304 {
305 /* The SCB is wakeup-capable: do not restore the address
306 * match and general call interrupt sources. The next
307 * transaction intended to the slave will be paused
308 * (SCL is stretched) before the address is ACKed because
309 * the corresponding interrupt source is disabled.
310 */
311 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR_NO_ADDR);
312 }
313 else
314 {
315 /* The SCB is NOT wakeup-capable: disable the I2C. The slave
316 * stops responding to the master and the master stops
317 * driving the bus until the I2C is enabled. This happens
318 * when the device failed to enter into Deep Sleep mode or it
319 * is awaken from Deep Sleep mode.
320 */
321 Cy_SCB_I2C_Disable(locBase, locContext);
322 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
323 }
324
325 retStatus = CY_SYSPM_SUCCESS;
326 }
327 else
328 {
329 /* Restore the slave interrupt sources */
330 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
331 }
332 }
333 break;
334
335 case CY_SYSPM_CHECK_FAIL:
336 {
337 /* The other driver is not ready for Deep Sleep mode. Restore
338 * Active mode configuration.
339 */
340
341 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
342 {
343 /* The SCB is wakeup-capable: restore the slave interrupt sources */
344 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
345 }
346 else
347 {
348 /* The SCB is NOT wakeup-capable: enable the I2C to operate */
349 Cy_SCB_I2C_Enable(locBase);
350 }
351
352 retStatus = CY_SYSPM_SUCCESS;
353 }
354 break;
355
356 case CY_SYSPM_BEFORE_TRANSITION:
357 {
358 /* This code executes inside the critical section. Enabling the
359 * active interrupt source makes the interrupt pending in the NVIC.
360 * However, the interrupt processing is delayed until the code exits
361 * the critical section. The pending interrupt force WFI instruction
362 * does nothing and the device remains in Active mode.
363 */
364
365 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
366 {
367 /* The SCB is wakeup-capable: enable the I2C wakeup interrupt
368 * source. If any transaction was paused, the I2C interrupt
369 * becomes pending and prevents entering Deep Sleep mode.
370 * The transaction continues as soon as the global interrupts
371 * are enabled.
372 */
373 Cy_SCB_SetI2CInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
374
375 /* Disable SCB clock */
376 SCB_I2C_CFG(locBase) &= (uint32_t) ~CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
377
378 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
379 * for proper entering Deep Sleep mode the I2C clock must be disabled.
380 * This code must be inserted by the user because the driver
381 * does not have access to the clock.
382 */
383 }
384
385 retStatus = CY_SYSPM_SUCCESS;
386 }
387 break;
388
389 case CY_SYSPM_AFTER_TRANSITION:
390 {
391 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
392 {
393 /* Enable SCB clock */
394 SCB_I2C_CFG(locBase) |= CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
395
396 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
397 * for proper exiting Deep Sleep, the I2C clock must be enabled.
398 * This code must be inserted by the user because the driver
399 * does not have access to the clock.
400 */
401
402 /* The SCB is wakeup-capable: disable the I2C wakeup interrupt
403 * source and restore slave interrupt sources.
404 */
405 Cy_SCB_SetI2CInterruptMask (locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
406 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
407 }
408 else
409 {
410 /* The SCB is NOT wakeup-capable: enable the I2C to operate */
411 Cy_SCB_I2C_Enable(locBase);
412 }
413
414 retStatus = CY_SYSPM_SUCCESS;
415 }
416 break;
417
418 default:
419 /* Unknown state */
420 break;
421 }
422
423 return (retStatus);
424 }
425
426
427 /*******************************************************************************
428 * Function Name: Cy_SCB_I2C_HibernateCallback
429 ****************************************************************************//**
430 *
431 * This function handles the transition of the I2C SCB block into Hibernate
432 * mode. It prevents the device from entering Hibernate mode if the I2C slave or
433 * master is actively communicating.
434 * If the I2C is ready to enter Hibernate mode it is disabled. If the device
435 * failed to enter Hibernate mode, the SCB is enabled. After the SCB is disabled,
436 * it stops driving the outputs and ignores the inputs. The slave NACKs all
437 * incoming addresses.
438 *
439 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
440 * To do it, register this function as a callback before calling
441 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
442 * type and call \ref Cy_SysPm_RegisterCallback.
443 *
444 * \param callbackParams
445 * The pointer to the callback parameters structure
446 * \ref cy_stc_syspm_callback_params_t.
447 *
448 * \param mode
449 * Callback mode, see \ref cy_en_syspm_callback_mode_t
450 *
451 * \return
452 * \ref cy_en_syspm_status_t
453 *
454 *******************************************************************************/
Cy_SCB_I2C_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)455 cy_en_syspm_status_t Cy_SCB_I2C_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
456 {
457 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
458 cy_stc_scb_i2c_context_t *locContext = (cy_stc_scb_i2c_context_t *) callbackParams->context;
459
460 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
461
462 switch(mode)
463 {
464 case CY_SYSPM_CHECK_READY:
465 {
466 /* Disable the slave interrupt sources to protect the state */
467 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
468
469 /* If the I2C is in the IDLE state, it is ready for Hibernate mode
470 * (either the master or the slave is not busy).
471 * Otherwise, return fail and restore the slave interrupt sources.
472 */
473 if (CY_SCB_I2C_IDLE == locContext->state)
474 {
475 /* Disable the I2C. The slave stops responding to the master and
476 * the master stops driving the bus until the I2C is enabled.
477 * This happens if the device failed to enter Hibernate mode.
478 */
479 Cy_SCB_I2C_Disable(locBase, locContext);
480
481 retStatus = CY_SYSPM_SUCCESS;
482 }
483
484 /* Restore the slave interrupt sources */
485 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_I2C_SLAVE_INTR);
486 }
487 break;
488
489 case CY_SYSPM_CHECK_FAIL:
490 {
491 /* The other driver is not ready for Hibernate mode. Restore the
492 * Active mode configuration.
493 */
494
495 /* Enable the I2C to operate */
496 Cy_SCB_I2C_Enable(locBase);
497
498 retStatus = CY_SYSPM_SUCCESS;
499 }
500 break;
501
502 case CY_SYSPM_BEFORE_TRANSITION:
503 case CY_SYSPM_AFTER_TRANSITION:
504 {
505 /* The SCB is not capable of waking up from Hibernate mode: do nothing */
506 retStatus = CY_SYSPM_SUCCESS;
507 }
508 break;
509
510 default:
511 /* Unknown state */
512 break;
513 }
514
515 return (retStatus);
516 }
517
518
519 /*******************************************************************************
520 * Function Name: Cy_SCB_I2C_SetDataRate
521 ****************************************************************************//**
522 *
523 * Configures the SCB to work at the desired data rate.
524 *
525 * \param base
526 * The pointer to the I2C SCB instance.
527 *
528 * \param dataRateHz
529 * The desired data Rate in Hz.
530 *
531 * \param scbClockHz
532 * The frequency of the clock connected to the SCB in Hz.
533 *
534 * \return
535 * The achieved data rate in Hz. \n
536 * When zero value is returned there is an error in the input parameters:
537 * data rate or clk_scb is out of valid range.
538 *
539 * \note
540 * This function does not change the values of the clock divider connected
541 * to the SCB, it changes only the SCB clock oversample registers. If this
542 * function is not able to achieve the desired data rate, then the clock
543 * divider must be adjusted. Call this function only while the SCB is
544 * disabled. For the slave, this function only checks that the attached clock is
545 * fast enough to meet the desired data rate. It does not change any registers.
546 *
547 *******************************************************************************/
Cy_SCB_I2C_SetDataRate(CySCB_Type * base,uint32_t dataRateHz,uint32_t scbClockHz)548 uint32_t Cy_SCB_I2C_SetDataRate(CySCB_Type *base, uint32_t dataRateHz, uint32_t scbClockHz)
549 {
550 CY_ASSERT_L2(scbClockHz > 0UL);
551 CY_ASSERT_L2(CY_SCB_I2C_IS_DATA_RATE_VALID(dataRateHz));
552
553 uint32_t actualDataRateHz = 0UL;
554
555 if (((uint32_t) CY_SCB_I2C_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
556 {
557 actualDataRateHz = Cy_SCB_I2C_GetDataRate(base, scbClockHz);
558
559 /* Use an analog filter for the slave */
560 SCB_RX_CTRL(base) &= (uint32_t) ~SCB_RX_CTRL_MEDIAN_Msk;
561 SCB_I2C_CFG(base) = CY_SCB_I2C_ENABLE_ANALOG_FITLER;
562 }
563 else
564 {
565 bool errorRange = true;
566 uint32_t sclLow;
567 uint32_t sclHigh;
568
569 uint32_t lowPhase = 8U;
570 uint32_t highPhase = 8U;
571 bool enableMedian = false;
572
573 /* Get duration of SCL low and high for the selected data rate */
574 if ((0U == dataRateHz) || (dataRateHz > CY_SCB_I2C_FSTP_DATA_RATE))
575 {
576 errorRange = true;
577 }
578 else if (dataRateHz <= CY_SCB_I2C_STD_DATA_RATE)
579 {
580 /* Check SCB clock ranges for Standard rate */
581 if ((scbClockHz >= CY_SCB_I2C_MASTER_STD_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_STD_CLK_MAX))
582 {
583 sclLow = CY_SCB_I2C_MASTER_STD_SCL_LOW;
584 sclHigh = CY_SCB_I2C_MASTER_STD_SCL_HIGH;
585 enableMedian = false;
586
587 errorRange = false;
588 }
589 }
590 else if (dataRateHz <= CY_SCB_I2C_FST_DATA_RATE)
591 {
592 /* Check SCB clock ranges for Fast rate */
593 if ((scbClockHz >= CY_SCB_I2C_MASTER_FST_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_FST_CLK_MAX))
594 {
595 sclLow = CY_SCB_I2C_MASTER_FST_SCL_LOW;
596 sclHigh = CY_SCB_I2C_MASTER_FST_SCL_HIGH;
597 enableMedian = false;
598
599 errorRange = false;
600 }
601 }
602 else
603 {
604 /* Check SCB clock ranges for Fast rate */
605 if ((scbClockHz >= CY_SCB_I2C_MASTER_FSTP_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_MASTER_FSTP_CLK_MAX))
606 {
607 /* Check SCB clock ranges for Fast rate */
608 sclLow = CY_SCB_I2C_MASTER_FSTP_SCL_LOW;
609 sclHigh = CY_SCB_I2C_MASTER_FSTP_SCL_HIGH;
610 enableMedian = true;
611
612 errorRange = false;
613 }
614 }
615
616 /* Calculate data rate if data rate and clock ranges are valid */
617 if (!errorRange)
618 {
619 bool updateLowPhase;
620
621 /* Get period of the SCB clock in ns */
622 uint32_t period = 1000000000U / scbClockHz;
623
624 /* Get low phase minimum value in SCB clocks */
625 lowPhase = sclLow / period;
626
627 if ((period * lowPhase) < sclLow)
628 {
629 ++lowPhase;
630 }
631
632 if (lowPhase > CY_SCB_I2C_LOW_PHASE_MAX)
633 {
634 lowPhase = CY_SCB_I2C_LOW_PHASE_MAX;
635 }
636
637 /* Define if update low phase */
638 updateLowPhase = (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX);
639
640 /* Get high phase minimum value in SCB clocks */
641 highPhase = sclHigh / period;
642
643 if ((period * highPhase) < sclHigh)
644 {
645 ++highPhase;
646 }
647
648 if (highPhase > CY_SCB_I2C_HIGH_PHASE_MAX)
649 {
650 highPhase = CY_SCB_I2C_HIGH_PHASE_MAX;
651 }
652
653 /* Get actual data rate */
654 actualDataRateHz = scbClockHz / (lowPhase + highPhase);
655
656 /* Find desired data rate */
657 while ((actualDataRateHz > dataRateHz) && ((lowPhase + highPhase) < CY_SCB_I2C_DUTY_CYCLE_MAX))
658 {
659 /* Increase low and high phase to reach desired data rate */
660 if (updateLowPhase)
661 {
662 if (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX)
663 {
664 /* Update low phase */
665 lowPhase++;
666 updateLowPhase = false;
667 }
668 }
669 else
670 {
671 if (highPhase < CY_SCB_I2C_HIGH_PHASE_MAX)
672 {
673 /* Update high phase */
674 highPhase++;
675 updateLowPhase = (lowPhase < CY_SCB_I2C_LOW_PHASE_MAX);
676 }
677 }
678
679 /* Update actual data rate */
680 actualDataRateHz = scbClockHz / (lowPhase + highPhase);
681 }
682
683 /* Set filter configuration based on actual data rate */
684 if (enableMedian)
685 {
686 /* Use a digital filter */
687 SCB_RX_CTRL(base) |= (uint32_t) SCB_RX_CTRL_MEDIAN_Msk;
688 SCB_I2C_CFG(base) = CY_SCB_I2C_DISABLE_ANALOG_FITLER;
689 }
690 else
691 {
692 /* Use an analog filter */
693 SCB_RX_CTRL(base) &= (uint32_t) ~SCB_RX_CTRL_MEDIAN_Msk;
694 SCB_I2C_CFG(base) = CY_SCB_I2C_ENABLE_ANALOG_FITLER;
695 }
696
697 /* Set phase low and high */
698 Cy_SCB_I2C_MasterSetLowPhaseDutyCycle (base, lowPhase);
699 Cy_SCB_I2C_MasterSetHighPhaseDutyCycle(base, highPhase);
700 }
701 }
702
703 return (actualDataRateHz);
704 }
705
706
707 /*******************************************************************************
708 * Function Name: Cy_SCB_I2C_GetDataRate
709 ****************************************************************************//**
710 *
711 * Returns the data rate for the selected SCB block.
712 *
713 * \param base
714 * The pointer to the I2C SCB instance.
715 *
716 * \param scbClockHz
717 * The frequency of the clock connected to the SCB in Hz.
718 *
719 * \return
720 * The data rate in Hz. \n
721 * For slave mode when zero value is returned the clk_scb is out of valid
722 * range.
723 *
724 *******************************************************************************/
Cy_SCB_I2C_GetDataRate(CySCB_Type const * base,uint32_t scbClockHz)725 uint32_t Cy_SCB_I2C_GetDataRate(CySCB_Type const *base, uint32_t scbClockHz)
726 {
727 CY_ASSERT_L2(scbClockHz > 0UL);
728
729 uint32_t actualDataRate = 0UL;
730
731 if (((uint32_t) CY_SCB_I2C_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
732 {
733 /* Check the clock frequency range to get maximum supported data rate */
734 if ((scbClockHz >= CY_SCB_I2C_SLAVE_FST_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_FST_CLK_MAX))
735 {
736 actualDataRate = CY_SCB_I2C_FST_DATA_RATE;
737 }
738 else if ((scbClockHz >= CY_SCB_I2C_SLAVE_STD_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_STD_CLK_MAX))
739 {
740 actualDataRate = CY_SCB_I2C_STD_DATA_RATE;
741 }
742 else if ((scbClockHz >= CY_SCB_I2C_SLAVE_FSTP_CLK_MIN) && (scbClockHz <= CY_SCB_I2C_SLAVE_FSTP_CLK_MAX))
743 {
744 actualDataRate = CY_SCB_I2C_FSTP_DATA_RATE;
745 }
746 else
747 {
748 /* The clock frequency is too low or it gets to the gap between
749 * Fast and Fast Plus data rates.
750 */
751 actualDataRate = 0UL;
752 }
753 }
754 else
755 {
756 if (scbClockHz > 0U)
757 {
758 uint32_t dutyCycle;
759
760 /* Get number of clocks in one SCL period */
761 dutyCycle = _FLD2VAL(SCB_I2C_CTRL_LOW_PHASE_OVS, SCB_I2C_CTRL(base)) +
762 _FLD2VAL(SCB_I2C_CTRL_HIGH_PHASE_OVS, SCB_I2C_CTRL(base)) +
763 2UL;
764
765 /* Calculate the actual data rate */
766 actualDataRate = (scbClockHz / dutyCycle);
767 }
768 }
769
770 return (actualDataRate);
771 }
772
773
774 /*******************************************************************************
775 * I2C Slave API
776 *******************************************************************************/
777
778 /*******************************************************************************
779 * Function Name: Cy_SCB_I2C_SlaveGetStatus
780 ****************************************************************************//**
781 *
782 * Returns the current I2C slave status.
783 * This status is a bit mask and the value returned may have multiple bits set.
784 *
785 * \param base
786 * The pointer to the I2C SCB instance.
787 *
788 * \param context
789 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
790 * by the user. The structure is used during the I2C operation for internal
791 * configuration and data retention. The user must not modify anything
792 * in this structure.
793 *
794 * \return
795 * \ref group_scb_i2c_macros_slave_status.
796 *
797 *******************************************************************************/
Cy_SCB_I2C_SlaveGetStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)798 uint32_t Cy_SCB_I2C_SlaveGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
799 {
800 /* Suppress a compiler warning about unused variables */
801 (void) base;
802
803 return (context->slaveStatus);
804 }
805
806
807 /*******************************************************************************
808 * Function Name: Cy_SCB_I2C_SlaveConfigReadBuf
809 ****************************************************************************//**
810 *
811 * Configures the buffer pointer and the read buffer size. This is the buffer
812 * from which the master reads data. After this function is called, data
813 * transfer from the read buffer to the master is handled by
814 * \ref Cy_SCB_I2C_Interrupt.
815 *
816 * When the Read transaction is completed (master generated Stop, ReStart or
817 * error occurred), the \ref CY_SCB_I2C_SLAVE_RD_BUSY status is cleared and
818 * the \ref CY_SCB_I2C_SLAVE_RD_CMPLT is set. Also
819 * the \ref CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT event is generated.
820 *
821 * \param base
822 * The pointer to the I2C SCB instance.
823 *
824 * \param buffer
825 * The pointer to the buffer with data to be read by the master.
826 *
827 * \param size
828 * Size of the buffer.
829 *
830 * \param context
831 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
832 * by the user. The structure is used during the I2C operation for internal
833 * configuration and data retention. The user must not modify anything
834 * in this structure.
835 *
836 * \note
837 * * The Read buffer must not be modified and stay allocated until it has been
838 * read by the master.
839 * * If this function has not been called, and the master tries to read data
840 * from the slave a \ref CY_SCB_I2C_DEFAULT_TX is returned to the master.
841 * * If the master tries to read more bytes than available in the Read buffer,
842 * a \ref CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT event occurs. The
843 * \ref CY_SCB_I2C_DEFAULT_TX is returned to the master if the buffer remains
844 * empty after an event notification.
845 *
846 *******************************************************************************/
Cy_SCB_I2C_SlaveConfigReadBuf(CySCB_Type const * base,uint8_t * buffer,uint32_t size,cy_stc_scb_i2c_context_t * context)847 void Cy_SCB_I2C_SlaveConfigReadBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size,
848 cy_stc_scb_i2c_context_t *context)
849 {
850 CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
851
852 /* Suppress a compiler warning about unused variables */
853 (void) base;
854
855 context->slaveTxBuffer = buffer;
856 context->slaveTxBufferSize = size;
857 context->slaveTxBufferIdx = 0UL;
858 context->slaveTxBufferCnt = 0UL;
859 }
860
861
862 /*******************************************************************************
863 * Function Name: Cy_SCB_I2C_SlaveAbortRead
864 ****************************************************************************//**
865 *
866 * Aborts the configured slave read buffer to be read by the master.
867 * If the master reads and "abort operation" is requested, the
868 * \ref CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT event occurs. The
869 * \ref CY_SCB_I2C_DEFAULT_TX is returned to the master if the buffer remains
870 * empty after the event notification.
871 *
872 * \param base
873 * The pointer to the I2C SCB instance.
874 *
875 * \param context
876 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
877 * by the user. The structure is used during the I2C operation for internal
878 * configuration and data retention. The user must not modify anything
879 * in this structure.
880 *
881 * \sideeffect
882 * If the TX FIFO is used, this function clears it.
883 * The TX FIFO clear operation also clears the shift register, thus
884 * the shifter can be cleared in the middle of a data element transfer,
885 * corrupting it. The data element corruption means that all bits that have
886 * not been transmitted are transmitted as "ones" on the bus.
887 *
888 *******************************************************************************/
Cy_SCB_I2C_SlaveAbortRead(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)889 void Cy_SCB_I2C_SlaveAbortRead(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
890 {
891 uint32_t intrState;
892
893 /* Suppress a compiler warning about unused variables */
894 (void) base;
895
896 intrState = Cy_SysLib_EnterCriticalSection();
897
898 /* Reset index to make write buffer empty */
899 context->slaveTxBufferSize = 0UL;
900
901 if ((context->useTxFifo) &&
902 (0UL != (CY_SCB_I2C_SLAVE_RD_BUSY & context->slaveStatus)))
903 {
904 /* Clear TX FIFO from available data */
905 Cy_SCB_ClearTxFifo(base);
906 }
907
908 Cy_SysLib_ExitCriticalSection(intrState);
909 }
910
911
912 /*******************************************************************************
913 * Function Name: Cy_SCB_I2C_SlaveGetReadTransferCount
914 ****************************************************************************//**
915 *
916 * Returns the number of bytes read by the master since the last time
917 * \ref Cy_SCB_I2C_SlaveConfigReadBuf was called.
918 *
919 * \param base
920 * The pointer to the I2C SCB instance.
921 *
922 * \param context
923 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
924 * by the user. The structure is used during the I2C operation for internal
925 * configuration and data retention. The user must not modify anything
926 * in this structure.
927 *
928 * \return
929 * The number of bytes read by the master.
930 *
931 * \note
932 * * This function returns an invalid value if a read transaction was
933 * aborted or any listed event occurs during the transaction:
934 * \ref CY_SCB_I2C_SLAVE_ARB_LOST, \ref CY_SCB_I2C_SLAVE_BUS_ERR.
935 * * This number is updated only when a transaction completes, either through
936 * an error or successfully.
937 *
938 *******************************************************************************/
Cy_SCB_I2C_SlaveGetReadTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)939 uint32_t Cy_SCB_I2C_SlaveGetReadTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
940 {
941 /* Suppress a compiler warning about unused variables */
942 (void) base;
943
944 return (context->slaveTxBufferCnt);
945 }
946
947
948 /*******************************************************************************
949 * Function Name: Cy_SCB_I2C_SlaveClearReadStatus
950 ****************************************************************************//**
951 *
952 * Clears the read status and error conditions flags and returns their values.
953 *
954 * \param base
955 * The pointer to the I2C SCB instance.
956 *
957 * \param context
958 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
959 * by the user. The structure is used during the I2C operation for internal
960 * configuration and data retention. The user must not modify anything
961 * in this structure.
962 *
963 * \return
964 * \ref group_scb_i2c_macros_slave_status.
965 *
966 * \note
967 * The \ref CY_SCB_I2C_SLAVE_RD_BUSY flag is not cleared.
968 *
969 *******************************************************************************/
Cy_SCB_I2C_SlaveClearReadStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t * context)970 uint32_t Cy_SCB_I2C_SlaveClearReadStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t *context)
971 {
972 uint32_t retStatus;
973
974 /* Suppress a compiler warning about unused variables */
975 (void) base;
976
977 retStatus = (context->slaveStatus & CY_SCB_I2C_SLAVE_RD_CLEAR);
978 context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_RD_CLEAR;
979
980 return (retStatus);
981 }
982
983
984 /*******************************************************************************
985 * Function Name: Cy_SCB_I2C_SlaveConfigWriteBuf
986 ****************************************************************************//**
987 *
988 * Configures the buffer pointer and size of the write buffer. This is the buffer
989 * that the master writes data to. After this function is called data transfer
990 * from the master into the write buffer is handled by \ref Cy_SCB_I2C_Interrupt.
991 *
992 * When write transaction is completed (master generated Stop, ReStart or
993 * error occurred) the \ref CY_SCB_I2C_SLAVE_WR_BUSY status is cleared and
994 * the \ref CY_SCB_I2C_SLAVE_WR_CMPLT is set, also
995 * the \ref CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT event is generated.
996 *
997 * \param base
998 * The pointer to the I2C SCB instance.
999 *
1000 * \param buffer
1001 * The pointer to buffer to store data written by the master.
1002 *
1003 * \param size
1004 * Size of the buffer.
1005 *
1006 * \param context
1007 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1008 * by the user. The structure is used during the I2C operation for internal
1009 * configuration and data retention. The user must not modify anything
1010 * in this structure.
1011 *
1012 * \note
1013 * * The write buffer must not be modified and must stay allocated until it has been
1014 * written by the master.
1015 * * If this function has not been called and the master tries to write data,
1016 * the first byte is NAKed and discarded.
1017 * * If the master writes more bytes than the slave can store in the write buffer,
1018 * the \ref CY_SCB_I2C_SLAVE_WR_OVRFL status is set and the slave will NACK last
1019 * byte, unless the RX FIFO is used. Then the slave will NAK only after
1020 * RX FIFO becomes full.
1021 * * If the RX FIFO is used, the minimum write buffer size is automatically
1022 * the size of the RX FIFO. If a write buffer is less than the RX FIFO size, extra
1023 * bytes are ACKed and stored into RX FIFO but ignored by firmware.
1024 *
1025 *******************************************************************************/
Cy_SCB_I2C_SlaveConfigWriteBuf(CySCB_Type const * base,uint8_t * buffer,uint32_t size,cy_stc_scb_i2c_context_t * context)1026 void Cy_SCB_I2C_SlaveConfigWriteBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size,
1027 cy_stc_scb_i2c_context_t *context)
1028 {
1029 CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
1030
1031 /* Suppress a compiler warning about unused variables */
1032 (void) base;
1033
1034 context->slaveRxBuffer = buffer;
1035 context->slaveRxBufferSize = size;
1036 context->slaveRxBufferIdx = 0UL;
1037 }
1038
1039
1040 /*******************************************************************************
1041 * Function Name: Cy_SCB_I2C_SlaveAbortWrite
1042 ****************************************************************************//**
1043 *
1044 * Aborts the configured slave write buffer to be written by the master.
1045 * If master writes and an "abort operation" is requested, the next incoming
1046 * byte will be NAKed.
1047 *
1048 * \param base
1049 * The pointer to the I2C SCB instance.
1050 *
1051 * \param context
1052 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1053 * by the user. The structure is used during the I2C operation for internal
1054 * configuration and data retention. The user must not modify anything
1055 * in this structure.
1056 *
1057 * \note
1058 * If the RX FIFO is used, the NAK will not be sent until RX FIFO
1059 * becomes full, however bytes accepted after an abort request are ignored.
1060 *
1061 *******************************************************************************/
Cy_SCB_I2C_SlaveAbortWrite(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1062 void Cy_SCB_I2C_SlaveAbortWrite(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
1063 {
1064 uint32_t intrState;
1065
1066 /* Suppress a compiler warning about unused variables */
1067 (void) base;
1068
1069 intrState = Cy_SysLib_EnterCriticalSection();
1070
1071 /* Reset index to make read buffer empty */
1072 context->slaveRxBufferSize = 0UL;
1073
1074 if ((context->useRxFifo) &&
1075 (0UL != (CY_SCB_I2C_SLAVE_WR_BUSY & context->slaveStatus)))
1076 {
1077 /* Configure to NACK when RX FIFO is full and disable RX level
1078 * interrupt sources to stop getting data from RX FIFO.
1079 */
1080 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
1081 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1082 }
1083
1084 Cy_SysLib_ExitCriticalSection(intrState);
1085 }
1086
1087
1088 /*******************************************************************************
1089 * Function Name: Cy_SCB_I2C_SlaveGetWriteTransferCount
1090 ****************************************************************************//**
1091 *
1092 * Returns the number of bytes written by the master since the last time
1093 * \ref Cy_SCB_I2C_SlaveConfigWriteBuf was called.
1094 *
1095 * \param base
1096 * The pointer to the I2C SCB instance.
1097 *
1098 * \param context
1099 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1100 * by the user. The structure is used during the I2C operation for internal
1101 * configuration and data retention. The user must not modify anything
1102 * in this structure.
1103 *
1104 * \return
1105 * Number of bytes written by the master.
1106 *
1107 * \note
1108 * * This function returns an invalid value if write transaction was
1109 * aborted or any listed event occurs during the transaction:
1110 * \ref CY_SCB_I2C_SLAVE_ARB_LOST, \ref CY_SCB_I2C_SLAVE_BUS_ERR.
1111 * * This number is updated only when the transaction completes, either through
1112 * an error or successfully.
1113 *
1114 *******************************************************************************/
Cy_SCB_I2C_SlaveGetWriteTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1115 uint32_t Cy_SCB_I2C_SlaveGetWriteTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1116 {
1117 /* Suppress a compiler warning about unused variables */
1118 (void) base;
1119
1120 return (context->slaveRxBufferIdx);
1121 }
1122
1123
1124 /*******************************************************************************
1125 * Function Name: Cy_SCB_I2C_SlaveClearWriteStatus
1126 ****************************************************************************//**
1127 *
1128 * Clears the write status flags and error condition flags and returns their
1129 * values.
1130 *
1131 * \param base
1132 * The pointer to the I2C SCB instance.
1133 *
1134 * \param context
1135 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1136 * by the user. The structure is used during the I2C operation for internal
1137 * configuration and data retention. The user must not modify anything
1138 * in this structure.
1139 *
1140 * \return
1141 * \ref group_scb_i2c_macros_slave_status.
1142 *
1143 * \note
1144 * The \ref CY_SCB_I2C_SLAVE_WR_BUSY flag is not cleared.
1145 *
1146 *******************************************************************************/
Cy_SCB_I2C_SlaveClearWriteStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t * context)1147 uint32_t Cy_SCB_I2C_SlaveClearWriteStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t *context)
1148 {
1149 uint32_t retStatus;
1150
1151 /* Suppress a compiler warning about unused variables */
1152 (void) base;
1153
1154 retStatus = (context->slaveStatus & CY_SCB_I2C_SLAVE_WR_CLEAR);
1155 context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_WR_CLEAR;
1156
1157 return (retStatus);
1158 }
1159
1160
1161 /*******************************************************************************
1162 * I2C Master API: High level
1163 *******************************************************************************/
1164
1165 /*******************************************************************************
1166 * Function Name: Cy_SCB_I2C_MasterGetStatus
1167 ****************************************************************************//**
1168 *
1169 * Returns the current I2C master status.
1170 * This status is a bit mask and the value returned may have multiple bits set.
1171 *
1172 * \param base
1173 * The pointer to the I2C SCB instance.
1174 *
1175 * \param context
1176 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1177 * by the user. The structure is used during the I2C operation for internal
1178 * configuration and data retention. The user must not modify anything
1179 * in this structure.
1180 *
1181 * \return
1182 * \ref group_scb_i2c_macros_master_status.
1183 * Note that not all I2C master statuses are returned by this function. Refer to
1184 * more details of each status.
1185 *
1186 * \note
1187 * Status is cleared by calling \ref Cy_SCB_I2C_MasterRead or
1188 * \ref Cy_SCB_I2C_MasterWrite.
1189 *
1190 *******************************************************************************/
Cy_SCB_I2C_MasterGetStatus(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1191 uint32_t Cy_SCB_I2C_MasterGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1192 {
1193 /* Suppress a compiler warning about unused variables */
1194 (void) base;
1195
1196 return (context->masterStatus);
1197 }
1198
1199
1200 /*******************************************************************************
1201 * Function Name: Cy_SCB_I2C_MasterRead
1202 ****************************************************************************//**
1203 *
1204 * This function configures the master to automatically read an entire buffer
1205 * of data from the slave device. After the transaction is initiated by this
1206 * function it returns and \ref Cy_SCB_I2C_Interrupt manages further data
1207 * transfer.
1208 *
1209 * When a read transaction is completed (requested number of bytes are read or
1210 * error occurred) the \ref CY_SCB_I2C_MASTER_BUSY status is cleared and
1211 * the \ref CY_SCB_I2C_MASTER_RD_CMPLT_EVENT event is generated.
1212 *
1213 * Note that the master must read at least one byte.
1214 *
1215 * \param base
1216 * The pointer to the I2C SCB instance.
1217 *
1218 * \param xferConfig
1219 * Master transfer configuration structure
1220 * \ref cy_stc_scb_i2c_master_xfer_config_t.
1221 *
1222 * \param context
1223 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1224 * by the user. The structure is used during the I2C operation for internal
1225 * configuration and data retention. The user must not modify anything
1226 * in this structure.
1227 *
1228 * \return
1229 * \ref cy_en_scb_i2c_status_t
1230 *
1231 * \note
1232 * * The buffer must not be modified and must stay allocated until read operation
1233 * completion.
1234 *
1235 * * \ref Cy_SCB_I2C_MasterRead requests the SCB hardware to generate a start
1236 * condition when there is no pending transfer and returns (does not wait
1237 * until hardware generate a start condition). If the I2C bus is busy the
1238 * hardware will not generate the until bus becomes free.
1239 * The SCB hardware sets the busy status after the Start detection, and clears
1240 * it on the Stop detection. Noise caused by the ESD or other events may cause
1241 * an erroneous Start condition on the bus. Then, the master will never generate
1242 * a Start condition because the hardware assumes the bus is busy. If this occurs,
1243 * the \ref Cy_SCB_I2C_MasterGetStatus returns \ref CY_SCB_I2C_MASTER_BUSY
1244 * status and the transaction will never finish. The option is to implement a
1245 * timeout to detect the transfer completion. If the transfer never completes,
1246 * the SCB needs a reset by calling the \ref Cy_SCB_I2C_Disable and
1247 * \ref Cy_SCB_I2C_Enable functions. The \ref Cy_SCB_I2C_MasterAbortRead
1248 * function will not work, the block must be reset.
1249 *
1250 *******************************************************************************/
Cy_SCB_I2C_MasterRead(CySCB_Type * base,cy_stc_scb_i2c_master_xfer_config_t * xferConfig,cy_stc_scb_i2c_context_t * context)1251 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterRead(CySCB_Type *base,
1252 cy_stc_scb_i2c_master_xfer_config_t *xferConfig,
1253 cy_stc_scb_i2c_context_t *context)
1254 {
1255 CY_ASSERT_L1(xferConfig != NULL);
1256 CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID (xferConfig->buffer, xferConfig->bufferSize));
1257 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(xferConfig->slaveAddress));
1258
1259 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1260
1261 /* Disable I2C slave interrupt sources to protect state */
1262 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1263
1264 if (0UL != (CY_SCB_I2C_IDLE_MASK & context->state))
1265 {
1266 uint32_t intrState;
1267
1268 /* Set address byte (bit0 = 1, read direction) */
1269 uint32_t address = _VAL2FLD(CY_SCB_I2C_ADDRESS, xferConfig->slaveAddress) |
1270 (uint32_t) CY_SCB_I2C_READ_XFER;
1271
1272 /* Setup context */
1273 context->masterStatus = CY_SCB_I2C_MASTER_BUSY;
1274
1275 context->masterBuffer = xferConfig->buffer;
1276 context->masterBufferSize = xferConfig->bufferSize;
1277 context->masterBufferIdx = 0UL;
1278 context->masterNumBytes = 0UL;
1279 context->masterPause = xferConfig->xferPending;
1280 context->masterRdDir = true;
1281
1282 /* Clean-up hardware before transfer. Note RX FIFO is empty at here. */
1283 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1284 Cy_SCB_ClearTxFifo(base);
1285
1286 if (CY_SCB_I2C_IDLE == context->state)
1287 {
1288 /* Put the address in the TX FIFO, then generate a Start condition.
1289 * This sequence ensures that after the Start condition generation
1290 * the address is available to be sent onto the bus.
1291 */
1292 Cy_SCB_WriteTxFifo(base, address);
1293 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1294 }
1295 else
1296 {
1297 /* Generate a ReStart condition.
1298 * If the previous transfer was read, NACK is generated before
1299 * ReStart to complete the previous transfer.
1300 */
1301 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1302 SCB_I2C_M_CMD_M_NACK_Msk : 0UL));
1303
1304 /* Put address in TX FIFO */
1305 Cy_SCB_WriteTxFifo(base, address);
1306 }
1307
1308 /* Configure interrupt for data reception */
1309 if ((context->useRxFifo) && (!context->masterPause) && (context->masterBufferSize >= 2UL))
1310 {
1311 uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
1312
1313 /* Enable Auto data ACK */
1314 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
1315
1316 /* Adjust level in RX FIFO */
1317 Cy_SCB_SetRxFifoLevel(base, (context->masterBufferSize <= fifoSize) ?
1318 (context->masterBufferSize - 2UL) : ((fifoSize / 2UL) - 1UL));
1319
1320 context->state = CY_SCB_I2C_MASTER_RX1;
1321 }
1322 else
1323 {
1324 /* Adjust level in RX FIFO */
1325 Cy_SCB_SetRxFifoLevel(base, 0UL);
1326
1327 context->state = CY_SCB_I2C_MASTER_RX0;
1328 }
1329
1330 /* Enable interrupt sources to continue transfer.
1331 * Requires critical section to not cause race condition between RX and Master
1332 * interrupt sources.
1333 */
1334 intrState = Cy_SysLib_EnterCriticalSection();
1335 Cy_SCB_SetRxInterruptMask (base, CY_SCB_RX_INTR_LEVEL);
1336 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1337 Cy_SysLib_ExitCriticalSection(intrState);
1338
1339 retStatus = CY_SCB_I2C_SUCCESS;
1340 }
1341
1342 /* Enable I2C slave interrupt sources */
1343 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1344
1345 return (retStatus);
1346 }
1347
1348
1349 /*******************************************************************************
1350 * Function Name: Cy_SCB_I2C_MasterAbortRead
1351 ****************************************************************************//**
1352 *
1353 * This function requests master to abort read operation by NAKing the next byte
1354 * and generating a Stop condition. The function does not wait until these
1355 * actions are completed. Therefore the next operation can be initiated only
1356 * after the \ref CY_SCB_I2C_MASTER_BUSY is cleared.
1357 *
1358 * \param base
1359 * The pointer to the I2C SCB instance.
1360 *
1361 * \param context
1362 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1363 * by the user. The structure is used during the I2C operation for internal
1364 * configuration and data retention. The user must not modify anything
1365 * in this structure.
1366 *
1367 ******************************************************************************/
Cy_SCB_I2C_MasterAbortRead(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1368 void Cy_SCB_I2C_MasterAbortRead(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
1369 {
1370 uint32_t intrState;
1371
1372 intrState = Cy_SysLib_EnterCriticalSection();
1373
1374 if (0UL != (CY_SCB_I2C_MASTER_BUSY & context->masterStatus))
1375 {
1376 /* Catch state to abort read operation */
1377 if ((CY_SCB_I2C_MASTER_RX0 == context->state) || (CY_SCB_I2C_MASTER_RX1 == context->state))
1378 {
1379 if (context->useRxFifo)
1380 {
1381 /* Disable RX processing */
1382 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1383
1384 /* Change state to request Stop generation */
1385 context->state = CY_SCB_I2C_MASTER_STOP;
1386
1387 /* Enable ACK interrupt source to generate Stop after Start was generated */
1388 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
1389 }
1390 else
1391 {
1392 /* Reduce buffer size to minimum */
1393 context->masterBufferSize = 1UL;
1394 }
1395
1396 /* Cancel pending read operation if it was requested */
1397 context->masterPause = false;
1398 }
1399 }
1400 else
1401 {
1402 /* There are two possible states when master is not busy:
1403 * CY_SCB_I2C_MASTER_WAIT and CY_SCB_I2C_IDLE.
1404 * Do nothing for CY_SCB_I2C_IDLE.
1405 */
1406 if (CY_SCB_I2C_MASTER_WAIT == context->state)
1407 {
1408 /* Clear master previous transaction results:
1409 * - status to indicate that master is busy;
1410 * - number of bytes (only Stop is generated);
1411 * - cancel previous pending operation.
1412 */
1413 context->masterStatus = CY_SCB_I2C_MASTER_BUSY;
1414 context->masterNumBytes = 0UL;
1415 context->masterPause = false;
1416
1417 /* Enable master interrupt sources to catch Stop condition */
1418 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1419
1420 /* Complete transaction generating Stop */
1421 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1422 context->state = CY_SCB_I2C_MASTER_WAIT_STOP;
1423 }
1424 }
1425
1426 Cy_SysLib_ExitCriticalSection(intrState);
1427 }
1428
1429
1430 /*******************************************************************************
1431 * Function Name: Cy_SCB_I2C_MasterWrite
1432 ****************************************************************************//**
1433 *
1434 * This function configures the master to automatically write an entire buffer
1435 * of data to a slave device. After the transaction is initiated by this
1436 * function it returns and \ref Cy_SCB_I2C_Interrupt manages further data
1437 * transfer.
1438 *
1439 * When a write transaction is completed (requested number of bytes are written
1440 * or error occurred) the \ref CY_SCB_I2C_MASTER_BUSY status is cleared and
1441 * the \ref CY_SCB_I2C_MASTER_WR_CMPLT_EVENT event is generated.
1442 *
1443 * \param base
1444 * The pointer to the I2C SCB instance.
1445 *
1446 * \param xferConfig
1447 * Master transfer configuration structure
1448 * \ref cy_stc_scb_i2c_master_xfer_config_t.
1449 *
1450 * \param context
1451 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1452 * by the user. The structure is used during the I2C operation for internal
1453 * configuration and data retention. The user must not modify anything
1454 * in this structure.
1455 *
1456 * \return
1457 * \ref cy_en_scb_i2c_status_t
1458 *
1459 * \note
1460 * * The buffer must not be modified and must stay allocated until data has been
1461 * copied into the TX FIFO.
1462 *
1463 * * \ref Cy_SCB_I2C_MasterWrite requests the SCB hardware to generate a start
1464 * condition when there is no pending transfer and returns (does not wait
1465 * until hardware generate a start condition). If the I2C bus is busy the
1466 * hardware will not generate the until bus becomes free.
1467 * The SCB hardware sets the busy status after the Start detection, and clears
1468 * it on the Stop detection. Noise caused by the ESD or other events may cause
1469 * an erroneous Start condition on the bus. Then, the master will never generate
1470 * a Start condition because the hardware assumes the bus is busy. If this occurs,
1471 * the \ref Cy_SCB_I2C_MasterGetStatus returns \ref CY_SCB_I2C_MASTER_BUSY
1472 * status and the transaction will never finish. The option is to implement a
1473 * timeout to detect the transfer completion. If the transfer never completes,
1474 * the SCB needs a reset by calling the \ref Cy_SCB_I2C_Disable and
1475 * \ref Cy_SCB_I2C_Enable functions. The \ref Cy_SCB_I2C_MasterAbortWrite
1476 * function will not work, the block must be reset.
1477 *
1478 *******************************************************************************/
Cy_SCB_I2C_MasterWrite(CySCB_Type * base,cy_stc_scb_i2c_master_xfer_config_t * xferConfig,cy_stc_scb_i2c_context_t * context)1479 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWrite(CySCB_Type *base,
1480 cy_stc_scb_i2c_master_xfer_config_t *xferConfig,
1481 cy_stc_scb_i2c_context_t *context)
1482 {
1483 CY_ASSERT_L1(xferConfig != NULL);
1484 CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(xferConfig->buffer, xferConfig->bufferSize));
1485 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID (xferConfig->slaveAddress));
1486
1487 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1488
1489 /* Disable I2C slave interrupt sources to protect state */
1490 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1491
1492 if (0UL != (CY_SCB_I2C_IDLE_MASK & context->state))
1493 {
1494 uint32_t intrState;
1495
1496 /* Set address byte (bit0 = 0, write direction) */
1497 uint32_t address = _VAL2FLD(CY_SCB_I2C_ADDRESS, xferConfig->slaveAddress);
1498
1499 /* Setup context */
1500 context->masterStatus = CY_SCB_I2C_MASTER_BUSY;
1501
1502 context->masterBuffer = xferConfig->buffer;
1503 context->masterBufferSize = xferConfig->bufferSize;
1504 context->masterBufferIdx = 0UL;
1505 context->masterNumBytes = 0UL;
1506 context->masterPause = xferConfig->xferPending;
1507 context->masterRdDir = false;
1508
1509 /* Clean-up hardware before transfer. Note RX FIFO is empty at here. */
1510 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1511 Cy_SCB_ClearTxFifo(base);
1512
1513 if (CY_SCB_I2C_IDLE == context->state)
1514 {
1515 /* Put the address in the TX FIFO, then generate a Start condition.
1516 * This sequence ensures that after the Start condition generation
1517 * the address is available to be sent onto the bus.
1518 */
1519 Cy_SCB_WriteTxFifo (base, address);
1520 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
1521 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1522 }
1523 else
1524 {
1525 /* Generate a ReStart condition.
1526 * If the previous transfer was read, NACK is generated before
1527 * ReStart to complete the previous transfer.
1528 */
1529 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1530 SCB_I2C_M_CMD_M_NACK_Msk : 0UL));
1531
1532 if (0U == context->masterBufferSize)
1533 {
1534 /* The address is the last byte to transfer.
1535 * Put the address byte in the TX FIFO and clear the TX
1536 * Underflow interrupt source inside the critical section
1537 * to ensure that the TX Underflow interrupt will trigger
1538 * after the address byte is sent onto the bus.
1539 */
1540 intrState = Cy_SysLib_EnterCriticalSection();
1541
1542 /* Put address in TX FIFO */
1543 Cy_SCB_WriteTxFifo (base, address);
1544 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
1545
1546 Cy_SysLib_ExitCriticalSection(intrState);
1547 }
1548 else
1549 {
1550 /* Put address in TX FIFO */
1551 Cy_SCB_WriteTxFifo(base, address);
1552 }
1553 }
1554
1555 context->state = CY_SCB_I2C_MASTER_TX;
1556
1557 /* TX FIFO is empty. Set level to start transfer */
1558 Cy_SCB_SetTxFifoLevel(base, (context->useTxFifo) ? CY_SCB_I2C_HALF_FIFO_SIZE : (1UL));
1559
1560 /* Enable interrupt sources to continue transfer.
1561 * Requires critical section to not cause race condition between TX and Master
1562 * interrupt sources.
1563 */
1564 intrState = Cy_SysLib_EnterCriticalSection();
1565 Cy_SCB_SetTxInterruptMask (base, CY_SCB_TX_INTR_LEVEL);
1566 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1567 Cy_SysLib_ExitCriticalSection(intrState);
1568
1569 retStatus = CY_SCB_I2C_SUCCESS;
1570 }
1571
1572 /* Enable I2C slave interrupt sources */
1573 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1574
1575 return (retStatus);
1576 }
1577
1578
1579 /*******************************************************************************
1580 * Function Name: Cy_SCB_I2C_MasterAbortWrite
1581 ****************************************************************************//**
1582 *
1583 * This function requests the master to abort write operation by generating a Stop
1584 * condition. The function does not wait until this action is completed.
1585 * Therefore next write operation can be initiated only after the
1586 * \ref CY_SCB_I2C_MASTER_BUSY is cleared.
1587 *
1588 * \param base
1589 * The pointer to the I2C SCB instance.
1590 *
1591 * \param context
1592 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1593 * by the user. The structure is used during the I2C operation for internal
1594 * configuration and data retention. The user must not modify anything
1595 * in this structure.
1596 *
1597 * \sideeffect
1598 * If the TX FIFO is used, it is cleared before Stop generation.
1599 * The TX FIFO clear operation also clears shift register. Thus, the shifter
1600 * could be cleared in the middle of a data element transfer, corrupting it.
1601 * The remaining bits to transfer within corrupted data element are
1602 * complemented with ones.\n
1603 * If the clear operation is requested while the master transmits the address,
1604 * the direction of transaction is changed to read and one byte is read
1605 * before Stop is issued. This byte is discarded.
1606 *
1607 *******************************************************************************/
Cy_SCB_I2C_MasterAbortWrite(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)1608 void Cy_SCB_I2C_MasterAbortWrite(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
1609 {
1610 uint32_t intrState;
1611
1612 intrState = Cy_SysLib_EnterCriticalSection();
1613
1614 if (0UL != (CY_SCB_I2C_MASTER_BUSY & context->masterStatus))
1615 {
1616 /* Disable TX processing */
1617 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1618
1619 if (context->useTxFifo)
1620 {
1621 /* Clear TX FIFO to allow Stop generation */
1622 Cy_SCB_ClearTxFifo(base);
1623 }
1624
1625 if ((CY_SCB_I2C_MASTER_TX == context->state) || (CY_SCB_I2C_MASTER_TX_DONE == context->state))
1626 {
1627 /* Change state to request Stop generation */
1628 context->state = CY_SCB_I2C_MASTER_STOP;
1629
1630 /* Enable ACK interrupt source to trigger Stop generation */
1631 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
1632 }
1633
1634 /* Cancel pending write operation if it was requested */
1635 context->masterPause = false;
1636 }
1637 else
1638 {
1639 /* There are two possible states when master is not busy:
1640 * CY_SCB_I2C_MASTER_WAIT and CY_SCB_I2C_IDLE.
1641 * Do nothing for CY_SCB_I2C_IDLE.
1642 */
1643 if (CY_SCB_I2C_MASTER_WAIT == context->state)
1644 {
1645 /* Clear master previous transaction results:
1646 * - status to indicate that master is busy;
1647 * - number of bytes (only Stop is generated);
1648 * - cancel previous pending operation.
1649 */
1650 context->masterStatus = CY_SCB_I2C_MASTER_BUSY;
1651 context->masterNumBytes = 0UL;
1652 context->masterPause = false;
1653
1654 /* Enable master interrupt sources to catch Stop condition */
1655 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
1656
1657 /* Complete transaction generating Stop */
1658 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1659 context->state = CY_SCB_I2C_MASTER_WAIT_STOP;
1660 }
1661 }
1662
1663 Cy_SysLib_ExitCriticalSection(intrState);
1664 }
1665
1666
1667 /*******************************************************************************
1668 * Function Name: Cy_SCB_I2C_MasterGetTransferCount
1669 ****************************************************************************//**
1670 *
1671 * Returns the number of bytes transferred since the last call of
1672 * \ref Cy_SCB_I2C_MasterWrite or \ref Cy_SCB_I2C_MasterRead function.
1673 *
1674 * \param base
1675 * The pointer to the I2C SCB instance.
1676 *
1677 * \param context
1678 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1679 * by the user. The structure is used during the I2C operation for internal
1680 * configuration and data retention. The user must not modify anything
1681 * in this structure.
1682 *
1683 * \return
1684 * Number of bytes read or written by the master.
1685 *
1686 * \note
1687 * * This function returns an invalid value if read or write transaction was
1688 * aborted or any listed event occurs during the transaction:
1689 * \ref CY_SCB_I2C_MASTER_ARB_LOST, \ref CY_SCB_I2C_MASTER_BUS_ERR or
1690 * \ref CY_SCB_I2C_MASTER_ABORT_START.
1691 *
1692 * * This number is updated only when the transaction completes, either through
1693 * an error or successfully.
1694 *
1695 *******************************************************************************/
Cy_SCB_I2C_MasterGetTransferCount(CySCB_Type const * base,cy_stc_scb_i2c_context_t const * context)1696 uint32_t Cy_SCB_I2C_MasterGetTransferCount(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
1697 {
1698 /* Suppress a compiler warning about unused variables */
1699 (void) base;
1700
1701 return (context->masterNumBytes);
1702 }
1703
1704
1705 /*******************************************************************************
1706 * I2C Master API: Low level
1707 *******************************************************************************/
1708
1709
1710 /*******************************************************************************
1711 * Function Name: Cy_SCB_I2C_MasterSendStart
1712 ****************************************************************************//**
1713 *
1714 * Generates a Start condition and sends a slave address with the Read/Write bit.
1715 * This function is blocking. It does not return until the Start condition
1716 * and address byte are sent and a ACK/NAK is received, or an error or timeout
1717 * occurs.
1718 *
1719 * \param base
1720 * The pointer to the I2C SCB instance.
1721 *
1722 * \param address
1723 * 7 bit right justified slave address.
1724 *
1725 * \param bitRnW
1726 * This sets the value of the Read/Write bit in the address, thus defining
1727 * the direction of the following transfer.
1728 * See \ref cy_en_scb_i2c_direction_t for the set of constants.
1729 *
1730 * \param timeoutMs
1731 * Defines in milliseconds the time for which this function can block.
1732 * If that time expires, the function returns. If a zero is passed,
1733 * the function waits forever for the action to complete. If a timeout occurs,
1734 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1735 *
1736 * \param context
1737 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1738 * by the user. The structure is used during the I2C operation for internal
1739 * configuration and data retention. The user must not modify anything
1740 * in this structure.
1741 *
1742 * \return
1743 * \ref cy_en_scb_i2c_status_t
1744 *
1745 * \note
1746 * After a read transaction is initiated and the slave ACKs the address, at
1747 * least one byte must be read before completing the transaction or changing
1748 * its direction.
1749 *
1750 *******************************************************************************/
Cy_SCB_I2C_MasterSendStart(CySCB_Type * base,uint32_t address,cy_en_scb_i2c_direction_t bitRnW,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1751 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStart(CySCB_Type *base,
1752 uint32_t address, cy_en_scb_i2c_direction_t bitRnW,
1753 uint32_t timeoutMs,
1754 cy_stc_scb_i2c_context_t *context)
1755 {
1756 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID (address));
1757 CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1758 CY_ASSERT_L3(CY_SCB_I2C_IS_RW_BIT_VALID (bitRnW));
1759
1760 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1761
1762 /* Disable the I2C slave interrupt sources to protect the state */
1763 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1764
1765 if (CY_SCB_I2C_IDLE == context->state)
1766 {
1767 uint32_t locStatus;
1768 uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1769
1770 /* Set the read or write direction */
1771 context->state = CY_SCB_I2C_MASTER_ADDR;
1772 context->masterRdDir = (CY_SCB_I2C_READ_XFER == bitRnW);
1773
1774 /* Clean up the hardware before a transfer. Note RX FIFO is empty at here */
1775 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
1776 Cy_SCB_ClearRxInterrupt (base, CY_SCB_RX_INTR_NOT_EMPTY);
1777 Cy_SCB_ClearTxFifo(base);
1778
1779 /* Generate a Start and send address byte */
1780 Cy_SCB_WriteTxFifo(base, (_VAL2FLD(CY_SCB_I2C_ADDRESS, address) | (uint32_t) bitRnW));
1781 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
1782
1783 /* Wait for a completion event from the master or slave */
1784 do
1785 {
1786 locStatus = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1787 locStatus |= (CY_SCB_I2C_SLAVE_ADDR_DONE & Cy_SCB_GetSlaveInterruptStatus(base));
1788 locStatus |= WaitOneUnit(&timeout);
1789
1790 } while (0UL == locStatus);
1791
1792 /* Convert the status from register plus timeout to the return status */
1793 retStatus = HandleStatus(base, locStatus, context);
1794 }
1795
1796 /* Enable I2C slave interrupt sources */
1797 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
1798
1799 return (retStatus);
1800 }
1801
1802
1803 /*******************************************************************************
1804 * Function Name: Cy_SCB_I2C_MasterSendReStart
1805 ****************************************************************************//**
1806 *
1807 * Generates a ReStart condition and sends a slave address with the Read/Write
1808 * bit.
1809 * This function is blocking. It does not return until the ReStart condition
1810 * and address byte are sent and an ACK/NAK is received, or an error or timeout
1811 * occurs.
1812 *
1813 * \param base
1814 * The pointer to the I2C SCB instance.
1815 *
1816 * \param address
1817 * A 7-bit right-justified slave address.
1818 *
1819 * \param bitRnW
1820 * This sets the value of the Read/Write bit in the address, thus defining
1821 * the direction of the following transfer.
1822 * See \ref cy_en_scb_i2c_direction_t for the set of constants.
1823 *
1824 * \param timeoutMs
1825 * Defines in milliseconds the time for which this function can block.
1826 * If that time expires, the function returns. If a zero is passed,
1827 * the function waits forever for the action to complete. If a timeout occurs,
1828 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1829 *
1830 * \param context
1831 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1832 * by the user. The structure is used during the I2C operation for internal
1833 * configuration and data retention. The user must not modify anything
1834 * in this structure.
1835 *
1836 * \return
1837 * \ref cy_en_scb_i2c_status_t
1838 *
1839 * \note
1840 * * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
1841 * before calling this function. If this condition is not met, this function
1842 * does nothing and returns \ref CY_SCB_I2C_MASTER_NOT_READY.
1843 * * After a read transaction is initiated and the slave ACKs the address,
1844 * at least one byte must be read before completing the transaction or
1845 * changing its direction.
1846 *
1847 *******************************************************************************/
Cy_SCB_I2C_MasterSendReStart(CySCB_Type * base,uint32_t address,cy_en_scb_i2c_direction_t bitRnW,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1848 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendReStart(CySCB_Type *base,
1849 uint32_t address, cy_en_scb_i2c_direction_t bitRnW,
1850 uint32_t timeoutMs,
1851 cy_stc_scb_i2c_context_t *context)
1852 {
1853 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID (address));
1854 CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1855 CY_ASSERT_L3(CY_SCB_I2C_IS_RW_BIT_VALID (bitRnW));
1856
1857 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1858
1859 if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
1860 {
1861 uint32_t locStatus = 0U;
1862 uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1863
1864 /* Set the read or write direction */
1865 context->state = CY_SCB_I2C_MASTER_ADDR;
1866 context->masterRdDir = (CY_SCB_I2C_READ_XFER == bitRnW);
1867
1868 /* Generate ReStart condition.
1869 * If previous transfer was read, NACK is generated before ReStart to
1870 * complete previous transfer.
1871 */
1872 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_START_Msk | (_FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)) ?
1873 SCB_I2C_M_CMD_M_NACK_Msk : 0UL);
1874
1875 /* Previous transfer was a write */
1876 if (false == _FLD2BOOL(SCB_I2C_STATUS_M_READ, SCB_I2C_STATUS(base)))
1877 {
1878 /* Cypress ID #295908: Wait until ReStart is generated to complete
1879 * the previous write transfer. This ensures that the address byte
1880 * will not be interpreted as the data byte of the previous
1881 * transfer.
1882 */
1883 while ((0U == locStatus) &&
1884 (0U != (SCB_I2C_M_CMD_M_START_Msk & SCB_I2C_M_CMD(base))))
1885 {
1886 locStatus = WaitOneUnit(&timeout);
1887 }
1888 }
1889
1890 /* Check for timeout and continue */
1891 if (0U == locStatus)
1892 {
1893 /* Send the address byte */
1894 Cy_SCB_WriteTxFifo(base, (_VAL2FLD(CY_SCB_I2C_ADDRESS, address) | (uint32_t) bitRnW));
1895
1896 /* Wait for a completion event from the or slave */
1897 do
1898 {
1899 locStatus = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1900 locStatus |= WaitOneUnit(&timeout);
1901
1902 } while (0UL == locStatus);
1903 }
1904
1905 /* Convert the status from register plus timeout to the return status */
1906 retStatus = HandleStatus(base, locStatus, context);
1907 }
1908
1909 return (retStatus);
1910 }
1911
1912
1913 /*******************************************************************************
1914 * Function Name: Cy_SCB_I2C_MasterSendStop
1915 ****************************************************************************//**
1916 *
1917 * Generates a Stop condition to complete the current transaction.
1918 * This function is blocking. It does not return until the Stop condition
1919 * is generated, or an error or timeout occurs.
1920 *
1921 * \param base
1922 * The pointer to the I2C SCB instance.
1923 *
1924 * \param timeoutMs
1925 * Defines in milliseconds the time for which this function can block.
1926 * If that time expires, the function returns. If a zero is passed,
1927 * the function waits forever for the action to complete. If a timeout occurs,
1928 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
1929 *
1930 * \param context
1931 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
1932 * by the user. The structure is used during the I2C operation for internal
1933 * configuration and data retention. The user must not modify anything
1934 * in this structure.
1935 *
1936 * \return
1937 * \ref cy_en_scb_i2c_status_t
1938 *
1939 * \note
1940 * * A successful transaction must be initiated by
1941 * \ref Cy_SCB_I2C_MasterSendStart or \ref Cy_SCB_I2C_MasterSendReStart
1942 * before calling this function. If this condition is not met, this function
1943 * does nothing and returns.
1944 * \ref CY_SCB_I2C_MASTER_NOT_READY.
1945 * * Even after the slave NAKs the address, this function must be called
1946 * to complete the transaction.
1947 *
1948 *******************************************************************************/
Cy_SCB_I2C_MasterSendStop(CySCB_Type * base,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)1949 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStop(CySCB_Type *base,uint32_t timeoutMs,
1950 cy_stc_scb_i2c_context_t *context)
1951 {
1952 CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
1953
1954 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
1955
1956 if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
1957 {
1958 uint32_t locStatus;
1959 uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
1960
1961 /* Generate a stop (for Write direction) and NACK plus stop for the Read direction */
1962 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
1963
1964 /* Wait for a completion event from the master or slave */
1965 do
1966 {
1967 locStatus = (CY_SCB_I2C_MASTER_STOP_DONE & Cy_SCB_GetMasterInterruptStatus(base));
1968 locStatus |= WaitOneUnit(&timeout);
1969
1970 } while (0UL == locStatus);
1971
1972 /* Convert the status from register plus timeout to the return status */
1973 retStatus = HandleStatus(base, locStatus, context);
1974 }
1975
1976 return (retStatus);
1977 }
1978
1979
1980 /*******************************************************************************
1981 * Function Name: Cy_SCB_I2C_MasterReadByte
1982 ****************************************************************************//**
1983 *
1984 * Reads one byte from a slave and generates an ACK or prepares to generate
1985 * a NAK. The NAK will be generated before a Stop or ReStart condition by
1986 * \ref Cy_SCB_I2C_MasterSendStop or \ref Cy_SCB_I2C_MasterSendReStart function
1987 * appropriately.
1988 * This function is blocking. It does not return until a byte is
1989 * received, or an error or timeout occurs.
1990 *
1991 * \param base
1992 * The pointer to the I2C SCB instance.
1993 *
1994 * \param ackNack
1995 * A response to a received byte.
1996 * See \ref cy_en_scb_i2c_command_t for the set of constants.
1997 *
1998 * \param byte
1999 * The pointer to the location to store the Read byte.
2000 *
2001 * \param timeoutMs
2002 * Defines in milliseconds the time for which this function can block.
2003 * If that time expires, the function returns. If a zero is passed,
2004 * the function waits forever for the action to complete. If a timeout occurs,
2005 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
2006 *
2007 * \param context
2008 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2009 * by the user. The structure is used during the I2C operation for internal
2010 * configuration and data retention. The user must not modify anything
2011 * in this structure.
2012 *
2013 * \return
2014 * \ref cy_en_scb_i2c_status_t
2015 *
2016 * \note
2017 * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
2018 * or \ref Cy_SCB_I2C_MasterSendReStart before calling this function. If this
2019 * condition is not met, this function does nothing and returns
2020 * \ref CY_SCB_I2C_MASTER_NOT_READY.
2021 *
2022 *******************************************************************************/
Cy_SCB_I2C_MasterReadByte(CySCB_Type * base,cy_en_scb_i2c_command_t ackNack,uint8_t * byte,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)2023 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterReadByte(CySCB_Type *base,
2024 cy_en_scb_i2c_command_t ackNack, uint8_t *byte,
2025 uint32_t timeoutMs,
2026 cy_stc_scb_i2c_context_t *context)
2027 {
2028 CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID (byte, 1UL));
2029 CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID (timeoutMs));
2030 CY_ASSERT_L3(CY_SCB_I2C_IS_RESPONSE_VALID(ackNack));
2031
2032 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
2033
2034 if (CY_SCB_I2C_MASTER_RX0 == context->state)
2035 {
2036 bool rxNotEmpty;
2037 uint32_t locStatus;
2038 uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
2039
2040 /* Wait for ACK/NAK transmission and data byte reception */
2041 do
2042 {
2043 rxNotEmpty = (0UL != (CY_SCB_RX_INTR_NOT_EMPTY & Cy_SCB_GetRxInterruptStatus(base)));
2044 locStatus = (CY_SCB_I2C_MASTER_RX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
2045 locStatus |= WaitOneUnit(&timeout);
2046
2047 } while ((!rxNotEmpty) && (0UL == locStatus));
2048
2049
2050 if (rxNotEmpty)
2051 {
2052 /* Get the received data byte */
2053 *byte = (uint8_t) Cy_SCB_ReadRxFifo(base);
2054
2055 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_NOT_EMPTY | CY_SCB_RX_INTR_LEVEL);
2056 }
2057
2058 /* Convert the status from register plus timeout to the return status */
2059 retStatus = HandleStatus(base, locStatus, context);
2060
2061 if (CY_SCB_I2C_SUCCESS == retStatus)
2062 {
2063 if (CY_SCB_I2C_ACK == ackNack)
2064 {
2065 /* Generate ACK */
2066 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_ACK_Msk;
2067 }
2068 else
2069 {
2070 /* NAK is generated by SendStop() or SendReStart() */
2071 }
2072 }
2073 }
2074
2075 return (retStatus);
2076 }
2077
2078
2079 /*******************************************************************************
2080 * Function Name: Cy_SCB_I2C_MasterWriteByte
2081 ****************************************************************************//**
2082 *
2083 * Sends one byte to a slave.
2084 * This function is blocking. It does not return until a byte is
2085 * transmitted, or an error or timeout occurs.
2086 *
2087 * \param base
2088 * The pointer to the I2C SCB instance.
2089 *
2090 * \param byte
2091 * The byte to write to a slave.
2092 *
2093 * \param timeoutMs
2094 * Defines in milliseconds the time for which this function can block.
2095 * If that time expires, the function returns. If a zero is passed,
2096 * the function waits forever for the action to complete. If a timeout occurs,
2097 * the SCB block is reset. Note The maximum value is UINT32_MAX/1000.
2098 *
2099 * \param context
2100 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2101 * by the user. The structure is used during the I2C operation for internal
2102 * configuration and data retention. The user must not modify anything
2103 * in this structure.
2104 *
2105 * \return
2106 * \ref cy_en_scb_i2c_status_t
2107 *
2108 * \note
2109 * A successful transaction must be initiated by \ref Cy_SCB_I2C_MasterSendStart
2110 * or \ref Cy_SCB_I2C_MasterSendReStart before calling this function. If this
2111 * condition is not met, this function does nothing and returns
2112 * \ref CY_SCB_I2C_MASTER_NOT_READY.
2113 *
2114 *******************************************************************************/
Cy_SCB_I2C_MasterWriteByte(CySCB_Type * base,uint8_t byte,uint32_t timeoutMs,cy_stc_scb_i2c_context_t * context)2115 cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWriteByte(CySCB_Type *base, uint8_t byte, uint32_t timeoutMs,
2116 cy_stc_scb_i2c_context_t *context)
2117 {
2118 CY_ASSERT_L2(CY_SCB_I2C_IS_TIMEOUT_VALID(timeoutMs));
2119
2120 cy_en_scb_i2c_status_t retStatus = CY_SCB_I2C_MASTER_NOT_READY;
2121
2122 if (CY_SCB_I2C_MASTER_TX == context->state)
2123 {
2124 uint32_t locStatus;
2125 uint32_t timeout = CY_SCB_I2C_CONVERT_TIMEOUT_TO_US(timeoutMs);
2126
2127 /* Send the data byte */
2128 Cy_SCB_WriteTxFifo(base, (uint32_t) byte);
2129
2130 /* Wait for a completion event from the master or slave */
2131 do
2132 {
2133 locStatus = (CY_SCB_I2C_MASTER_TX_BYTE_DONE & Cy_SCB_GetMasterInterruptStatus(base));
2134 locStatus |= WaitOneUnit(&timeout);
2135
2136 } while (0UL == locStatus);
2137
2138 /* Convert the status from register plus timeout to the API status */
2139 retStatus = HandleStatus(base, locStatus, context);
2140 }
2141
2142 return (retStatus);
2143 }
2144
2145
2146 /*******************************************************************************
2147 * Function Name: Cy_SCB_I2C_Interrupt
2148 ****************************************************************************//**
2149 *
2150 * This is the interrupt function for the SCB configured in the I2C mode.
2151 * The interrupt is mandatory for I2C operation and this function must be called
2152 * inside the user-defined interrupt service. The exception is the I2C master,
2153 * which uses only the \ref group_scb_i2c_master_low_level_functions functions.
2154 * To reduce the flash consumed by the I2C driver call
2155 * \ref Cy_SCB_I2C_SlaveInterrupt when I2C mode is the slave and
2156 * \ref Cy_SCB_I2C_MasterInterrupt when I2C mode is the master.
2157 *
2158 * \param base
2159 * The pointer to the I2C SCB instance.
2160 *
2161 * \param context
2162 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2163 * by the user. The structure is used during the I2C operation for internal
2164 * configuration and data retention. The user must not modify anything
2165 * in this structure.
2166 *
2167 *******************************************************************************/
Cy_SCB_I2C_Interrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2168 void Cy_SCB_I2C_Interrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2169 {
2170 if (0UL != (CY_SCB_I2C_MASTER_ACTIVE & context->state))
2171 {
2172 /* Execute a transfer as the master */
2173 Cy_SCB_I2C_MasterInterrupt(base, context);
2174 }
2175 else
2176 {
2177 /* Execute a transfer as the slave */
2178 Cy_SCB_I2C_SlaveInterrupt(base, context);
2179 }
2180 }
2181
2182
2183 /*******************************************************************************
2184 * Function Name: Cy_SCB_I2C_SlaveInterrupt
2185 ****************************************************************************//**
2186 *
2187 * This is the interrupt function for the SCB configured in I2C mode as the
2188 * slave. This function should be called inside the user-defined interrupt
2189 * service routine to make any of the slave functions to work.
2190 *
2191 * \param base
2192 * The pointer to the I2C SCB instance.
2193 *
2194 * \param context
2195 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2196 * by the user. The structure is used during the I2C operation for internal
2197 * configuration and data retention. The user must not modify anything
2198 * in this structure.
2199 *
2200 *******************************************************************************/
Cy_SCB_I2C_SlaveInterrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2201 void Cy_SCB_I2C_SlaveInterrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2202 {
2203 uint32_t slaveIntrStatus;
2204
2205 /* Handle an I2C wake-up event */
2206 if (0UL != (CY_SCB_I2C_INTR_WAKEUP & Cy_SCB_GetI2CInterruptStatusMasked(base)))
2207 {
2208 /* Move from IDLE state, the slave was addressed. Following address match
2209 * interrupt continue transfer.
2210 */
2211 context->state = CY_SCB_I2C_SLAVE_ACTIVE;
2212
2213 Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
2214 }
2215
2216 /* Handle the slave interrupt sources */
2217 slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
2218
2219 /* Handle the error conditions */
2220 if (0UL != (CY_SCB_I2C_SLAVE_INTR_ERROR & slaveIntrStatus))
2221 {
2222 /* Update the status */
2223 context->slaveStatus |= (0UL != (CY_SCB_SLAVE_INTR_I2C_BUS_ERROR & slaveIntrStatus)) ?
2224 CY_SCB_I2C_SLAVE_BUS_ERR : CY_SCB_I2C_SLAVE_ARB_LOST;
2225
2226 /* Disable the RX interrupt source to drop data into RX FIFO if any */
2227 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2228
2229 /* Add the stop status to back into the default state and set completion statuses */
2230 slaveIntrStatus |= CY_SCB_SLAVE_INTR_I2C_STOP;
2231 }
2232 else
2233 {
2234 if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
2235 {
2236 /* Get data from the RX FIFO after a stop is generated if there is
2237 * space to store it.
2238 */
2239 if ((Cy_SCB_GetNumInRxFifo(base) > 0UL) && (context->slaveRxBufferSize > 0UL))
2240 {
2241 Cy_SCB_SetRxInterrupt (base, CY_SCB_RX_INTR_LEVEL);
2242 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
2243 }
2244 }
2245 }
2246
2247 /* Handle the receive direction (master writes data) */
2248 if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
2249 {
2250 SlaveHandleDataReceive(base, context);
2251
2252 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2253 }
2254
2255 /* Handle the transfer completion */
2256 if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
2257 {
2258 SlaveHandleStop(base, context);
2259
2260 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
2261
2262 /* Update the slave interrupt status */
2263 slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
2264 }
2265
2266 /* Handle the address reception */
2267 if (0UL != (CY_SCB_I2C_SLAVE_INTR_ADDR & slaveIntrStatus))
2268 {
2269 SlaveHandleAddress(base, context);
2270
2271 Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
2272 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_I2C_SLAVE_INTR_ADDR);
2273 }
2274
2275 /* Handle the transmit direction (master reads data) */
2276 if (0UL != (CY_SCB_I2C_SLAVE_INTR_TX & Cy_SCB_GetTxInterruptStatusMasked(base)))
2277 {
2278 SlaveHandleDataTransmit(base, context);
2279
2280 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
2281 }
2282 }
2283
2284 #if (((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=3)) || defined (CY_IP_MXS22SCB)) || defined (CY_DOXYGEN))
2285 /*******************************************************************************
2286 * Function Name: Cy_SCB_I2C_SetStretchThreshold
2287 ****************************************************************************//**
2288 *
2289 * Sets the stretch threshold value.
2290 *
2291 * \param base
2292 * The pointer to the I2C SCB instance.
2293 *
2294 * \param value
2295 * The stretch threshold value to be set.
2296 * Typically it is the SCL turaround delay (including IO cell delay, SCL rise time,
2297 * analog filter delay), in number of clk_scb cycles.
2298 *
2299 * \note
2300 * * The STRETCH_THRESHOLD value is 0 by default. If there is no device stretching
2301 * the SCL bus, the delay between SCL output and input are reported in
2302 * STRETCH_COUNT \ref Cy_SCB_I2C_GetStretchCount, in number of clk_scb cycles,
2303 * which can then be set as the STRETCH_THRESHOLD value.
2304 * * The STRETCH_THRESHOLD value should be less than or equal to 0xFUL.
2305 * * When STRETCH_COUNT \ref Cy_SCB_I2C_GetStretchCount is higher than this
2306 * STRETCH_THRESHOLD, STRETCH_DETECTED \ref Cy_SCB_I2C_IsStretchDetected
2307 * will be set.
2308 *
2309 * \note
2310 * This API is available for CAT1B and CAT1D devices.
2311 *
2312 *******************************************************************************/
Cy_SCB_I2C_SetStretchThreshold(CySCB_Type const * base,uint32_t value)2313 void Cy_SCB_I2C_SetStretchThreshold(CySCB_Type const *base, uint32_t value)
2314 {
2315 CY_ASSERT_L2(CY_SCB_I2C_STRETCH_THRESHOLD_VALUE_VALID(value));
2316 SCB_I2C_STRETCH_CTRL(base) = _VAL2FLD(SCB_I2C_STRETCH_CTRL_STRETCH_THRESHOLD, value);
2317 }
2318
2319 /*******************************************************************************
2320 * Function Name: Cy_SCB_I2C_GetStretchCount
2321 ****************************************************************************//**
2322 *
2323 * Provides the stretch count. The count is started when the I2C device begins to
2324 * drive high phase on internal SCL output signal and is stalled when it detects
2325 * high level on SCL input signal.
2326 *
2327 * \param base
2328 * The pointer to the I2C SCB instance.
2329 *
2330 * \return
2331 * The stretch count.
2332 *
2333 * \note
2334 * This API is available for CAT1B and CAT1D devices.
2335 *
2336 *******************************************************************************/
Cy_SCB_I2C_GetStretchCount(CySCB_Type const * base)2337 uint32_t Cy_SCB_I2C_GetStretchCount(CySCB_Type const *base)
2338 {
2339 return(_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCH_COUNT, SCB_I2C_STRETCH_STATUS(base)));
2340 }
2341
2342 /*******************************************************************************
2343 * Function Name: Cy_SCB_I2C_IsStretchDetected
2344 ****************************************************************************//**
2345 *
2346 * Checks if stretch is detected on I2C SCL.
2347 *
2348 * \param base
2349 * The pointer to the I2C SCB instance.
2350 *
2351 * \return
2352 * If true, stretch is detected; false otherwise.
2353 *
2354 * \note
2355 * This API is available for CAT1B and CAT1D devices.
2356 *
2357 *******************************************************************************/
Cy_SCB_I2C_IsStretchDetected(CySCB_Type const * base)2358 bool Cy_SCB_I2C_IsStretchDetected(CySCB_Type const *base)
2359 {
2360 return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCH_DETECTED, SCB_I2C_STRETCH_STATUS(base))));
2361 }
2362
2363 /*******************************************************************************
2364 * Function Name: Cy_SCB_I2C_IsSyncDetected
2365 ****************************************************************************//**
2366 *
2367 * Checks if synchronization is detected on I2C SCL.
2368 *
2369 * \param base
2370 * The pointer to the I2C SCB instance.
2371 *
2372 * \return
2373 * If true, synchronization is detected; false otherwise.
2374 *
2375 * \note
2376 * This API is available for CAT1B and CAT1D devices.
2377 *
2378 *******************************************************************************/
Cy_SCB_I2C_IsSyncDetected(CySCB_Type const * base)2379 bool Cy_SCB_I2C_IsSyncDetected(CySCB_Type const *base)
2380 {
2381 return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_SYNC_DETECTED, SCB_I2C_STRETCH_STATUS(base))));
2382 }
2383
2384 /*******************************************************************************
2385 * Function Name: Cy_SCB_I2C_IsStretching
2386 ****************************************************************************//**
2387 *
2388 * Checks if I2C SCL is stretched by the block.
2389 *
2390 * \param base
2391 * The pointer to the I2C SCB instance.
2392 *
2393 * \return
2394 * If true, I2C SCL is being stretch by the block, false otherwise.
2395 *
2396 * \note
2397 * This API is available for CAT1B and CAT1D devices.
2398 *
2399 *******************************************************************************/
Cy_SCB_I2C_IsStretching(CySCB_Type const * base)2400 bool Cy_SCB_I2C_IsStretching(CySCB_Type const *base)
2401 {
2402 return (1UL == (_FLD2VAL(SCB_I2C_STRETCH_STATUS_STRETCHING, SCB_I2C_STRETCH_STATUS(base))));
2403 }
2404 #endif /* CY_IP_MXSCB_VERSION */
2405
2406 /*******************************************************************************
2407 * Function Name: SlaveHandleAddress
2408 ****************************************************************************//**
2409 *
2410 * Prepares the slave for the following Read or Write transfer after the
2411 * matched address was received.
2412 *
2413 * \param base
2414 * The pointer to the I2C SCB instance.
2415 *
2416 * \param context
2417 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2418 * by the user. The structure is used during the I2C operation for internal
2419 * configuration and data retention. The user must not modify anything
2420 * in this structure.
2421 *
2422 *******************************************************************************/
SlaveHandleAddress(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2423 static void SlaveHandleAddress(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2424 {
2425 /* The default command is the ACK address. It can be overridden in an address callback */
2426 cy_en_scb_i2c_command_t cmd = CY_SCB_I2C_ACK;
2427
2428 /* The callback for the address in RX FIFO or a general call */
2429 if (NULL != context->cbAddr)
2430 {
2431 uint32_t events = 0UL;
2432
2433 /* Set an address in the FIFO event if the address accept is enabled */
2434 if (_FLD2BOOL(SCB_CTRL_ADDR_ACCEPT, SCB_CTRL(base)))
2435 {
2436 events = (0UL != (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH & Cy_SCB_GetSlaveInterruptStatusMasked(base))) ?
2437 CY_SCB_I2C_ADDR_IN_FIFO_EVENT : 0UL;
2438 }
2439
2440 /* Set a general call event if "ignore general call" is disabled */
2441 if (!_FLD2BOOL(SCB_I2C_CTRL_S_GENERAL_IGNORE, SCB_I2C_CTRL(base)))
2442 {
2443 events |= (0UL != (CY_SCB_SLAVE_INTR_I2C_GENERAL_ADDR & Cy_SCB_GetSlaveInterruptStatusMasked(base))) ?
2444 CY_SCB_I2C_GENERAL_CALL_EVENT : 0UL;
2445 }
2446
2447 /* Check presence of events before involve callback */
2448 if (0UL != events)
2449 {
2450 /* Involve a callback for the address phase and get the ACK/NACK command */
2451 cmd = context->cbAddr(events);
2452
2453 /* Clear RX level interrupt after address reception */
2454 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2455
2456 if (cmd == CY_SCB_I2C_ACK)
2457 {
2458 /* Clear the stall stop status and enable the stop interrupt source */
2459 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
2460 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR);
2461 }
2462 else
2463 {
2464 /* Disable the stop interrupt source */
2465 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_I2C_SLAVE_INTR_NO_STOP);
2466 }
2467 }
2468 }
2469
2470 /* Clear the TX FIFO before continue the transaction */
2471 Cy_SCB_ClearTxFifo(base);
2472
2473 /* Set the command to an ACK or NACK address */
2474 SCB_I2C_S_CMD(base) = (cmd == CY_SCB_I2C_ACK) ? SCB_I2C_S_CMD_S_ACK_Msk : SCB_I2C_S_CMD_S_NACK_Msk;
2475
2476 if (cmd == CY_SCB_I2C_ACK)
2477 {
2478 bool readDirection = _FLD2BOOL(SCB_I2C_STATUS_S_READ,SCB_I2C_STATUS(base));
2479
2480 /* Notify the user about start of transfer */
2481 if (NULL != context->cbEvents)
2482 {
2483 context->cbEvents(readDirection ? CY_SCB_I2C_SLAVE_READ_EVENT : CY_SCB_I2C_SLAVE_WRITE_EVENT);
2484 }
2485
2486 /* Prepare for a transfer */
2487 if (readDirection)
2488 {
2489 context->state = CY_SCB_I2C_SLAVE_TX;
2490 context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_BUSY;
2491
2492 /* Prepare to transmit data */
2493 context->slaveTxBufferIdx = context->slaveTxBufferCnt;
2494 context->slaveRdBufEmpty = false;
2495 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
2496 }
2497 else
2498 {
2499 uint32_t level = 0UL;
2500
2501 context->state = CY_SCB_I2C_SLAVE_RX;
2502 context->slaveStatus |= CY_SCB_I2C_SLAVE_WR_BUSY;
2503
2504 /* Prepare to receive data */
2505 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
2506
2507 if (context->useRxFifo)
2508 {
2509 if (context->slaveRxBufferSize > 0UL)
2510 {
2511 uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
2512
2513 /* ACK data automatically until RX FIFO is full */
2514 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_READY_DATA_ACK_Msk;
2515
2516 if (context->slaveRxBufferSize > fifoSize)
2517 {
2518 /* Set a level in RX FIFO to trigger the receive interrupt source */
2519 level = (context->slaveRxBufferSize - fifoSize);
2520 level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
2521 }
2522 else
2523 {
2524 /* Set a level in RX FIFO to read the number of bytes */
2525 level = (context->slaveRxBufferSize - 1UL);
2526
2527 /* NACK when RX FIFO becomes full */
2528 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
2529
2530 /* Disable the RX level interrupt and wait until RX FIFO is full or stops */
2531 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2532 }
2533 }
2534 }
2535
2536 Cy_SCB_SetRxFifoLevel(base, level);
2537 }
2538 }
2539 }
2540
2541
2542 /*******************************************************************************
2543 * Function Name: SlaveHandleDataReceive
2544 ****************************************************************************//**
2545 *
2546 * Reads data from RX FIFO into the buffer provided by
2547 * \ref Cy_SCB_I2C_SlaveConfigWriteBuf.
2548 *
2549 * \param base
2550 * The pointer to the I2C SCB instance.
2551 *
2552 * \param context
2553 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2554 * by the user. The structure is used during the I2C operation for internal
2555 * configuration and data retention. The user must not modify anything
2556 * in this structure.
2557 *
2558 *******************************************************************************/
SlaveHandleDataReceive(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2559 static void SlaveHandleDataReceive(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2560 {
2561 /* Check whether there is space to put data */
2562 if (context->slaveRxBufferSize > 0UL)
2563 {
2564 if (context->useRxFifo)
2565 {
2566 uint32_t level;
2567 uint32_t fifoSize = CY_SCB_I2C_FIFO_SIZE;
2568
2569 /* Get the number of bytes to read from RX FIFO */
2570 uint32_t numToCopy = Cy_SCB_GetRxFifoLevel(base) + 1UL;
2571
2572 /* Get data from RX FIFO */
2573 numToCopy = Cy_SCB_ReadArray(base, context->slaveRxBuffer, numToCopy);
2574 context->slaveRxBufferIdx += numToCopy;
2575 context->slaveRxBufferSize -= numToCopy;
2576 context->slaveRxBuffer = &context->slaveRxBuffer[numToCopy];
2577
2578 /* Prepare to read a next chunk of data */
2579 if (context->slaveRxBufferSize > fifoSize)
2580 {
2581 level = context->slaveRxBufferSize - fifoSize;
2582 level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
2583 }
2584 else
2585 {
2586 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
2587
2588 level = (context->slaveRxBufferSize == 0UL) ? (0UL) : (context->slaveRxBufferSize - 1UL);
2589 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2590 }
2591
2592 /* Set the RX level to trigger an interrupt */
2593 Cy_SCB_SetRxFifoLevel(base, level);
2594 }
2595 else
2596 {
2597 /* Continue the transfer: send an ACK */
2598 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
2599
2600 /* Put data into the RX buffer */
2601 context->slaveRxBuffer[context->slaveRxBufferIdx] = (uint8_t) Cy_SCB_ReadRxFifo(base);
2602 ++context->slaveRxBufferIdx;
2603 --context->slaveRxBufferSize;
2604 }
2605 }
2606 else
2607 {
2608 /* Finish a transfer: send a NACK and discard the received byte */
2609 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_NACK_Msk;
2610 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2611 }
2612 }
2613
2614
2615 /*******************************************************************************
2616 * Function Name: SlaveHandleDataTransmit
2617 ****************************************************************************//**
2618 *
2619 * Loads TX FIFO with data provided by \ref Cy_SCB_I2C_SlaveConfigReadBuf.
2620 *
2621 * \param base
2622 * The pointer to the I2C SCB instance.
2623 *
2624 * \param context
2625 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2626 * by the user. The structure is used during the I2C operation for internal
2627 * configuration and data retention. The user must not modify anything
2628 * in this structure.
2629 *
2630 *******************************************************************************/
SlaveHandleDataTransmit(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2631 static void SlaveHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2632 {
2633 uint32_t numToCopy;
2634
2635 /* Notify the user that there is no data to send to the master.
2636 * This event triggers once in scope of a transfer.
2637 */
2638 if ((!context->slaveRdBufEmpty) && (0UL == context->slaveTxBufferSize))
2639 {
2640 /* Involve a callback if registered: no data to send */
2641 if (NULL != context->cbEvents)
2642 {
2643 context->cbEvents(CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT);
2644 }
2645
2646 /* Update the Read buffer empty status after a callback is involved */
2647 context->slaveRdBufEmpty = (0UL == context->slaveTxBufferSize);
2648
2649 /* Enable the TX level interrupt source to continue sending data */
2650 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
2651 }
2652
2653 /* Check whether the Read buffer was updated in the callback */
2654 if (context->slaveRdBufEmpty)
2655 {
2656 /* The Read buffer is empty: copy CY_SCB_I2C_DEFAULT_TX into TX FIFO */
2657 numToCopy = (context->useTxFifo) ? Cy_SCB_GetFifoSize(base) : 1UL;
2658
2659 numToCopy = Cy_SCB_WriteDefaultArray(base, CY_SCB_I2C_DEFAULT_TX, numToCopy);
2660 context->slaveTxBufferIdx += numToCopy;
2661
2662 context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_UNDRFL;
2663 }
2664 else
2665 {
2666 if (context->slaveTxBufferSize > 1UL)
2667 {
2668 /* Get the number of bytes to copy into TX FIFO */
2669 numToCopy = (context->useTxFifo) ? (context->slaveTxBufferSize - 1UL) : (1UL);
2670
2671 /* Write data into TX FIFO */
2672 numToCopy = Cy_SCB_WriteArray(base, context->slaveTxBuffer, numToCopy);
2673 context->slaveTxBufferIdx += numToCopy;
2674 context->slaveTxBufferSize -= numToCopy;
2675 context->slaveTxBuffer = &context->slaveTxBuffer[numToCopy];
2676 }
2677
2678 /* Put the last byte */
2679 if ((CY_SCB_I2C_FIFO_SIZE != Cy_SCB_GetNumInTxFifo(base)) && (1UL == context->slaveTxBufferSize))
2680 {
2681 uint32_t intrStatus;
2682
2683 /* Put the last data byte in the TX FIFO and clear the TX Underflow
2684 * interrupt source inside the critical section to ensure that the
2685 * TX Underflow interrupt will trigger after all data bytes from the
2686 * TX FIFO are transferred onto the bus.
2687 */
2688 intrStatus = Cy_SysLib_EnterCriticalSection();
2689
2690 Cy_SCB_WriteTxFifo (base, (uint32_t) context->slaveTxBuffer[0UL]);
2691 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
2692
2693 Cy_SysLib_ExitCriticalSection(intrStatus);
2694
2695 /* Move the pointers */
2696 ++context->slaveTxBufferIdx;
2697 context->slaveTxBufferSize = 0UL;
2698 context->slaveTxBuffer = &context->slaveTxBuffer[1UL];
2699
2700 /* Enable the TX underflow interrupt to catch when there is no data to send */
2701 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_UNDERFLOW);
2702
2703 if (context->useTxFifo)
2704 {
2705 /* Data is copied into TX FIFO */
2706 context->slaveStatus |= CY_SCB_I2C_SLAVE_RD_IN_FIFO;
2707
2708 /* Involve a callback if registered: data copied into TX FIFO */
2709 if (NULL != context->cbEvents)
2710 {
2711 context->cbEvents(CY_SCB_I2C_SLAVE_RD_IN_FIFO_EVENT);
2712 }
2713 }
2714 }
2715 }
2716 }
2717
2718
2719 /*******************************************************************************
2720 * Function Name: SlaveHandleStop
2721 ****************************************************************************//**
2722 *
2723 * Handles transfer completion. It is triggered by a stop or restart
2724 * condition on the bus.
2725 *
2726 * \param base
2727 * The pointer to the I2C SCB instance.
2728 *
2729 * \param context
2730 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2731 * by the user. The structure is used during the I2C operation for internal
2732 * configuration and data retention. The user must not modify anything
2733 * in this structure.
2734 *
2735 *******************************************************************************/
SlaveHandleStop(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2736 static void SlaveHandleStop(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2737 {
2738 uint32_t locEvents;
2739
2740 if (CY_SCB_I2C_SLAVE_RX == context->state)
2741 {
2742 /* If any data is left in RX FIFO, this is an overflow */
2743 if (Cy_SCB_GetNumInRxFifo(base) > 0UL)
2744 {
2745 context->slaveStatus |= CY_SCB_I2C_SLAVE_WR_OVRFL;
2746
2747 if (context->useRxFifo)
2748 {
2749 Cy_SCB_ClearRxFifo(base);
2750 }
2751 else
2752 {
2753 (void) Cy_SCB_ReadRxFifo(base);
2754 }
2755 }
2756
2757 locEvents = (uint32_t) CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT;
2758 context->slaveStatus |= (uint32_t) CY_SCB_I2C_SLAVE_WR_CMPLT;
2759 context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_WR_BUSY;
2760
2761 /* Clean up the RX direction */
2762 SCB_I2C_CTRL(base) &= (uint32_t) ~(SCB_I2C_CTRL_S_READY_DATA_ACK_Msk |
2763 SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk);
2764
2765 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2766 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2767 }
2768 else
2769 {
2770 /* The number of bytes left in TX FIFO */
2771 uint32_t size = Cy_SCB_GetNumInTxFifo(base) + Cy_SCB_GetTxSrValid(base);
2772
2773 /* Get the number of bytes transferred from the read buffer */
2774 context->slaveTxBufferCnt = (context->slaveTxBufferIdx - size);
2775
2776 /* Update buffer pointer and its size if there is no overflow */
2777 if (0UL == (CY_SCB_I2C_SLAVE_RD_UNDRFL & context->slaveStatus))
2778 {
2779 context->slaveTxBufferSize += size;
2780 context->slaveTxBuffer -= size;
2781 }
2782
2783 locEvents = (uint32_t) CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT;
2784 context->slaveStatus |= (uint32_t) CY_SCB_I2C_SLAVE_RD_CMPLT;
2785 context->slaveStatus &= (uint32_t) ~CY_SCB_I2C_SLAVE_RD_BUSY;
2786
2787 /* Clean up the TX direction */
2788 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
2789 }
2790
2791 /* Return scb into the known state after an error */
2792 if (0UL != (CY_SCB_I2C_SLAVE_INTR_ERROR & Cy_SCB_GetSlaveInterruptStatusMasked(base)))
2793 {
2794 /* After scb IP is reset, the interrupt statuses are cleared */
2795 Cy_SCB_FwBlockReset(base);
2796
2797 locEvents |= CY_SCB_I2C_SLAVE_ERR_EVENT;
2798 }
2799
2800 /* After a stop or error, set the state to idle */
2801 context->state = CY_SCB_I2C_IDLE;
2802
2803 /* Call a completion callback if registered */
2804 if (NULL != context->cbEvents)
2805 {
2806 context->cbEvents(locEvents);
2807 }
2808 }
2809
2810
2811 /*******************************************************************************
2812 * Function Name: Cy_SCB_I2C_MasterInterrupt
2813 ****************************************************************************//**
2814 *
2815 * This is the interrupt function for the SCB configured in I2C mode as the
2816 * master. This function should be called inside the user-defined interrupt
2817 * service routine to make \ref group_scb_i2c_master_high_level_functions
2818 * functions to work.
2819 *
2820 * \param base
2821 * The pointer to the I2C SCB instance.
2822 *
2823 * \param context
2824 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2825 * by the user. The structure is used during the I2C operation for internal
2826 * configuration and data retention. The user must not modify anything
2827 * in this structure.
2828 *
2829 *******************************************************************************/
Cy_SCB_I2C_MasterInterrupt(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2830 void Cy_SCB_I2C_MasterInterrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2831 {
2832 uint32_t intrCause = Cy_SCB_GetInterruptCause(base);
2833
2834 /* Check whether the slave is active. It can be addressed during the master set-up transfer */
2835 if (0UL != (CY_SCB_SLAVE_INTR & intrCause))
2836 {
2837 /* Abort the transfer due to slave operation */
2838 if (0UL != SCB_I2C_M_CMD(base))
2839 {
2840 SCB_I2C_M_CMD(base) = 0UL;
2841
2842 context->masterStatus |= CY_SCB_I2C_MASTER_ABORT_START;
2843 }
2844
2845 context->state = CY_SCB_I2C_MASTER_CMPLT;
2846 }
2847
2848 /* Check for master error conditions */
2849 if (0UL != (CY_SCB_MASTER_INTR & intrCause))
2850 {
2851 MasterHandleEvents(base, context);
2852
2853 /* Any master event does not require further TX processing */
2854 intrCause &= (uint32_t) ~CY_SCB_TX_INTR;
2855 }
2856
2857 if (0UL != (CY_SCB_RX_INTR & intrCause))
2858 {
2859 MasterHandleDataReceive(base, context);
2860
2861 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
2862 }
2863
2864 if (0UL != (CY_SCB_TX_INTR & intrCause))
2865 {
2866 MasterHandleDataTransmit(base, context);
2867
2868 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
2869 }
2870
2871 /* Complete the transfer */
2872 if (CY_SCB_I2C_MASTER_CMPLT == context->state)
2873 {
2874 MasterHandleComplete(base, context);
2875 }
2876
2877 /* Generate stop to complete transfer */
2878 if (CY_SCB_I2C_MASTER_STOP == context->state)
2879 {
2880 MasterHandleStop(base, context);
2881 }
2882 }
2883
2884
2885 /*******************************************************************************
2886 * Function Name: MasterHandleMasterEvents
2887 ****************************************************************************//**
2888 *
2889 * Reads data from RX FIFO into the buffer provided by \ref Cy_SCB_I2C_MasterRead.
2890 *
2891 * \param base
2892 * The pointer to the I2C SCB instance.
2893 *
2894 * \param context
2895 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2896 * by the user. The structure is used during the I2C operation for internal
2897 * configuration and data retention. The user must not modify anything
2898 * in this structure.
2899 *
2900 * \note
2901 * The master CY_SCB_MASTER_INTR_I2C_ACK interrupt source is used for Stop
2902 * generation or request to abort transfer.
2903 *
2904 *******************************************************************************/
MasterHandleEvents(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2905 static void MasterHandleEvents(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2906 {
2907 uint32_t masterIntrStatus = Cy_SCB_GetMasterInterruptStatusMasked(base);
2908
2909 /* The master has not received the acknowledgment for slave */
2910 if (0UL != (CY_SCB_MASTER_INTR_I2C_NACK & masterIntrStatus))
2911 {
2912 /* Clear NAK interrupt source */
2913 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_MASTER_INTR_I2C_NACK);
2914
2915 /* Update status to indicate address or data was NACKed */
2916 context->masterStatus |= (0UL != (CY_SCB_MASTER_INTR_I2C_ACK & Cy_SCB_GetMasterInterruptStatus(base))) ?
2917 CY_SCB_I2C_MASTER_DATA_NAK : CY_SCB_I2C_MASTER_ADDR_NAK;
2918
2919 /* Check whether Stop generation was requested before */
2920 if (CY_SCB_I2C_MASTER_WAIT_STOP != context->state)
2921 {
2922 context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_CMPLT : CY_SCB_I2C_MASTER_STOP;
2923 }
2924 }
2925
2926 /* The master detected a bus error condition */
2927 if (0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & masterIntrStatus))
2928 {
2929 context->masterStatus |= CY_SCB_I2C_MASTER_BUS_ERR;
2930 }
2931
2932 /* The master detected an arbitration lost condition */
2933 if (0UL != (CY_SCB_MASTER_INTR_I2C_ARB_LOST & masterIntrStatus))
2934 {
2935 context->masterStatus |= CY_SCB_I2C_MASTER_ARB_LOST;
2936 }
2937
2938 /* Complete the transfer: stop, bus error or arbitration lost */
2939 if (0UL != (CY_SCB_I2C_MASTER_INTR_CMPLT & masterIntrStatus))
2940 {
2941 context->state = CY_SCB_I2C_MASTER_CMPLT;
2942 }
2943 }
2944
2945
2946 /*******************************************************************************
2947 * Function Name: MasterHandleDataReceive
2948 ****************************************************************************//**
2949 *
2950 * Reads data from RX FIFO into the buffer provided by \ref Cy_SCB_I2C_MasterRead.
2951 *
2952 * \param base
2953 * The pointer to the I2C SCB instance.
2954 *
2955 * \param context
2956 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
2957 * by the user. The structure is used during the I2C operation for internal
2958 * configuration and data retention. The user must not modify anything
2959 * in this structure.
2960 *
2961 *******************************************************************************/
MasterHandleDataReceive(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)2962 static void MasterHandleDataReceive(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
2963 {
2964 switch (context->state)
2965 {
2966 case CY_SCB_I2C_MASTER_RX0:
2967 {
2968 /* Put data into the component buffer */
2969 context->masterBuffer[0UL] = (uint8_t) Cy_SCB_ReadRxFifo(base);
2970
2971 ++context->masterBufferIdx;
2972 --context->masterBufferSize;
2973
2974 if (context->masterBufferSize > 0UL)
2975 {
2976 /* Continue the transaction: move pointer send an ACK */
2977 context->masterBuffer = &context->masterBuffer[1UL];
2978 SCB_I2C_M_CMD(base) = SCB_I2C_M_CMD_M_ACK_Msk;
2979 }
2980 else
2981 {
2982 /* Complete the transaction */
2983 context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_CMPLT : CY_SCB_I2C_MASTER_STOP;
2984 }
2985 }
2986 break;
2987
2988 case CY_SCB_I2C_MASTER_RX1:
2989 {
2990 uint32_t numToCopied;
2991
2992 /* Get data from RX FIFO */
2993 numToCopied = Cy_SCB_ReadArray(base, context->masterBuffer, context->masterBufferSize);
2994 context->masterBufferIdx += numToCopied;
2995 context->masterBufferSize -= numToCopied;
2996 context->masterBuffer = &context->masterBuffer[numToCopied];
2997
2998 if (context->masterBufferSize < 2UL)
2999 {
3000 /* Stop ACKing data */
3001 SCB_I2C_CTRL(base) &= (uint32_t) ~SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
3002
3003 if (1UL == context->masterBufferSize)
3004 {
3005 /* Catch the last byte */
3006 Cy_SCB_SetRxFifoLevel(base, 0UL);
3007
3008 context->state = CY_SCB_I2C_MASTER_RX0;
3009 }
3010 else
3011 {
3012 /* Stop RX processing */
3013 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3014
3015 context->state = CY_SCB_I2C_MASTER_STOP;
3016 }
3017 }
3018 else
3019 {
3020 uint32_t halfFifoSize = CY_SCB_I2C_HALF_FIFO_SIZE;
3021
3022 /* Continue the transfer: Adjust the level in RX FIFO */
3023 Cy_SCB_SetRxFifoLevel(base, (context->masterBufferSize <= halfFifoSize) ?
3024 (context->masterBufferSize - 2UL) : (halfFifoSize - 1UL));
3025 }
3026 }
3027 break;
3028
3029 default:
3030 /* Do nothing: drop data into RX FIFO */
3031 break;
3032 }
3033 }
3034
3035
3036 /*******************************************************************************
3037 * Function Name: MasterHandleDataTransmit
3038 ****************************************************************************//**
3039 *
3040 * Loads TX FIFO with data provided by \ref Cy_SCB_I2C_MasterWrite.
3041 *
3042 * \param base
3043 * The pointer to the I2C SCB instance.
3044 *
3045 * \param context
3046 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3047 * by the user. The structure is used during the I2C operation for internal
3048 * configuration and data retention. The user must not modify anything
3049 * in this structure.
3050 *
3051 *******************************************************************************/
MasterHandleDataTransmit(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3052 static void MasterHandleDataTransmit(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3053 {
3054 if (CY_SCB_I2C_MASTER_TX_DONE == context->state)
3055 {
3056 context->state = CY_SCB_I2C_MASTER_CMPLT;
3057 }
3058 else if (CY_SCB_I2C_MASTER_TX == context->state)
3059 {
3060 if (context->masterBufferSize > 1UL)
3061 {
3062 /* Get the number of bytes to copy into TX FIFO */
3063 uint32_t NumToCopy = (context->useTxFifo) ? (context->masterBufferSize - 1UL) : (1UL);
3064
3065 /* Write data into TX FIFO */
3066 NumToCopy = Cy_SCB_WriteArray(base, context->masterBuffer, NumToCopy);
3067 context->masterBufferIdx += NumToCopy;
3068 context->masterBufferSize -= NumToCopy;
3069 context->masterBuffer = &context->masterBuffer[NumToCopy];
3070 }
3071
3072 /* Put the last byte */
3073 if ((CY_SCB_I2C_FIFO_SIZE != Cy_SCB_GetNumInTxFifo(base)) && (1UL == context->masterBufferSize))
3074 {
3075 uint32_t intrStatus;
3076
3077 /* Put the last data byte in the TX FIFO and clear the TX Underflow
3078 * interrupt source inside the critical section to ensure that the
3079 * TX Underflow interrupt will trigger after all data bytes from the
3080 * TX FIFO are transferred onto the bus.
3081 */
3082 intrStatus = Cy_SysLib_EnterCriticalSection();
3083
3084 Cy_SCB_WriteTxFifo (base, (uint32_t) context->masterBuffer[0UL]);
3085 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
3086
3087 Cy_SysLib_ExitCriticalSection(intrStatus);
3088
3089 ++context->masterBufferIdx;
3090 context->masterBufferSize = 0UL;
3091 }
3092
3093 /* Complete the transfer */
3094 if (0UL == context->masterBufferSize)
3095 {
3096 if (context->masterPause)
3097 {
3098 /* Wait until data is transferred onto the bus */
3099 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_UNDERFLOW);
3100
3101 context->state = CY_SCB_I2C_MASTER_TX_DONE;
3102 }
3103 else
3104 {
3105 /* Disable TX processing */
3106 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3107
3108 /* Request Stop generation */
3109 context->state = CY_SCB_I2C_MASTER_STOP;
3110 }
3111
3112 if (context->useTxFifo)
3113 {
3114 /* Notify the user that data is in TX FIFO */
3115 context->masterStatus |= CY_SCB_I2C_MASTER_WR_IN_FIFO;
3116
3117 if (NULL != context->cbEvents)
3118 {
3119 context->cbEvents(CY_SCB_I2C_MASTER_WR_IN_FIFO_EVENT);
3120 }
3121 }
3122 }
3123 }
3124 else
3125 {
3126 /* Do nothing */
3127 }
3128 }
3129
3130
3131 /*******************************************************************************
3132 * Function Name: MasterHandleStop
3133 ****************************************************************************//**
3134 *
3135 * Handles the stop condition generation
3136 *
3137 * \param base
3138 * The pointer to the I2C SCB instance.
3139 *
3140 * \param context
3141 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3142 * by the user. The structure is used during the I2C operation for internal
3143 * configuration and data retention. The user must not modify anything
3144 * in this structure.
3145 *
3146 *******************************************************************************/
MasterHandleStop(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3147 static void MasterHandleStop(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3148 {
3149 /* Stop RX and TX processing */
3150 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3151 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3152
3153 if (0UL != SCB_I2C_M_CMD(base))
3154 {
3155 /* Enable ACK interrupt source: it triggers after ACK response to
3156 * address was received.
3157 */
3158 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR_ALL);
3159 }
3160 else
3161 {
3162 /* Disable ACK interrupt source */
3163 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_I2C_MASTER_INTR);
3164
3165 /* Complete transaction generating Stop */
3166 SCB_I2C_M_CMD(base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
3167 context->state = CY_SCB_I2C_MASTER_WAIT_STOP;
3168 }
3169 }
3170
3171
3172 /*******************************************************************************
3173 * Function Name: MasterHandleComplete
3174 ****************************************************************************//**
3175 *
3176 * Handles the transfer completion on a stop or restart - the normal case or
3177 * completion due to an error on the bus or lost arbitration.
3178 *
3179 * \param base
3180 * The pointer to the I2C SCB instance.
3181 *
3182 * \param context
3183 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3184 * by the user. The structure is used during the I2C operation for internal
3185 * configuration and data retention. The user must not modify anything
3186 * in this structure.
3187 *
3188 *******************************************************************************/
MasterHandleComplete(CySCB_Type * base,cy_stc_scb_i2c_context_t * context)3189 static void MasterHandleComplete(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
3190 {
3191 uint32_t masterIntrStatus = Cy_SCB_GetMasterInterruptStatusMasked(base);
3192
3193 /* Clean-up hardware */
3194
3195 /* Disable auto data ACK option */
3196 SCB_I2C_CTRL(base) &= (uint32_t) ~SCB_I2C_CTRL_M_READY_DATA_ACK_Msk;
3197
3198 /* Disable the interrupt source for master operation */
3199 Cy_SCB_SetRxInterruptMask (base, CY_SCB_CLEAR_ALL_INTR_SRC);
3200 Cy_SCB_SetTxInterruptMask (base, CY_SCB_CLEAR_ALL_INTR_SRC);
3201 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
3202
3203 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
3204
3205 /* Operation complete - master is not busy anymore */
3206 context->masterStatus &= (uint32_t) ~CY_SCB_I2C_MASTER_BUSY;
3207
3208 /* Get number of byte transferred on the bus */
3209 if (context->masterRdDir)
3210 {
3211 context->masterNumBytes = context->masterBufferIdx;
3212 }
3213 else
3214 {
3215 context->masterNumBytes = context->masterBufferIdx -
3216 (Cy_SCB_GetNumInTxFifo(base) + Cy_SCB_GetTxSrValid(base));
3217 }
3218
3219 /* Clean up after a not completed transfer */
3220 if (0UL != (CY_SCB_I2C_MASTER_INTR_ERR & masterIntrStatus))
3221 {
3222 /* Reset the scb IP block when:
3223 * 1. Master mode: Reset IP when arbitration is lost or a bus error occurs.
3224 * 2. Master-Slave mode: Reset IP if it is not the address phase (ACK is 0).
3225 * Otherwise, reset only on a bus error. If "lost arbitration" happens, the slave
3226 * can be addressed, so let the slave accept the address.
3227 */
3228
3229 bool resetIp = true;
3230
3231 /* Check the Master-Slave address an ACK/NACK */
3232 if (((uint32_t) CY_SCB_I2C_MASTER_SLAVE) == _FLD2VAL(CY_SCB_I2C_CTRL_MODE, SCB_I2C_CTRL(base)))
3233 {
3234 resetIp = ((0UL != (CY_SCB_MASTER_INTR_I2C_ACK & masterIntrStatus)) ? true :
3235 ((0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & masterIntrStatus)) ? true : false));
3236 }
3237
3238 if (resetIp)
3239 {
3240 /* Reset to get it back in an known state */
3241 Cy_SCB_FwBlockReset(base);
3242 }
3243
3244 /* Back to the idle state. The master is not active anymore */
3245 context->state = CY_SCB_I2C_IDLE;
3246 }
3247 else
3248 {
3249 if (context->useRxFifo)
3250 {
3251 /* Clear RX FIFO from remaining data and level interrupt source */
3252 Cy_SCB_ClearRxFifo(base);
3253 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
3254 }
3255
3256 context->state = (context->masterPause) ? CY_SCB_I2C_MASTER_WAIT : CY_SCB_I2C_IDLE;
3257 }
3258
3259 /* An operation completion callback */
3260 if (NULL != context->cbEvents)
3261 {
3262 /* Get completion events based on the hardware status */
3263 uint32_t locEvents = context->masterRdDir ? CY_SCB_I2C_MASTER_RD_CMPLT_EVENT : CY_SCB_I2C_MASTER_WR_CMPLT_EVENT;
3264
3265 /* Add errors if any */
3266 locEvents |= (0UL != (CY_SCB_I2C_MASTER_ERR & context->masterStatus)) ? CY_SCB_I2C_MASTER_ERR_EVENT : 0UL;
3267
3268 context->cbEvents(locEvents);
3269 }
3270 }
3271
3272
3273
3274 /******************************************************************************
3275 * Function Name: WaitOneUnit
3276 ****************************************************************************//**
3277 *
3278 * Waits for one unit before unblock code execution.
3279 * Note that if a timeout value is 0, this function does nothing and returns 0.
3280 *
3281 * \param timeout
3282 * The pointer to a timeout value.
3283 *
3284 * \return
3285 * Returns 0 if a timeout does not expire or the timeout mask.
3286 *
3287 *******************************************************************************/
WaitOneUnit(uint32_t * timeout)3288 static uint32_t WaitOneUnit(uint32_t *timeout)
3289 {
3290 uint32_t status = 0UL;
3291
3292 /* If the timeout equal to 0. Ignore the timeout */
3293 if (*timeout > 0UL)
3294 {
3295 Cy_SysLib_DelayUs(CY_SCB_WAIT_1_UNIT);
3296 --(*timeout);
3297
3298 if (0UL == *timeout)
3299 {
3300 status = CY_SCB_I2C_MASTER_TIMEOUT_DONE;
3301 }
3302 }
3303
3304 return (status);
3305 }
3306
3307
3308 /******************************************************************************
3309 * Function Name: HandleStatus
3310 ****************************************************************************//**
3311 *
3312 * Converts passed status into the cy_en_scb_i2c_status_t.
3313 *
3314 * \param base
3315 * The pointer to the I2C SCB instance.
3316 *
3317 * \param status
3318 * The status to covert.
3319 *
3320 * \param context
3321 * The pointer to the context structure \ref cy_stc_scb_i2c_context_t allocated
3322 * by the user. The structure is used during the I2C operation for internal
3323 * configuration and data retention. The user must not modify anything
3324 * in this structure.
3325 *
3326 * \return
3327 * \ref cy_en_scb_i2c_status_t
3328 *
3329 *******************************************************************************/
HandleStatus(CySCB_Type * base,uint32_t status,cy_stc_scb_i2c_context_t * context)3330 static cy_en_scb_i2c_status_t HandleStatus(CySCB_Type *base, uint32_t status, cy_stc_scb_i2c_context_t *context)
3331 {
3332 cy_en_scb_i2c_status_t retStatus;
3333 bool resetBlock = false;
3334
3335 /* Convert the master status to the API status */
3336 if (0UL != (CY_SCB_I2C_MASTER_TIMEOUT_DONE & status))
3337 {
3338 retStatus = CY_SCB_I2C_MASTER_MANUAL_TIMEOUT;
3339 resetBlock = true;
3340 }
3341 else if (0UL != (CY_SCB_I2C_SLAVE_ADDR_DONE & status))
3342 {
3343 /* Abort the master operation, the slave was addressed first */
3344 retStatus = CY_SCB_I2C_MASTER_MANUAL_ABORT_START;
3345
3346 SCB_I2C_M_CMD(base) = 0UL;
3347 context->state = CY_SCB_I2C_IDLE;
3348 }
3349 else if (0UL != (CY_SCB_MASTER_INTR_I2C_BUS_ERROR & status))
3350 {
3351 retStatus = CY_SCB_I2C_MASTER_MANUAL_BUS_ERR;
3352 resetBlock = true;
3353 }
3354 else if (0UL != (CY_SCB_MASTER_INTR_I2C_ARB_LOST & status))
3355 {
3356 retStatus = CY_SCB_I2C_MASTER_MANUAL_ARB_LOST;
3357
3358 if (CY_SCB_I2C_MASTER_ADDR == context->state)
3359 {
3360 /* This is the address phase:
3361 * 1. Master mode: Reset IP when "arbitration lost" occurs.
3362 * 2. Master-Slave mode: If "lost arbitration" occurs, the slave
3363 * can be addressed to let the slave accept the address; do not
3364 * reset IP.
3365 */
3366 resetBlock = !_FLD2BOOL(SCB_I2C_CTRL_SLAVE_MODE, SCB_I2C_CTRL(base));
3367
3368 context->state = CY_SCB_I2C_IDLE;
3369 }
3370 else
3371 {
3372 resetBlock = true;
3373 }
3374 }
3375 else if (0UL != (CY_SCB_MASTER_INTR_I2C_NACK & status))
3376 {
3377 /* An address or data was NAKed */
3378 retStatus = (CY_SCB_I2C_MASTER_ADDR == context->state) ?
3379 CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK : CY_SCB_I2C_MASTER_MANUAL_NAK;
3380 }
3381 else
3382 {
3383 retStatus = CY_SCB_I2C_SUCCESS;
3384
3385 if (0UL != (CY_SCB_MASTER_INTR_I2C_STOP & status))
3386 {
3387 /* End of transaction, go to idle state */
3388 context->state = CY_SCB_I2C_IDLE;
3389 }
3390 else
3391 {
3392 /* Continue transaction */
3393 if (CY_SCB_I2C_MASTER_ADDR == context->state)
3394 {
3395 /* Switch from address to data state */
3396 context->state = (context->masterRdDir) ?
3397 CY_SCB_I2C_MASTER_RX0 : CY_SCB_I2C_MASTER_TX;
3398 }
3399 }
3400 }
3401
3402 if (resetBlock)
3403 {
3404 /* Back block into default state */
3405 Cy_SCB_FwBlockReset(base);
3406
3407 context->state = CY_SCB_I2C_IDLE;
3408 }
3409 else
3410 {
3411 Cy_SCB_ClearMasterInterrupt(base, CY_SCB_I2C_MASTER_INTR_ALL);
3412 }
3413
3414 return (retStatus);
3415 }
3416
3417
3418 #if defined(__cplusplus)
3419 }
3420 #endif
3421
3422 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
3423
3424 /* [] END OF FILE */
3425