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