1 /***************************************************************************//**
2 * \file cy_scb_ezi2c.c
3 * \version 3.10
4 *
5 * Provides EZI2C 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_ezi2c.h"
30
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34
35
36 /***************************************
37 * Function Prototypes
38 ***************************************/
39
40 static void HandleErrors (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
41 static void HandleAddress (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
42 static void UpdateRxFifoLevel (CySCB_Type *base, uint32_t bufSize);
43 static void HandleDataReceive (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
44 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
45 static void HandleStop (CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context);
46 static void UpdateAddressMask (CySCB_Type *base, cy_stc_scb_ezi2c_context_t const *context);
47
48
49 /*******************************************************************************
50 * Function Name: Cy_SCB_EZI2C_Init
51 ****************************************************************************//**
52 *
53 * Initializes the SCB for the EZI2C operation.
54 *
55 * \param base
56 * The pointer to the EZI2C SCB instance.
57 *
58 * \param config
59 * The pointer to the configuration structure \ref cy_stc_scb_ezi2c_config_t.
60 *
61 * \param context
62 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
63 * allocated by the user. The structure is used during the EZI2C operation for
64 * internal configuration and data retention. The user must not modify anything
65 * in this structure.
66 *
67 * \return
68 * \ref cy_en_scb_ezi2c_status_t
69 *
70 * \note
71 * Ensure that the SCB block is disabled before calling this function.
72 *
73 *******************************************************************************/
Cy_SCB_EZI2C_Init(CySCB_Type * base,cy_stc_scb_ezi2c_config_t const * config,cy_stc_scb_ezi2c_context_t * context)74 cy_en_scb_ezi2c_status_t Cy_SCB_EZI2C_Init(CySCB_Type *base, cy_stc_scb_ezi2c_config_t const *config,
75 cy_stc_scb_ezi2c_context_t *context)
76 {
77 /* Input parameters verification */
78 if ((NULL == base) || (NULL == config) || (NULL == context))
79 {
80 return CY_SCB_EZI2C_BAD_PARAM;
81 }
82
83 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(config->slaveAddress1));
84 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(config->slaveAddress2));
85 CY_ASSERT_L2(config->slaveAddress1 != config->slaveAddress2);
86 CY_ASSERT_L3(CY_SCB_EZI2C_IS_NUM_OF_ADDR_VALID (config->numberOfAddresses));
87 CY_ASSERT_L3(CY_SCB_EZI2C_IS_SUB_ADDR_SIZE_VALID(config->subAddressSize));
88
89 /* Configure the EZI2C interface */
90 SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, (config->numberOfAddresses == CY_SCB_EZI2C_TWO_ADDRESSES)) |
91 _BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep);
92 #if ((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
93 SCB_CTRL(base) |= SCB_CTRL_BYTE_MODE_Msk;
94 #endif /* CY_IP_MXSCB_VERSION */
95 SCB_I2C_CTRL(base) = CY_SCB_EZI2C_I2C_CTRL;
96
97 /* Configure the RX direction */
98 SCB_RX_CTRL(base) = CY_SCB_EZI2C_RX_CTRL;
99 SCB_RX_FIFO_CTRL(base) = 0UL;
100
101 /* Set the default address and mask */
102 if (config->numberOfAddresses == CY_SCB_EZI2C_ONE_ADDRESS)
103 {
104 context->address2 = 0U;
105 Cy_SCB_EZI2C_SetAddress1(base, config->slaveAddress1, context);
106 }
107 else
108 {
109 Cy_SCB_EZI2C_SetAddress1(base, config->slaveAddress1, context);
110 Cy_SCB_EZI2C_SetAddress2(base, config->slaveAddress2, context);
111 }
112
113 /* Configure the TX direction */
114 SCB_TX_CTRL(base) = CY_SCB_EZI2C_TX_CTRL;
115 SCB_TX_FIFO_CTRL(base) = CY_SCB_EZI2C_HALF_FIFO_SIZE;
116
117 /* Configure the interrupt sources */
118 SCB_INTR_SPI_EC_MASK(base) = 0UL;
119 SCB_INTR_I2C_EC_MASK(base) = 0UL;
120 SCB_INTR_RX_MASK(base) = 0UL;
121 SCB_INTR_TX_MASK(base) = 0UL;
122 SCB_INTR_M_MASK(base) = 0UL;
123 SCB_INTR_S_MASK(base) = CY_SCB_EZI2C_SLAVE_INTR;
124
125 /* Initialize the context */
126 context->status = 0UL;
127 context->state = CY_SCB_EZI2C_STATE_IDLE;
128
129 context->subAddrSize = config->subAddressSize;
130
131 context->buf1Size = 0UL;
132 context->buf1rwBondary = 0UL;
133 context->baseAddr1 = 0UL;
134
135 context->buf2Size = 0UL;
136 context->buf2rwBondary = 0UL;
137 context->baseAddr2 = 0UL;
138
139 return CY_SCB_EZI2C_SUCCESS;
140 }
141
142
143 /*******************************************************************************
144 * Function Name: Cy_SCB_EZI2C_DeInit
145 ****************************************************************************//**
146 *
147 * De-initializes the SCB block, returns the register values to default.
148 *
149 * \param base
150 * The pointer to the EZI2C SCB instance.
151 *
152 * \note
153 * Ensure that the SCB block is disabled before calling this function.
154 *
155 *******************************************************************************/
Cy_SCB_EZI2C_DeInit(CySCB_Type * base)156 void Cy_SCB_EZI2C_DeInit(CySCB_Type *base)
157 {
158 /* Return the block registers into the default state */
159 SCB_CTRL(base) = CY_SCB_CTRL_DEF_VAL;
160 SCB_I2C_CTRL(base) = CY_SCB_I2C_CTRL_DEF_VAL;
161
162 SCB_RX_CTRL(base) = CY_SCB_RX_CTRL_DEF_VAL;
163 SCB_RX_FIFO_CTRL(base) = 0UL;
164 SCB_RX_MATCH(base) = 0UL;
165
166 SCB_TX_CTRL(base) = CY_SCB_TX_CTRL_DEF_VAL;
167 SCB_TX_FIFO_CTRL(base) = 0UL;
168
169 SCB_INTR_SPI_EC_MASK(base) = 0UL;
170 SCB_INTR_I2C_EC_MASK(base) = 0UL;
171 SCB_INTR_RX_MASK(base) = 0UL;
172 SCB_INTR_TX_MASK(base) = 0UL;
173 SCB_INTR_M_MASK(base) = 0UL;
174 SCB_INTR_S_MASK(base) = 0UL;
175 }
176
177
178 /*******************************************************************************
179 * Function Name: Cy_SCB_EZI2C_Disable
180 ****************************************************************************//**
181 *
182 * Disables the SCB block and clears the context statuses.
183 * Note that after the block is disabled, the TX and RX FIFOs and hardware
184 * statuses are cleared. Also, the hardware stops driving the output and
185 * ignores the input.
186 *
187 * \param base
188 * The pointer to the EZI2C SCB instance.
189 *
190 * \param context
191 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
192 * allocated by the user. The structure is used during the EZI2C operation for
193 * internal configuration and data retention. The user must not modify anything
194 * in this structure.
195 *
196 * \note
197 * Calling this function while EZI2C is busy (the slave has been addressed and is
198 * communicating with the master), may cause transaction corruption because
199 * the hardware stops driving the output and ignores the input. Ensure that
200 * the EZI2C slave is not busy before calling this function.
201 *
202 *******************************************************************************/
Cy_SCB_EZI2C_Disable(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)203 void Cy_SCB_EZI2C_Disable(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
204 {
205 SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
206
207 /* Set the state to default and clear the statuses */
208 context->status = 0UL;
209 context->state = CY_SCB_EZI2C_STATE_IDLE;
210 }
211
212
213 /*******************************************************************************
214 * Function Name: Cy_SCB_EZI2C_DeepSleepCallback
215 ****************************************************************************//**
216 *
217 * This function handles the transition of the EZI2C SCB into and out of
218 * Deep Sleep mode. It prevents the device from entering Deep Sleep mode if
219 * the EZI2C slave is actively communicating.
220 * The following behavior of the EZI2C depends on whether the SCB block is
221 * wakeup-capable:
222 * * <b>Wakeup-capable</b>: on the incoming EZI2C slave address, the slave
223 * receives the address and stretches the clock until the device is woken from
224 * Deep Sleep mode. If the slave address occurs before the device enters
225 * Deep Sleep mode, the device will not enter Deep Sleep mode.
226 * * <b>Not wakeup-capable</b>: the EZI2C is disabled. It is enabled
227 * when the device fails to enter Deep Sleep mode or it is woken from Deep Sleep
228 * mode. While the EZI2C is disabled, it stops driving the outputs and
229 * ignores the input lines. The slave NACKs all incoming addresses.
230 *
231 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep.
232 * To do this, register this function as a callback before calling
233 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
234 * type and call \ref Cy_SysPm_RegisterCallback.
235 *
236 * \param callbackParams
237 * The pointer to the callback parameters structure.
238 * \ref cy_stc_syspm_callback_params_t.
239 *
240 * \param mode
241 * Callback mode, see \ref cy_en_syspm_callback_mode_t
242 *
243 * \return
244 * \ref cy_en_syspm_status_t
245 *
246 * \note
247 * Only applicable for <b>rev-08 of the CY8CKIT-062-BLE</b>.
248 * For proper operation, when the EZI2C slave is configured to be a wakeup source
249 * from Deep Sleep mode, this function must be copied and modified by the user.
250 * The EZI2C clock disable code must be inserted in the
251 * \ref CY_SYSPM_BEFORE_TRANSITION and clock enable code in the
252 * \ref CY_SYSPM_AFTER_TRANSITION mode processing.
253 *
254 *******************************************************************************/
Cy_SCB_EZI2C_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)255 cy_en_syspm_status_t Cy_SCB_EZI2C_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
256 {
257 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
258 cy_stc_scb_ezi2c_context_t *locContext = (cy_stc_scb_ezi2c_context_t *) callbackParams->context;
259
260 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
261
262 switch (mode)
263 {
264 case CY_SYSPM_CHECK_READY:
265 {
266 /* Disable the slave interrupt sources to protect the state */
267 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
268
269 /* If the EZI2C is in the IDLE state, it is ready for Deep Sleep
270 * mode. Otherwise, it returns fail and restores the slave interrupt
271 * sources.
272 */
273 if (CY_SCB_EZI2C_STATE_IDLE == locContext->state)
274 {
275 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
276 {
277 /* The SCB is wakeup-capable: do not restore the address
278 * match interrupt source. The next transaction intended
279 * for the slave will be paused (the SCL is stretched) before
280 * the address is ACKed because the corresponding interrupt
281 * source is disabled.
282 */
283 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR_NO_ADDR);
284 }
285 else
286 {
287 /* The SCB is NOT wakeup-capable: disable the EZI2C.
288 * The slave stops responding to the master until the
289 * EZI2C is enabled. This happens when the device fails
290 * to enter Deep Sleep mode or it is woken from Deep Sleep
291 * mode.
292 */
293 Cy_SCB_EZI2C_Disable(locBase, locContext);
294 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
295 }
296
297 retStatus = CY_SYSPM_SUCCESS;
298 }
299 else
300 {
301 /* Restore the slave interrupt sources */
302 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
303 }
304 }
305 break;
306
307 case CY_SYSPM_CHECK_FAIL:
308 {
309 /* The other driver is not ready for Deep Sleep mode. Restore
310 * Active mode configuration.
311 */
312
313 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
314 {
315 /* The SCB is wakeup-capable: restore the slave interrupt
316 * sources.
317 */
318 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
319 }
320 else
321 {
322 /* The SCB is NOT wakeup-capable: enable the slave to operate. */
323 Cy_SCB_EZI2C_Enable(locBase);
324 }
325
326 retStatus = CY_SYSPM_SUCCESS;
327 }
328 break;
329
330 case CY_SYSPM_BEFORE_TRANSITION:
331 {
332 /* This code executes inside the critical section and enabling the
333 * active interrupt source makes the interrupt pending in the NVIC.
334 * However, the interrupt processing is delayed until the code exists
335 * the critical section. The pending interrupt force WFI instruction
336 * does nothing and the device remains in Active mode.
337 */
338
339 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
340 {
341 /* The SCB is wakeup-capable: enable the I2C wakeup interrupt
342 * source. If any transaction was paused the the EZI2C interrupt
343 * becomes pending and prevents entering Deep Sleep mode.
344 * The transaction continues as soon as the global interrupts
345 * are enabled.
346 */
347 Cy_SCB_SetI2CInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
348
349 /* Disable SCB clock */
350 SCB_I2C_CFG(locBase) &= (uint32_t) ~CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
351
352 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
353 * for proper entering Deep Sleep mode the I2C clock must be disabled.
354 * This code must be inserted by the user because the driver
355 * does not have access to the clock.
356 */
357 }
358
359 retStatus = CY_SYSPM_SUCCESS;
360 }
361 break;
362
363 case CY_SYSPM_AFTER_TRANSITION:
364 {
365 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
366 {
367 /* Enable SCB clock */
368 SCB_I2C_CFG(locBase) |= CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
369
370 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
371 * for proper exiting Deep Sleep mode, the I2C clock must be enabled.
372 * This code must be inserted by the user because the driver
373 * does not have access to the clock.
374 */
375
376 /* The SCB is wakeup-capable: disable the I2C wakeup interrupt
377 * source and restore slave interrupt sources.
378 */
379 Cy_SCB_SetI2CInterruptMask (locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
380 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
381 }
382 else
383 {
384 /* The SCB is NOT wakeup-capable: enable the slave to operate */
385 Cy_SCB_EZI2C_Enable(locBase);
386 }
387
388 retStatus = CY_SYSPM_SUCCESS;
389 }
390 break;
391
392 default:
393 /* Unknown state */
394 break;
395 }
396
397 return (retStatus);
398 }
399
400
401 /*******************************************************************************
402 * Function Name: Cy_SCB_EZI2C_HibernateCallback
403 ****************************************************************************//**
404 *
405 * This function handles the transition of the EZI2C SCB block into Hibernate
406 * mode. It prevents the device from entering Hibernate mode if the EZI2C slave
407 * is actively communicating.
408 * If the EZI2C is ready to enter Hibernate mode, it is disabled. If the device
409 * fails to enter Hibernate mode, the EZI2C is enabled. While the EZI2C
410 * is disabled, it stops driving the output and ignores the inputs.
411 * The slave NACKs all incoming addresses.
412 *
413 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
414 * To do this, register this function as a callback before calling
415 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
416 * type and call \ref Cy_SysPm_RegisterCallback.
417 *
418 * \param callbackParams
419 * The pointer to the callback parameters structure
420 * \ref cy_stc_syspm_callback_params_t.
421 *
422 * \param mode
423 * Callback mode, see \ref cy_en_syspm_callback_mode_t
424 *
425 * \return
426 * \ref cy_en_syspm_status_t
427 *
428 *******************************************************************************/
Cy_SCB_EZI2C_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)429 cy_en_syspm_status_t Cy_SCB_EZI2C_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
430 {
431 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
432 cy_stc_scb_ezi2c_context_t *locContext = (cy_stc_scb_ezi2c_context_t *) callbackParams->context;
433
434 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
435
436 switch (mode)
437 {
438 case CY_SYSPM_CHECK_READY:
439 {
440 /* Disable the slave interrupt sources to protect the state */
441 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
442
443 /* If the EZI2C is in the IDLE state, it is ready for Hibernate mode.
444 * Otherwise, returns fail and restores the slave interrupt sources.
445 */
446 if (CY_SCB_EZI2C_STATE_IDLE == locContext->state)
447 {
448 /* Disable the EZI2C. It stops responding to the master until
449 * the EZI2C is enabled. This happens if the device fails to
450 * enter Hibernate mode.
451 */
452 Cy_SCB_EZI2C_Disable(locBase, locContext);
453
454 retStatus = CY_SYSPM_SUCCESS;
455 }
456
457 /* Restore the slave interrupt sources */
458 Cy_SCB_SetSlaveInterruptMask(locBase, CY_SCB_EZI2C_SLAVE_INTR);
459 }
460 break;
461
462 case CY_SYSPM_CHECK_FAIL:
463 {
464 /* The other driver is not ready for Hibernate mode. Restore the
465 * Active mode configuration.
466 */
467
468 /* Enable the slave to operate */
469 Cy_SCB_EZI2C_Enable(locBase);
470
471 retStatus = CY_SYSPM_SUCCESS;
472 }
473 break;
474
475 case CY_SYSPM_BEFORE_TRANSITION:
476 case CY_SYSPM_AFTER_TRANSITION:
477 {
478 /* The SCB is not capable of waking up from Hibernate mode: do nothing */
479 retStatus = CY_SYSPM_SUCCESS;
480 }
481 break;
482
483 default:
484 /* Unknown state */
485 break;
486 }
487
488 return (retStatus);
489 }
490
491
492 /*******************************************************************************
493 * Function Name: Cy_SCB_EZI2C_GetActivity
494 ****************************************************************************//**
495 *
496 * Returns a non-zero value if an I2C Read or Write cycle has occurred since the
497 * last time this function was called. All flags are reset to zero at the end of
498 * this function call, except the \ref CY_SCB_EZI2C_STATUS_BUSY.
499 *
500 * \param base
501 * The pointer to the EZI2C SCB instance.
502 *
503 * \param context
504 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
505 * allocated by the user. The structure is used during the EZI2C operation for
506 * internal configuration and data retention. The user must not modify anything
507 * in this structure.
508 *
509 * \return
510 * \ref group_scb_ezi2c_macros_get_activity.
511 *
512 *******************************************************************************/
Cy_SCB_EZI2C_GetActivity(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t * context)513 uint32_t Cy_SCB_EZI2C_GetActivity(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t *context)
514 {
515 uint32_t intrState;
516 uint32_t retStatus;
517
518 /* Suppress a compiler warning about unused variables */
519 (void) base;
520
521 intrState = Cy_SysLib_EnterCriticalSection();
522
523 retStatus = context->status;
524 context->status &= CY_SCB_EZI2C_STATUS_BUSY;
525
526 Cy_SysLib_ExitCriticalSection(intrState);
527
528 return (retStatus);
529 }
530
531
532 /*******************************************************************************
533 * Function Name: Cy_SCB_EZI2C_SetAddress1
534 ****************************************************************************//**
535 *
536 * Sets the primary EZI2C slave address.
537 *
538 * \param base
539 * The pointer to the EZI2C SCB instance.
540 *
541 * \param addr
542 * The 7-bit right justified slave address.
543 *
544 * \param context
545 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
546 * allocated by the user. The structure is used during the EZI2C operation for
547 * internal configuration and data retention. The user must not modify anything
548 * in this structure.
549 *
550 *******************************************************************************/
Cy_SCB_EZI2C_SetAddress1(CySCB_Type * base,uint8_t addr,cy_stc_scb_ezi2c_context_t * context)551 void Cy_SCB_EZI2C_SetAddress1(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context)
552 {
553 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(addr));
554 CY_ASSERT_L2(addr != context->address2);
555
556 context->address1 = addr;
557
558 CY_REG32_CLR_SET(SCB_RX_MATCH(base), SCB_RX_MATCH_ADDR, ((uint32_t)((uint32_t) addr << 1UL)));
559
560 UpdateAddressMask(base, context);
561 }
562
563
564 /*******************************************************************************
565 * Function Name: Cy_SCB_EZI2C_GetAddress1
566 ****************************************************************************//**
567 *
568 * Returns the primary the EZI2C slave address.
569 *
570 * \param base
571 * The pointer to the EZI2C SCB instance.
572 *
573 * * \param context
574 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
575 * allocated by the user. The structure is used during the EZI2C operation for
576 * internal configuration and data retention. The user must not modify anything
577 * in this structure.
578 *
579 * \return
580 * The 7-bit right justified slave address.
581 *
582 *******************************************************************************/
Cy_SCB_EZI2C_GetAddress1(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t const * context)583 uint32_t Cy_SCB_EZI2C_GetAddress1(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context)
584 {
585 /* Suppress a compiler warning about unused variables */
586 (void) base;
587
588 return ((uint32_t) context->address1);
589 }
590
591
592 /*******************************************************************************
593 * Function Name: Cy_SCB_EZI2C_SetBuffer1
594 ****************************************************************************//**
595 *
596 * Sets up the data buffer to be exposed to the I2C master on the primary slave
597 * address request.
598 *
599 * \param base
600 * The pointer to the EZI2C SCB instance.
601 *
602 * \param buffer
603 * The pointer to the data buffer.
604 *
605 * \param size
606 * The size of the buffer in bytes.
607 *
608 * \param rwBoundary
609 * The number of data bytes starting from the beginning of the buffer with Read and
610 * Write access. The data bytes located at rwBoundary or greater are read only.
611 *
612 * \param context
613 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
614 * allocated by the user. The structure is used during the EZI2C operation for
615 * internal configuration and data retention. The user must not modify anything
616 * in this structure.
617 *
618 * \note
619 * * This function is not interrupt-protected and to prevent a race condition,
620 * it must be protected from the EZI2C interruption in the place where it
621 * is called.
622 * * Calling this function in the middle of a transaction intended for the
623 * secondary slave address leads to unexpected behavior.
624 *
625 *******************************************************************************/
Cy_SCB_EZI2C_SetBuffer1(CySCB_Type const * base,uint8_t * buffer,uint32_t size,uint32_t rwBoundary,cy_stc_scb_ezi2c_context_t * context)626 void Cy_SCB_EZI2C_SetBuffer1(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
627 cy_stc_scb_ezi2c_context_t *context)
628 {
629 CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
630 CY_ASSERT_L2(rwBoundary <= size);
631
632 /* Suppress a compiler warning about unused variables */
633 (void) base;
634
635 context->buf1 = buffer;
636 context->buf1Size = size;
637 context->buf1rwBondary = rwBoundary;
638 }
639
640
641 /*******************************************************************************
642 * Function Name: Cy_SCB_EZI2C_SetAddress2
643 ****************************************************************************//**
644 *
645 * Sets the secondary EZI2C slave address.
646 *
647 * \param base
648 * The pointer to the EZI2C SCB instance.
649 *
650 * \param addr
651 * The 7-bit right justified slave address.
652 *
653 * \param context
654 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
655 * allocated by the user. The structure is used during the EZI2C operation for
656 * internal configuration and data retention. The user must not modify anything
657 * in this structure.
658 *
659 * \note
660 * Calling this function when the EZI2C slave is configured for one-address
661 * operation leads to unexpected behavior because it updates the address mask.
662 *
663 *******************************************************************************/
Cy_SCB_EZI2C_SetAddress2(CySCB_Type * base,uint8_t addr,cy_stc_scb_ezi2c_context_t * context)664 void Cy_SCB_EZI2C_SetAddress2(CySCB_Type *base, uint8_t addr, cy_stc_scb_ezi2c_context_t *context)
665 {
666 CY_ASSERT_L2(CY_SCB_IS_I2C_ADDR_VALID(addr));
667 CY_ASSERT_L2(addr != context->address1);
668
669 context->address2 = addr;
670
671 UpdateAddressMask(base, context);
672 }
673
674
675 /*******************************************************************************
676 * Function Name: Cy_SCB_EZI2C_GetAddress2
677 ****************************************************************************//**
678 *
679 * Returns the secondary EZI2C slave address.
680 *
681 * \param base
682 * The pointer to the EZI2C SCB instance.
683 *
684 * \param context
685 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
686 * allocated by the user. The structure is used during the EZI2C operation for
687 * internal configuration and data retention. The user must not modify anything
688 * in this structure.
689 *
690 * \return
691 * The 7-bit right justified slave address.
692 *
693 *******************************************************************************/
Cy_SCB_EZI2C_GetAddress2(CySCB_Type const * base,cy_stc_scb_ezi2c_context_t const * context)694 uint32_t Cy_SCB_EZI2C_GetAddress2(CySCB_Type const *base, cy_stc_scb_ezi2c_context_t const *context)
695 {
696 /* Suppress a compiler warning about unused variables */
697 (void) base;
698
699 return ((uint32_t) context->address2);
700 }
701
702
703 /*******************************************************************************
704 * Function Name: Cy_SCB_EZI2C_SetBuffer2
705 ****************************************************************************//**
706 *
707 * Sets up the data buffer to be exposed to the I2C master on the secondary
708 * slave address request.
709 *
710 * \param base
711 * The pointer to the EZI2C SCB instance.
712 *
713 * \param buffer
714 * The pointer to the data buffer.
715 *
716 * \param size
717 * The size of the buffer in bytes.
718 *
719 * \param rwBoundary
720 * The number of data bytes starting from the beginning of the buffer with Read and
721 * Write access. The data bytes located at rwBoundary or greater are read only.
722 *
723 * \param context
724 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t
725 * allocated by the user. The structure is used during the EZI2C operation for
726 * internal configuration and data retention. The user must not modify anything
727 * in this structure.
728 *
729 * \note
730 * * This function is not interrupt-protected. To prevent a race condition,
731 * it must be protected from the EZI2C interruption in the place where it
732 * is called.
733 * * Calling this function in the middle of a transaction intended for the
734 * secondary slave address leads to unexpected behavior.
735 *
736 *******************************************************************************/
Cy_SCB_EZI2C_SetBuffer2(CySCB_Type const * base,uint8_t * buffer,uint32_t size,uint32_t rwBoundary,cy_stc_scb_ezi2c_context_t * context)737 void Cy_SCB_EZI2C_SetBuffer2(CySCB_Type const *base, uint8_t *buffer, uint32_t size, uint32_t rwBoundary,
738 cy_stc_scb_ezi2c_context_t *context)
739 {
740 CY_ASSERT_L1(CY_SCB_IS_I2C_BUFFER_VALID(buffer, size));
741 CY_ASSERT_L2(rwBoundary <= size);
742
743 /* Suppress a compiler warning about unused variables */
744 (void) base;
745
746 context->buf2 = buffer;
747 context->buf2Size = size;
748 context->buf2rwBondary = rwBoundary;
749 }
750
751
752 /*******************************************************************************
753 * Function Name: Cy_SCB_EZI2C_Interrupt
754 ****************************************************************************//**
755 *
756 * This is the interrupt function for the SCB configured in the EZI2C mode.
757 * This function must be called inside the user-defined interrupt service
758 * routine to make the EZI2C slave work.
759 *
760 * \param base
761 * The pointer to the EZI2C SCB instance.
762 *
763 * \param context
764 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
765 * by the user. The structure is used during the EZI2C operation for internal
766 * configuration and data retention. The user must not modify anything
767 * in this structure.
768 *
769 *******************************************************************************/
Cy_SCB_EZI2C_Interrupt(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)770 void Cy_SCB_EZI2C_Interrupt(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
771 {
772 uint32_t slaveIntrStatus;
773
774 /* Handle an I2C wake-up event */
775 if (0UL != (CY_SCB_I2C_INTR_WAKEUP & Cy_SCB_GetI2CInterruptStatusMasked(base)))
776 {
777 /* Move from IDLE state, the slave was addressed. Following address match
778 * interrupt continue transfer.
779 */
780 context->state = CY_SCB_EZI2C_STATE_ADDR;
781
782 Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
783 }
784
785 /* Get the slave interrupt sources */
786 slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
787
788 /* Handle the error conditions */
789 if (0UL != (CY_SCB_EZI2C_SLAVE_INTR_ERROR & slaveIntrStatus))
790 {
791 HandleErrors(base, context);
792
793 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_EZI2C_SLAVE_INTR_ERROR);
794
795 /* Trigger the stop handling to complete the transaction */
796 slaveIntrStatus |= CY_SCB_SLAVE_INTR_I2C_STOP;
797 }
798 else
799 {
800 if ((CY_SCB_EZI2C_STATE_RX_DATA1 == context->state) &&
801 (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus)))
802 {
803 /* Get data from the RX FIFO after Stop is generated */
804 Cy_SCB_SetRxInterrupt (base, CY_SCB_RX_INTR_LEVEL);
805 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
806 }
807 }
808
809 /* Handle the receive direction (master writes data) */
810 if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
811 {
812 HandleDataReceive(base, context);
813
814 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
815 }
816
817 /* Handle the transaction completion */
818 if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
819 {
820 HandleStop(base, context);
821
822 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);
823
824 /* Update the slave interrupt status */
825 slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
826 }
827
828 /* Handle the address byte */
829 if (0UL != (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH & slaveIntrStatus))
830 {
831 HandleAddress(base, context);
832
833 Cy_SCB_ClearI2CInterrupt (base, CY_SCB_I2C_INTR_WAKEUP);
834 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH);
835 }
836
837 /* Handle the transmit direction (master reads data) */
838 if (0UL != (CY_SCB_TX_INTR_LEVEL & Cy_SCB_GetTxInterruptStatusMasked(base)))
839 {
840 HandleDataTransmit(base, context);
841
842 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
843 }
844 }
845
846
847
848 /*******************************************************************************
849 * Function Name: HandleErrors
850 ****************************************************************************//**
851 *
852 * Handles an error conditions.
853 *
854 * \param base
855 * The pointer to the EZI2C SCB instance.
856 *
857 * \param context
858 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
859 * by the user. The structure is used during the EZI2C operation for internal
860 * configuration and data retention. The user must not modify anything
861 * in this structure.
862 *
863 *******************************************************************************/
HandleErrors(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)864 static void HandleErrors(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
865 {
866 context->status |= CY_SCB_EZI2C_STATUS_ERR;
867
868 /* Drop any data available in the RX FIFO */
869 Cy_SCB_ClearRxFifo(base);
870
871 /* Stop the TX and RX processing */
872 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
873 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
874 }
875
876
877 /*******************************************************************************
878 * Function Name: HandleAddress
879 ****************************************************************************//**
880 *
881 * Prepares the EZI2C slave for the following read or write transfer after the
882 * matched address was received.
883 *
884 * \param base
885 * The pointer to the EZI2C SCB instance.
886 *
887 * \param context
888 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
889 * by the user. The structure is used during the EZI2C operation for internal
890 * configuration and data retention. The user must not modify anything
891 * in this structure.
892 *
893 *******************************************************************************/
HandleAddress(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)894 static void HandleAddress(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
895 {
896 /* Default actions: ACK address 1 */
897 uint32_t cmd = SCB_I2C_S_CMD_S_ACK_Msk;
898 context->addr1Active = true;
899
900 if (0U != context->address2)
901 {
902 /* Get an address from the RX FIFO and make it a 7-bit address */
903 uint32_t address = (Cy_SCB_ReadRxFifo(base) >> 1UL);
904 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
905
906 /* Decide whether the address matches */
907 if ((address == context->address1) || (address == context->address2))
908 {
909 /* ACK the address */
910 if (address == context->address2)
911 {
912 context->addr1Active = false;
913 }
914
915 /* Clear and enable the stop interrupt source */
916 Cy_SCB_ClearSlaveInterrupt (base, CY_SCB_SLAVE_INTR_I2C_STOP);
917 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR);
918 }
919 else
920 {
921 /* NACK the address */
922 cmd = SCB_I2C_S_CMD_S_NACK_Msk;
923
924 /* Disable the stop interrupt source */
925 Cy_SCB_SetI2CInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR_NO_STOP);
926 }
927 }
928
929 /* Clear the TX FIFO before continuing the transaction */
930 Cy_SCB_ClearTxFifo(base);
931
932 /* Set the command to an ACK or NACK address */
933 SCB_I2C_S_CMD(base) = cmd;
934
935 if (cmd == SCB_I2C_S_CMD_S_ACK_Msk)
936 {
937 context->status |= CY_SCB_EZI2C_STATUS_BUSY;
938
939 /* Prepare for a transaction */
940 if (_FLD2BOOL(SCB_I2C_STATUS_S_READ, SCB_I2C_STATUS(base)))
941 {
942 /* The master reads data from the slave */
943 context->state = CY_SCB_EZI2C_STATE_TX_DATA;
944
945 /* Prepare the buffer for transmit */
946 if (context->addr1Active)
947 {
948 context->curBuf = &context->buf1[context->baseAddr1];
949 context->bufSize = context->buf1Size - context->baseAddr1;
950 }
951 else
952 {
953 context->curBuf = &context->buf2[context->baseAddr2];
954 context->bufSize = context->buf2Size - context->baseAddr2;
955 }
956
957 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
958 }
959 else
960 {
961 /* The master writes data into the slave */
962 context->state = CY_SCB_EZI2C_STATE_RX_OFFSET_MSB;
963
964 context->bufSize = ((context->addr1Active) ? context->buf1Size : context->buf2Size);
965
966 Cy_SCB_SetRxFifoLevel (base, 0UL);
967 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
968 }
969 }
970 }
971
972
973 /*******************************************************************************
974 * Function Name: HandleDataReceive
975 ****************************************************************************//**
976 *
977 * Updates the RX FIFO level to trigger the next read from it. It also manages
978 * the auto-data NACK feature.
979 *
980 * \param base
981 * The pointer to the EZI2C SCB instance.
982 *
983 * \param bufSize
984 * The size of the buffer in bytes.
985 *
986 *******************************************************************************/
UpdateRxFifoLevel(CySCB_Type * base,uint32_t bufSize)987 static void UpdateRxFifoLevel(CySCB_Type *base, uint32_t bufSize)
988 {
989 uint32_t level;
990 uint32_t fifoSize = CY_SCB_EZI2C_FIFO_SIZE;
991
992 if (bufSize > fifoSize)
993 {
994 /* Continue the transaction: there is space in the buffer */
995 level = (bufSize - fifoSize);
996 level = ((level > fifoSize) ? (fifoSize / 2UL) : level) - 1UL;
997 }
998 else
999 {
1000 /* Prepare to end the transaction: after the FIFO becomes full, NACK the next byte.
1001 * The NACKed byte is dropped by the hardware.
1002 */
1003 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;
1004
1005 level = ((bufSize == 0UL) ? (0UL) : (bufSize - 1UL));
1006 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1007 }
1008
1009 Cy_SCB_SetRxFifoLevel(base, level);
1010 }
1011
1012
1013 /*******************************************************************************
1014 * Function Name: HandleDataReceive
1015 ****************************************************************************//**
1016 *
1017 * Handles the data read from the RX FIFO.
1018 *
1019 * \param base
1020 * The pointer to the EZI2C SCB instance.
1021 *
1022 * \param context
1023 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1024 * by the user. The structure is used during the EZI2C operation for internal
1025 * configuration and data retention. The user must not modify anything
1026 * in this structure.
1027 *
1028 *******************************************************************************/
HandleDataReceive(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1029 static void HandleDataReceive(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1030 {
1031 switch(context->state)
1032 {
1033 case CY_SCB_EZI2C_STATE_RX_OFFSET_MSB:
1034 case CY_SCB_EZI2C_STATE_RX_OFFSET_LSB:
1035 {
1036 /* Default actions: compare the base address and ACK it */
1037 bool checkBaseAddr = true;
1038
1039 /* Get the base address from the RX FIFO */
1040 uint32_t baseAddr = Cy_SCB_ReadRxFifo(base);
1041
1042 if (context->subAddrSize == CY_SCB_EZI2C_SUB_ADDR16_BITS)
1043 {
1044 if (context->state == CY_SCB_EZI2C_STATE_RX_OFFSET_MSB)
1045 {
1046 /* ACK base address MSB */
1047 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
1048
1049 /* Temporary store base address MSB */
1050 context->idx = (uint32_t) (baseAddr << 8UL);
1051
1052 /* Do not compare until 16 bits are received */
1053 checkBaseAddr = false;
1054 context->state = CY_SCB_EZI2C_STATE_RX_OFFSET_LSB;
1055 }
1056 else
1057 {
1058 /* Get the base address (MSB | LSB) */
1059 baseAddr |= context->idx;
1060 }
1061 }
1062
1063 /* Check whether the received base address is valid */
1064 if (checkBaseAddr)
1065 {
1066 uint32_t cmd = SCB_I2C_S_CMD_S_ACK_Msk;
1067
1068 /* Decide whether the base address within the buffer range */
1069 if (baseAddr < context->bufSize)
1070 {
1071 /* Accept the new base address */
1072 if (context->addr1Active)
1073 {
1074 context->baseAddr1 = baseAddr;
1075 }
1076 else
1077 {
1078 context->baseAddr2 = baseAddr;
1079 }
1080
1081 /* Store the base address to use it later */
1082 context->idx = baseAddr;
1083 }
1084 else
1085 {
1086 /* Restore the valid base address */
1087 context->idx = ((context->addr1Active) ? context->baseAddr1 : context->baseAddr2);
1088
1089 /* The base address is out of range - NACK it */
1090 cmd = SCB_I2C_S_CMD_S_NACK_Msk;
1091 }
1092
1093 /* Set the command to an ACK or NACK address */
1094 SCB_I2C_S_CMD(base) = cmd;
1095
1096 if (cmd == SCB_I2C_S_CMD_S_ACK_Msk)
1097 {
1098 /* Prepare the buffer for a write */
1099 if (context->addr1Active)
1100 {
1101 context->curBuf = &context->buf1[context->baseAddr1];
1102 context->bufSize = ((context->baseAddr1 < context->buf1rwBondary) ?
1103 (context->buf1rwBondary - context->baseAddr1) : (0UL));
1104 }
1105 else
1106 {
1107 context->curBuf = &context->buf2[context->baseAddr2];
1108 context->bufSize = ((context->baseAddr2 < context->buf2rwBondary) ?
1109 (context->buf2rwBondary - context->baseAddr2) : (0UL));
1110 }
1111
1112 /* Choice receive scheme */
1113 if ((0U != context->address2) || (context->bufSize < CY_SCB_EZI2C_FIFO_SIZE))
1114 {
1115 /* Handle each byte separately */
1116 context->state = CY_SCB_EZI2C_STATE_RX_DATA0;
1117 }
1118 else
1119 {
1120 /* Use the RX FIFO and the auto-ACK/NACK features */
1121 SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_READY_DATA_ACK_Msk;
1122 UpdateRxFifoLevel(base, context->bufSize);
1123
1124 context->state = CY_SCB_EZI2C_STATE_RX_DATA1;
1125 }
1126 }
1127 }
1128 }
1129 break;
1130
1131 case CY_SCB_EZI2C_STATE_RX_DATA0:
1132 {
1133 uint32_t byte = Cy_SCB_ReadRxFifo(base);
1134
1135 /* Check whether there is space to store the byte */
1136 if (context->bufSize > 0UL)
1137 {
1138 /* Continue the transfer: send an ACK */
1139 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_ACK_Msk;
1140
1141 /* Store the byte in the buffer */
1142 context->curBuf[0UL] = (uint8_t) byte;
1143 context->bufSize--;
1144 context->curBuf++;
1145
1146 /* Update the base address to notice that the buffer is modified */
1147 context->idx++;
1148 }
1149 else
1150 {
1151 /* Finish the transfer: send a NACK. Drop the received byte */
1152 SCB_I2C_S_CMD(base) = SCB_I2C_S_CMD_S_NACK_Msk;
1153 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1154 }
1155 }
1156 break;
1157
1158 case CY_SCB_EZI2C_STATE_RX_DATA1:
1159 {
1160 /* Get the number of bytes to read from the RX FIFO */
1161 uint32_t numToCopy = Cy_SCB_GetRxFifoLevel(base) + 1UL;
1162
1163 /* Get data from the RX FIFO */
1164 numToCopy = Cy_SCB_ReadArray(base, context->curBuf, numToCopy);
1165 context->bufSize -= numToCopy;
1166 context->curBuf += numToCopy;
1167
1168 /* Configure the next RX FIFO read event */
1169 UpdateRxFifoLevel(base, context->bufSize);
1170
1171 /* Update the base address to notice that the buffer is modified */
1172 context->idx++;
1173 }
1174 break;
1175
1176 default:
1177 /* Unknown state */
1178 break;
1179 }
1180 }
1181
1182
1183 /*******************************************************************************
1184 * Function Name: HandleDataTransmit
1185 ****************************************************************************//**
1186 *
1187 * Loads the TX FIFO with data from the buffer.
1188 *
1189 * \param base
1190 * The pointer to the EZI2C SCB instance.
1191 *
1192 * \param context
1193 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1194 * by the user. The structure is used during the EZI2C operation for internal
1195 * configuration and data retention. The user must not modify anything
1196 * in this structure.
1197 *
1198 *******************************************************************************/
HandleDataTransmit(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1199 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1200 {
1201 if (context->bufSize > 0UL)
1202 {
1203 /* Write data into the TX FIFO from the buffer */
1204 uint32_t numToCopy = Cy_SCB_WriteArray(base, context->curBuf, context->bufSize);
1205 context->bufSize -= numToCopy;
1206 context->curBuf += numToCopy;
1207 }
1208
1209 if (0UL == context->bufSize)
1210 {
1211 /* Write the default bytes into the TX FIFO */
1212 (void) Cy_SCB_WriteDefaultArray(base, CY_SCB_EZI2C_DEFAULT_TX, CY_SCB_EZI2C_FIFO_SIZE);
1213 }
1214 }
1215
1216
1217 /*******************************************************************************
1218 * Function Name: HandleStop
1219 ****************************************************************************//**
1220 *
1221 * Handles the transfer completion.
1222 * It is triggered by a Stop or Restart condition on the bus.
1223 *
1224 * \param base
1225 * The pointer to the EZI2C SCB instance.
1226 *
1227 * \param context
1228 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1229 * by the user. The structure is used during the EZI2C operation for internal
1230 * configuration and data retention. The user must not modify anything
1231 * in this structure.
1232 *
1233 *******************************************************************************/
HandleStop(CySCB_Type * base,cy_stc_scb_ezi2c_context_t * context)1234 static void HandleStop(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
1235 {
1236 /* Check for errors */
1237 if (0UL != (CY_SCB_EZI2C_STATUS_ERR & context->status))
1238 {
1239 /* Re-enable the SCB to recover from errors */
1240 Cy_SCB_FwBlockReset(base);
1241 }
1242
1243 /* Clean up the hardware to be ready for the next transaction */
1244 if (CY_SCB_EZI2C_STATE_TX_DATA == context->state)
1245 {
1246 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1247 }
1248 else
1249 {
1250 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1251
1252 SCB_I2C_CTRL(base) &= (uint32_t) ~(SCB_I2C_CTRL_S_READY_DATA_ACK_Msk |
1253 SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk);
1254 }
1255
1256 /* Update the statuses */
1257 context->status &= (uint32_t) ~CY_SCB_EZI2C_STATUS_BUSY;
1258
1259 if (context->addr1Active)
1260 {
1261 context->status |= ((CY_SCB_EZI2C_STATE_TX_DATA == context->state) ? CY_SCB_EZI2C_STATUS_READ1 :
1262 ((context->baseAddr1 != context->idx) ? CY_SCB_EZI2C_STATUS_WRITE1 : 0UL));
1263 }
1264 else
1265 {
1266 context->status |= ((CY_SCB_EZI2C_STATE_TX_DATA == context->state) ? CY_SCB_EZI2C_STATUS_READ2 :
1267 ((context->baseAddr2 != context->idx) ? CY_SCB_EZI2C_STATUS_WRITE2 : 0UL));
1268 }
1269
1270 /* Back to the idle state */
1271 context->state = CY_SCB_EZI2C_STATE_IDLE;
1272 }
1273
1274
1275 /*******************************************************************************
1276 * Function Name: UpdateAddressMask
1277 ****************************************************************************//**
1278 *
1279 * Updates the slave address mask to enable the SCB hardware to receive matching
1280 * slave addresses.
1281 *
1282 * \param base
1283 * The pointer to the EZI2C SCB instance.
1284 *
1285 * \param context
1286 * The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
1287 * by the user. The structure is used during the EZI2C operation for internal
1288 * configuration and data retention. The user must not modify anything
1289 * in this structure.
1290 *
1291 *******************************************************************************/
UpdateAddressMask(CySCB_Type * base,cy_stc_scb_ezi2c_context_t const * context)1292 static void UpdateAddressMask(CySCB_Type *base, cy_stc_scb_ezi2c_context_t const *context)
1293 {
1294 uint32_t addrMask;
1295
1296 /* Check how many addresses are used: */
1297 if (0U != context->address2)
1298 {
1299 /* If (addr1 and addr2) bits match - mask bit equals 1; otherwise 0 */
1300 addrMask = (uint32_t) ~((uint32_t) context->address1 ^ (uint32_t) context->address2);
1301 }
1302 else
1303 {
1304 addrMask = CY_SCB_EZI2C_ONE_ADDRESS_MASK;
1305 }
1306
1307 /* Update the hardware address match */
1308 CY_REG32_CLR_SET(SCB_RX_MATCH(base), SCB_RX_MATCH_MASK, ((uint32_t) addrMask << 1UL));
1309 }
1310
1311
1312 #if defined(__cplusplus)
1313 }
1314 #endif
1315
1316 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
1317
1318 /* [] END OF FILE */
1319