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