1 /*******************************************************************************
2 * File Name: cyhal_i2c.c
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Infineon I2C. This is
6 * a wrapper around the lower level PDL API.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include "cyhal_i2c.h"
31 #include "cyhal_scb_common.h"
32 #include "cyhal_gpio.h"
33 #include "cyhal_hwmgr.h"
34 #include "cyhal_system.h"
35 #include "cyhal_syspm.h"
36 #include "cyhal_utils.h"
37 #include "cyhal_irq_impl.h"
38 #include "cyhal_clock.h"
39
40 #if (CYHAL_DRIVER_AVAILABLE_I2C)
41
42 #if defined(__cplusplus)
43 extern "C"
44 {
45 #endif
46
47 #define _CYHAL_I2C_PENDING_NONE 0
48 #define _CYHAL_I2C_PENDING_RX 1
49 #define _CYHAL_I2C_PENDING_TX 2
50 #define _CYHAL_I2C_PENDING_TX_RX 3
51
52 #define _CYHAL_I2C_MASTER_DEFAULT_FREQ 100000
53
54
55 static const _cyhal_buffer_info_t _cyhal_i2c_buff_info_default = {
56 .addr = {NULL},
57 .size = 0,
58 };
59
60 static const cy_stc_scb_i2c_config_t _cyhal_i2c_default_config = {
61 .i2cMode = CY_SCB_I2C_MASTER,
62 .useRxFifo = false,
63 .useTxFifo = true,
64 .slaveAddress = 0U,
65 .slaveAddressMask = 0U,
66 .acceptAddrInFifo = false,
67 .ackGeneralAddr = false,
68 .enableWakeFromSleep = false,
69 .enableDigitalFilter = false,
70 .lowPhaseDutyCycle = 8U,
71 .highPhaseDutyCycle = 8U,
72 };
73
74
75 /* The PDL clears the IRQ status during Cy_SCB_I2C_Interrupt which prevents _cyhal_scb_get_irq_obj()
76 * from working properly in _cyhal_i2c_cb_wrapper on devices with muxed IRQs, because they can't tell
77 * at that point which system IRQ caused the CPU IRQ. So we need to save this value at the beginning of the
78 * IRQ handler when we are able to determine what it is */
79 static volatile cyhal_i2c_t* _cyhal_i2c_irq_obj = NULL;
80
_cyhal_i2c_convert_interrupt_cause(uint32_t pdl_cause)81 static cyhal_i2c_event_t _cyhal_i2c_convert_interrupt_cause(uint32_t pdl_cause)
82 {
83 static const uint32_t status_map1[] =
84 {
85 (uint32_t)CYHAL_I2C_EVENT_NONE, // Default no event
86 (uint32_t)CYHAL_I2C_SLAVE_READ_EVENT, // CY_SCB_I2C_SLAVE_READ_EVENT
87 (uint32_t)CYHAL_I2C_SLAVE_WRITE_EVENT, // CY_SCB_I2C_SLAVE_WRITE_EVENT
88 (uint32_t)CYHAL_I2C_SLAVE_RD_IN_FIFO_EVENT, // CY_SCB_I2C_SLAVE_RD_IN_FIFO_EVENT
89 (uint32_t)CYHAL_I2C_SLAVE_RD_BUF_EMPTY_EVENT, // CY_SCB_I2C_SLAVE_RD_BUF_EMPTY_EVENT
90 (uint32_t)CYHAL_I2C_SLAVE_RD_CMPLT_EVENT, // CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT
91 (uint32_t)CYHAL_I2C_SLAVE_WR_CMPLT_EVENT, // CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT
92 (uint32_t)CYHAL_I2C_SLAVE_ERR_EVENT, // CY_SCB_I2C_SLAVE_ERR_EVENT
93 };
94 uint32_t set1 = _cyhal_utils_convert_flags(status_map1, sizeof(status_map1) / sizeof(uint32_t), pdl_cause & 0xFF);
95
96 static const uint32_t status_map2[] =
97 {
98 (uint32_t)CYHAL_I2C_EVENT_NONE, // Default no event
99 (uint32_t)CYHAL_I2C_MASTER_WR_IN_FIFO_EVENT, // CY_SCB_I2C_MASTER_WR_IN_FIFO_EVENT
100 (uint32_t)CYHAL_I2C_MASTER_WR_CMPLT_EVENT, // CY_SCB_I2C_MASTER_WR_CMPLT_EVENT
101 (uint32_t)CYHAL_I2C_MASTER_RD_CMPLT_EVENT, // CY_SCB_I2C_MASTER_RD_CMPLT_EVENT
102 (uint32_t)CYHAL_I2C_MASTER_ERR_EVENT, // CY_SCB_I2C_MASTER_ERR_EVENT
103 };
104 uint32_t set2 = _cyhal_utils_convert_flags(status_map2, sizeof(status_map2) / sizeof(uint32_t), pdl_cause >> 16);
105
106 return (cyhal_i2c_event_t)(set1 | set2);
107 }
108
_cyhal_i2c_convert_addr_interrupt_cause(uint32_t pdl_cause)109 static cyhal_i2c_addr_event_t _cyhal_i2c_convert_addr_interrupt_cause(uint32_t pdl_cause)
110 {
111 static const uint32_t status_map1[] =
112 {
113 (uint32_t)CYHAL_I2C_ADDR_EVENT_NONE, // Default no event
114 (uint32_t)CYHAL_I2C_GENERAL_CALL_EVENT, // CY_SCB_I2C_READ_EVENT
115 (uint32_t)CYHAL_I2C_ADDR_MATCH_EVENT, // CY_SCB_I2C_ADDR_IN_FIFO_EVENT
116 };
117 uint32_t set1 = _cyhal_utils_convert_flags(status_map1, sizeof(status_map1) / sizeof(uint32_t), pdl_cause & 0xFF);
118
119 return (cyhal_i2c_addr_event_t)(set1);
120 }
121
122 #if defined (COMPONENT_CAT5)
_cyhal_i2c_irq_handler(_cyhal_system_irq_t irqn)123 static void _cyhal_i2c_irq_handler(_cyhal_system_irq_t irqn)
124 #else
125 static void _cyhal_i2c_irq_handler(void)
126 #endif
127 {
128 /* Save the old value and store it aftewards in case we get into a nested IRQ situation */
129 /* Safe to cast away volatile because we don't expect this pointer to be changed while we're in here, they
130 * just might change where the original pointer points */
131 cyhal_i2c_t* old_irq_obj = (cyhal_i2c_t*)_cyhal_i2c_irq_obj;
132 #if defined (COMPONENT_CAT5)
133 _cyhal_i2c_irq_obj = (cyhal_i2c_t*) _cyhal_scb_get_irq_obj(irqn);
134 #else
135 _cyhal_i2c_irq_obj = (cyhal_i2c_t*) _cyhal_scb_get_irq_obj();
136 #endif
137 cyhal_i2c_t* obj = (cyhal_i2c_t*)_cyhal_i2c_irq_obj;
138
139 Cy_SCB_I2C_Interrupt(obj->base, &(obj->context));
140
141 if (obj->pending)
142 {
143 /* This code is part of cyhal_i2c_master_transfer_async() API functionality */
144 /* cyhal_i2c_master_transfer_async() API uses this interrupt handler for RX transfer */
145 if (0 == (Cy_SCB_I2C_MasterGetStatus(obj->base, &obj->context) & CY_SCB_I2C_MASTER_BUSY))
146 {
147 /* Check if TX is completed and run RX in case when TX and RX are enabled */
148 if (obj->pending == _CYHAL_I2C_PENDING_TX_RX)
149 {
150 /* Start RX transfer */
151 obj->pending = _CYHAL_I2C_PENDING_RX;
152 Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
153 }
154 else
155 {
156 /* Finish async TX or RX separate transfer */
157 obj->pending = _CYHAL_I2C_PENDING_NONE;
158 }
159 }
160 }
161
162 _cyhal_i2c_irq_obj = old_irq_obj;
163 }
164
165 #if defined (COMPONENT_CAT5)
_cyhal_i2c0_irq_handler(void)166 static void _cyhal_i2c0_irq_handler(void)
167 {
168 _cyhal_i2c_irq_handler(scb_0_interrupt_IRQn);
169 }
170
_cyhal_i2c1_irq_handler(void)171 static void _cyhal_i2c1_irq_handler(void)
172 {
173 _cyhal_i2c_irq_handler(scb_1_interrupt_IRQn);
174 }
175
_cyhal_i2c2_irq_handler(void)176 static void _cyhal_i2c2_irq_handler(void)
177 {
178 _cyhal_i2c_irq_handler(scb_2_interrupt_IRQn);
179 }
180
181 static CY_SCB_IRQ_THREAD_CB_t _cyhal_irq_cb[3] = {_cyhal_i2c0_irq_handler, _cyhal_i2c1_irq_handler, _cyhal_i2c2_irq_handler};
182 #endif
183
_cyhal_i2c_cb_wrapper(uint32_t event)184 static void _cyhal_i2c_cb_wrapper(uint32_t event)
185 {
186 /* Safe to cast away volatile because we don't expect this pointer to be changed while we're in here, they
187 * just might change where the original pointer points */
188 cyhal_i2c_t *obj = (cyhal_i2c_t*)_cyhal_i2c_irq_obj;
189 cyhal_i2c_event_t anded_events = (cyhal_i2c_event_t)(obj->irq_cause & (uint32_t)_cyhal_i2c_convert_interrupt_cause(event));
190 if (anded_events)
191 {
192 /* Indicates read/write operations will be in a callback */
193 obj->op_in_callback = true;
194 cyhal_i2c_event_callback_t callback = (cyhal_i2c_event_callback_t) obj->callback_data.callback;
195 callback(obj->callback_data.callback_arg, anded_events);
196 obj->op_in_callback = false;
197 }
198 }
199
_cyhal_i2c_cb_addr_wrapper(uint32_t event)200 static cy_en_scb_i2c_command_t _cyhal_i2c_cb_addr_wrapper(uint32_t event)
201 {
202 /* Safe to cast away volatile because we don't expect this pointer to be changed while we're in here, they
203 * just might change where the original pointer points */
204 cyhal_i2c_t *obj = (cyhal_i2c_t*)_cyhal_i2c_irq_obj;
205 cyhal_i2c_addr_event_t addr_events = (cyhal_i2c_addr_event_t)(obj->addr_irq_cause & (uint32_t)_cyhal_i2c_convert_addr_interrupt_cause(event));
206 uint8_t device_address = 0;
207 /* The default command is the ACK address. It can be overridden in an address callback */
208 cyhal_i2c_command_rsp_t cmd = CYHAL_I2C_CMD_ACK;
209 if (addr_events)
210 {
211 /* If ADDR_IN_FIFO_EVENT received, HAL need to read the device address using Cy_SCB_ReadRxFifo API as per I2C PDL documentation */
212 if (0L != (CYHAL_I2C_ADDR_MATCH_EVENT & addr_events))
213 {
214 /* Slave address stored in PDL is shifted left by 1, so to get correct slave address need to do LSR by 1 */
215 device_address = (Cy_SCB_ReadRxFifo(obj->base)) >> 1;
216 }
217 /* Indicates read/write operations will be in a callback */
218 obj->op_in_callback = true;
219 cyhal_i2c_address_callback_t callback = (cyhal_i2c_address_callback_t) obj->addr_callback_data.callback;
220 cmd = callback(obj->addr_callback_data.callback_arg, addr_events, device_address);
221 obj->op_in_callback = false;
222 }
223 return (cy_en_scb_i2c_command_t)cmd;
224 }
225
_cyhal_i2c_pm_callback_instance(void * obj_ptr,cyhal_syspm_callback_state_t state,cy_en_syspm_callback_mode_t pdl_mode)226 static bool _cyhal_i2c_pm_callback_instance(void *obj_ptr, cyhal_syspm_callback_state_t state, cy_en_syspm_callback_mode_t pdl_mode)
227 {
228 cyhal_i2c_t *obj = (cyhal_i2c_t*)obj_ptr;
229 cy_stc_syspm_callback_params_t i2c_callback_params = {
230 .base = (void *) (obj->base),
231 .context = (void *) &(obj->context)
232 };
233 bool allow = true;
234
235 if ((CYHAL_SYSPM_CB_CPU_DEEPSLEEP == state) || (CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM == state))
236 allow = (CY_SYSPM_SUCCESS == Cy_SCB_I2C_DeepSleepCallback(&i2c_callback_params, pdl_mode));
237 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
238 else if (CYHAL_SYSPM_CB_SYSTEM_HIBERNATE == state)
239 allow = (CY_SYSPM_SUCCESS == Cy_SCB_I2C_HibernateCallback(&i2c_callback_params, pdl_mode));
240 #endif
241
242 return allow;
243 }
244
245
_cyhal_i2c_init_resources(cyhal_i2c_t * obj,cyhal_gpio_t sda,cyhal_gpio_t scl,const cyhal_clock_t * clk)246 static cy_rslt_t _cyhal_i2c_init_resources(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk)
247 {
248 /* Explicitly marked not allocated resources as invalid to prevent freeing them. */
249 obj->resource.type = CYHAL_RSC_INVALID;
250 obj->pin_scl = CYHAL_NC_PIN_VALUE;
251 obj->pin_sda = CYHAL_NC_PIN_VALUE;
252 obj->is_clock_owned = false;
253
254 // pins_blocks will contain bit representation of blocks, that are connected to specified pin
255 // 1 block - 1 bit, so, for example, pin_blocks = 0x00000006 means that certain pin
256 // can belong to next non-reserved blocks SCB2 and SCB1
257 uint32_t pins_blocks = _CYHAL_SCB_AVAILABLE_BLOCKS_MASK;
258 if (NC != sda)
259 {
260 pins_blocks &= _CYHAL_SCB_CHECK_AFFILIATION(sda, cyhal_pin_map_scb_i2c_sda);
261 }
262 if (NC != scl)
263 {
264 pins_blocks &= _CYHAL_SCB_CHECK_AFFILIATION(scl, cyhal_pin_map_scb_i2c_scl);
265 }
266
267 // One (or more) pin does not belong to any SCB instance or all corresponding SCB instances
268 // are reserved
269 if (0 == pins_blocks)
270 {
271 return CYHAL_I2C_RSLT_ERR_INVALID_PIN;
272 }
273
274 uint8_t found_block_idx = 0;
275 while(((pins_blocks >> found_block_idx) & 0x1) == 0)
276 {
277 found_block_idx++;
278 }
279
280 cyhal_resource_inst_t i2c_rsc = { CYHAL_RSC_SCB, found_block_idx, 0 };
281
282 /* Reserve the I2C */
283 const cyhal_resource_pin_mapping_t *sda_map = _CYHAL_SCB_FIND_MAP_BLOCK(sda, cyhal_pin_map_scb_i2c_sda, &i2c_rsc);
284 const cyhal_resource_pin_mapping_t *scl_map = _CYHAL_SCB_FIND_MAP_BLOCK(scl, cyhal_pin_map_scb_i2c_scl, &i2c_rsc);
285 uint8_t scb_arr_index = 0;
286
287 if ((NULL == sda_map) || (NULL == scl_map) || !_cyhal_utils_map_resources_equal(sda_map, scl_map))
288 {
289 return CYHAL_I2C_RSLT_ERR_INVALID_PIN;
290 }
291
292
293 cyhal_resource_inst_t rsc_to_reserve = { CYHAL_RSC_SCB, _cyhal_scb_get_block_index(found_block_idx), 0 };
294 cy_rslt_t result = cyhal_hwmgr_reserve(&rsc_to_reserve);
295
296 if (result == CY_RSLT_SUCCESS)
297 {
298 scb_arr_index = _cyhal_scb_get_block_index(i2c_rsc.block_num);
299 obj->base = _CYHAL_SCB_BASE_ADDRESSES[scb_arr_index];
300 obj->resource = i2c_rsc;
301
302 result = _cyhal_utils_reserve_and_connect(sda_map, (uint8_t)CYHAL_PIN_MAP_DRIVE_MODE_SCB_I2C_SDA);
303 if (result == CY_RSLT_SUCCESS)
304 obj->pin_sda = sda;
305 }
306
307 if (result == CY_RSLT_SUCCESS)
308 {
309 result = _cyhal_utils_reserve_and_connect(scl_map, (uint8_t)CYHAL_PIN_MAP_DRIVE_MODE_SCB_I2C_SCL);
310 if (result == CY_RSLT_SUCCESS)
311 obj->pin_scl = scl;
312 }
313
314 if (result == CY_RSLT_SUCCESS)
315 {
316 if (clk == NULL)
317 {
318 result = _cyhal_utils_allocate_clock(&(obj->clock), &(obj->resource), CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT, true);
319 obj->is_clock_owned = (result == CY_RSLT_SUCCESS);
320 }
321 else
322 {
323 obj->clock = *clk;
324 }
325 }
326
327 if (result == CY_RSLT_SUCCESS)
328 {
329 uint32_t dataRate = _cyhal_i2c_set_peri_divider((void *)obj, true, _CYHAL_I2C_MASTER_DEFAULT_FREQ, false);
330 if (dataRate == 0)
331 {
332 /* Can not reach desired data rate */
333 result = CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR;
334 }
335 }
336
337 return result;
338 }
339
_cyhal_i2c_init_hw(cyhal_i2c_t * obj,const cy_stc_scb_i2c_config_t * pdl_cfg)340 static cy_rslt_t _cyhal_i2c_init_hw(cyhal_i2c_t *obj, const cy_stc_scb_i2c_config_t *pdl_cfg)
341 {
342 CY_ASSERT(NULL != obj->base);
343
344 /* Initial value for async operations */
345 obj->pending = _CYHAL_I2C_PENDING_NONE;
346 /* Initial value for read/write operations in callback */
347 obj->op_in_callback = false;
348
349 obj->rx_slave_buff = _cyhal_i2c_buff_info_default;
350 obj->tx_slave_buff = _cyhal_i2c_buff_info_default;
351
352 /* Configure I2C to operate */
353 cy_rslt_t result = (cy_rslt_t)Cy_SCB_I2C_Init(obj->base, pdl_cfg, &(obj->context));
354 uint8_t scb_arr_index = _cyhal_scb_get_block_index(obj->resource.block_num);
355
356 if (result == CY_RSLT_SUCCESS)
357 {
358 _cyhal_scb_update_instance_data(obj->resource.block_num, (void*)obj, &_cyhal_i2c_pm_callback_instance);
359 /* Enable I2C to operate */
360 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
361 Cy_SCB_I2C_Enable(obj->base);
362 #elif defined(COMPONENT_CAT2)
363 Cy_SCB_I2C_Enable(obj->base, &(obj->context));
364 #endif
365 obj->callback_data.callback = NULL;
366 obj->callback_data.callback_arg = NULL;
367 obj->addr_callback_data.callback = NULL;
368 obj->addr_callback_data.callback_arg = NULL;
369 obj->irq_cause = CYHAL_I2C_EVENT_NONE;
370 obj->addr_irq_cause = CYHAL_I2C_ADDR_EVENT_NONE;
371
372 #if defined (COMPONENT_CAT5)
373 Cy_SCB_RegisterInterruptCallback(obj->base, _cyhal_irq_cb[_CYHAL_SCB_IRQ_N[scb_arr_index]]);
374 Cy_SCB_EnableInterrupt(obj->base);
375 #endif
376
377 _cyhal_irq_register(_CYHAL_SCB_IRQ_N[scb_arr_index], CYHAL_ISR_PRIORITY_DEFAULT, (cy_israddress)_cyhal_i2c_irq_handler);
378 _cyhal_irq_enable(_CYHAL_SCB_IRQ_N[scb_arr_index]);
379 }
380
381 return result;
382 }
383
_cyhal_i2c_slave_status(cyhal_i2c_t * obj)384 __STATIC_INLINE uint32_t _cyhal_i2c_slave_status(cyhal_i2c_t *obj)
385 {
386 return Cy_SCB_I2C_SlaveGetStatus(obj->base, &obj->context);
387 }
388
_cyhal_i2c_slave_clear_write_status(cyhal_i2c_t * obj)389 __STATIC_INLINE void _cyhal_i2c_slave_clear_write_status(cyhal_i2c_t *obj)
390 {
391 (void)Cy_SCB_I2C_SlaveClearWriteStatus(obj->base, &obj->context);
392 }
393
_cyhal_i2c_slave_clear_read_status(cyhal_i2c_t * obj)394 __STATIC_INLINE void _cyhal_i2c_slave_clear_read_status(cyhal_i2c_t *obj)
395 {
396 (void)Cy_SCB_I2C_SlaveClearReadStatus(obj->base, &obj->context);
397 }
398
399 /* Wait for I2C slave status for some time (timeout > 0) or no wait (timeout == 0).
400 * The function returns CYHAL_I2C_RSLT_WARN_TIMEOUT in case timeout reached, otherwise - CY_RSLT_SUCCESS
401 * NOTE: When the read/write operation was called in a I2C callback function timeout is ignored
402 */
_cyhal_i2c_slave_wait_for_status(cyhal_i2c_t * obj,uint32_t i2c_status,uint32_t timeout)403 static cy_rslt_t _cyhal_i2c_slave_wait_for_status(cyhal_i2c_t *obj, uint32_t i2c_status, uint32_t timeout)
404 {
405 cy_rslt_t result = CY_RSLT_SUCCESS;
406 uint32_t timeout_us = _CYHAL_UTILS_US_PER_MS;
407
408 if (!(obj->op_in_callback) && timeout > 0)
409 {
410 while (0U == (_cyhal_i2c_slave_status(obj) & i2c_status) && timeout > 0)
411 {
412 if (timeout_us > 0)
413 {
414 cyhal_system_delay_us(_CYHAL_UTILS_ONE_TIME_UNIT);
415 --timeout_us;
416 }
417 else
418 {
419 timeout_us = _CYHAL_UTILS_US_PER_MS;
420 --timeout;
421 }
422 }
423 result = (timeout > 0) ? CY_RSLT_SUCCESS : CYHAL_I2C_RSLT_WARN_TIMEOUT;
424 }
425 return result;
426 }
427
428 /* Start API implementing */
cyhal_i2c_init(cyhal_i2c_t * obj,cyhal_gpio_t sda,cyhal_gpio_t scl,const cyhal_clock_t * clk)429 cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk)
430 {
431 CY_ASSERT(NULL != obj);
432 obj->dc_configured = false;
433 memset(obj, 0, sizeof(cyhal_i2c_t));
434
435 cy_rslt_t result = _cyhal_i2c_init_resources(obj, sda, scl, clk);
436 if (CY_RSLT_SUCCESS == result)
437 {
438 result = _cyhal_i2c_init_hw(obj, &_cyhal_i2c_default_config);
439 }
440 if (CY_RSLT_SUCCESS != result)
441 {
442 cyhal_i2c_free(obj);
443 }
444 return result;
445 }
446
cyhal_i2c_init_cfg(cyhal_i2c_t * obj,const cyhal_i2c_configurator_t * cfg)447 cy_rslt_t cyhal_i2c_init_cfg(cyhal_i2c_t *obj, const cyhal_i2c_configurator_t *cfg)
448 {
449 CY_ASSERT(NULL != obj);
450 CY_ASSERT(NULL != cfg);
451 CY_ASSERT(NULL != cfg->config);
452
453 memset(obj, 0, sizeof(cyhal_i2c_t));
454
455 obj->dc_configured = true;
456 obj->resource = *cfg->resource;
457 obj->clock = *cfg->clock;
458 obj->is_clock_owned = false;
459
460 uint8_t scb_arr_index = _cyhal_scb_get_block_index(obj->resource.block_num);
461 obj->base = _CYHAL_SCB_BASE_ADDRESSES[scb_arr_index];
462
463 return _cyhal_i2c_init_hw(obj, cfg->config);
464 }
465
cyhal_i2c_free(cyhal_i2c_t * obj)466 void cyhal_i2c_free(cyhal_i2c_t *obj)
467 {
468 CY_ASSERT(NULL != obj);
469
470 if (NULL != obj->base)
471 {
472 Cy_SCB_I2C_Disable(obj->base, &obj->context);
473 Cy_SCB_I2C_DeInit(obj->base);
474 obj->base = NULL;
475 }
476
477 if (CYHAL_RSC_INVALID != obj->resource.type)
478 {
479 uint8_t scb_arr_index = _cyhal_scb_get_block_index(obj->resource.block_num);
480 _cyhal_scb_update_instance_data(obj->resource.block_num, NULL, NULL);
481 _cyhal_system_irq_t irqn = _CYHAL_SCB_IRQ_N[scb_arr_index];
482 _cyhal_irq_free(irqn);
483
484 if (!obj->dc_configured)
485 {
486 cyhal_resource_inst_t rsc_to_free = { CYHAL_RSC_SCB, _cyhal_scb_get_block_index(obj->resource.block_num), obj->resource.channel_num };
487 cyhal_hwmgr_free(&(rsc_to_free));
488 }
489
490 obj->resource.type = CYHAL_RSC_INVALID;
491 }
492
493 if (!obj->dc_configured)
494 {
495 _cyhal_utils_release_if_used(&(obj->pin_sda));
496 _cyhal_utils_release_if_used(&(obj->pin_scl));
497
498 if (obj->is_clock_owned)
499 {
500 cyhal_clock_free(&(obj->clock));
501 }
502 }
503 }
504
cyhal_i2c_configure(cyhal_i2c_t * obj,const cyhal_i2c_cfg_t * cfg)505 cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg)
506 {
507 CY_ASSERT(NULL != obj);
508 CY_ASSERT(NULL != cfg);
509
510 /* Prepare advanced configuration structure */
511 cyhal_i2c_adv_cfg_t adv_cfg = {
512 .basic_cfg = *cfg,
513 /* Fill advanced parameters by default values */
514 .address_mask = CYHAL_I2C_DEFAULT_ADDR_MASK,
515 .enable_address_callback = false,
516 };
517
518 return cyhal_i2c_configure_adv(obj, &adv_cfg);
519 }
520
cyhal_i2c_configure_adv(cyhal_i2c_t * obj,const cyhal_i2c_adv_cfg_t * cfg)521 cy_rslt_t cyhal_i2c_configure_adv(cyhal_i2c_t *obj, const cyhal_i2c_adv_cfg_t *cfg)
522 {
523 CY_ASSERT(NULL != obj);
524 CY_ASSERT(NULL != cfg);
525 CY_ASSERT(NULL != &cfg->basic_cfg);
526
527 (void) Cy_SCB_I2C_Disable(obj->base, &obj->context);
528
529 cy_stc_scb_i2c_config_t _config_structure = _cyhal_i2c_default_config;
530
531 _config_structure.i2cMode = (cfg->basic_cfg.is_slave)
532 ? CY_SCB_I2C_SLAVE
533 : CY_SCB_I2C_MASTER;
534
535 _config_structure.slaveAddress = (uint8_t)cfg->basic_cfg.address;
536
537 if (cfg->basic_cfg.is_slave)
538 {
539 _config_structure.acceptAddrInFifo = cfg->enable_address_callback;
540 _config_structure.ackGeneralAddr = cfg->enable_address_callback;
541 _config_structure.slaveAddressMask = cfg->address_mask;
542 }
543
544 cy_rslt_t result = (cy_rslt_t)Cy_SCB_I2C_Init(obj->base, &_config_structure, &(obj->context));
545 if (CY_RSLT_SUCCESS == result)
546 {
547 /* Set data rate */
548 uint32_t dataRate = _cyhal_i2c_set_peri_divider((void *)obj, true,
549 cfg->basic_cfg.frequencyhal_hz, cfg->basic_cfg.is_slave);
550 if (dataRate == 0)
551 {
552 /* Deinit SCB block */
553 Cy_SCB_I2C_DeInit(obj->base);
554 /* Can not reach desired data rate */
555 return CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR;
556 }
557
558 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
559 (void) Cy_SCB_I2C_Enable(obj->base);
560 #elif defined(COMPONENT_CAT2)
561 (void) Cy_SCB_I2C_Enable(obj->base, &(obj->context));
562 #endif
563 }
564 return result;
565 }
566
cyhal_i2c_master_write(cyhal_i2c_t * obj,uint16_t dev_addr,const uint8_t * data,uint16_t size,uint32_t timeout,bool send_stop)567 cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)
568 {
569 if (_cyhal_scb_pm_transition_pending())
570 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
571
572 cy_en_scb_i2c_status_t status = (obj->context.state == CY_SCB_I2C_IDLE)
573 ? Cy_SCB_I2C_MasterSendStart(obj->base, dev_addr, CY_SCB_I2C_WRITE_XFER, timeout, &obj->context)
574 : Cy_SCB_I2C_MasterSendReStart(obj->base, dev_addr, CY_SCB_I2C_WRITE_XFER, timeout, &obj->context);
575
576 if (status == CY_SCB_I2C_SUCCESS)
577 {
578 while (size > 0)
579 {
580 status = Cy_SCB_I2C_MasterWriteByte(obj->base, *data, timeout, &obj->context);
581 if (status != CY_SCB_I2C_SUCCESS)
582 {
583 break;
584 }
585 --size;
586 ++data;
587 }
588 }
589
590 if (send_stop)
591 {
592 /* SCB in I2C mode is very time sensitive. In practice we have to request STOP after */
593 /* each block, otherwise it may break the transmission */
594 Cy_SCB_I2C_MasterSendStop(obj->base, timeout, &obj->context);
595 }
596
597 return status;
598 }
599
cyhal_i2c_master_read(cyhal_i2c_t * obj,uint16_t dev_addr,uint8_t * data,uint16_t size,uint32_t timeout,bool send_stop)600 cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)
601 {
602 if (_cyhal_scb_pm_transition_pending())
603 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
604
605 cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK;
606
607 /* Start transaction, send dev_addr */
608 cy_en_scb_i2c_status_t status = obj->context.state == CY_SCB_I2C_IDLE
609 ? Cy_SCB_I2C_MasterSendStart(obj->base, dev_addr, CY_SCB_I2C_READ_XFER, timeout, &obj->context)
610 : Cy_SCB_I2C_MasterSendReStart(obj->base, dev_addr, CY_SCB_I2C_READ_XFER, timeout, &obj->context);
611
612 if (status == CY_SCB_I2C_SUCCESS)
613 {
614 while (size > 0) {
615 if (size == 1)
616 {
617 ack = CY_SCB_I2C_NAK;
618 }
619 status = Cy_SCB_I2C_MasterReadByte(obj->base, ack, (uint8_t *)data, timeout, &obj->context);
620 if (status != CY_SCB_I2C_SUCCESS)
621 {
622 break;
623 }
624 --size;
625 ++data;
626 }
627 }
628
629 if (send_stop)
630 {
631 /* SCB in I2C mode is very time sensitive. In practice we have to request STOP after */
632 /* each block, otherwise it may break the transmission */
633 Cy_SCB_I2C_MasterSendStop(obj->base, timeout, &obj->context);
634 }
635 return status;
636 }
637
cyhal_i2c_slave_abort_read(cyhal_i2c_t * obj)638 cy_rslt_t cyhal_i2c_slave_abort_read(cyhal_i2c_t *obj)
639 {
640 cy_rslt_t result = CY_RSLT_SUCCESS;
641
642 if (obj->context.state == CY_SCB_I2C_IDLE)
643 {
644 Cy_SCB_I2C_SlaveAbortRead(obj->base, &obj->context);
645 }
646 else
647 {
648 result = CYHAL_I2C_RSLT_WARN_DEVICE_BUSY;
649 }
650 return result;
651 }
652
cyhal_i2c_slave_config_write_buffer(cyhal_i2c_t * obj,const uint8_t * data,uint16_t size)653 cy_rslt_t cyhal_i2c_slave_config_write_buffer(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size)
654 {
655 cy_rslt_t result = CYHAL_I2C_RSLT_ERR_BAD_ARGUMENT;
656 if (size > 0 && data != NULL)
657 {
658 if (obj->context.state == CY_SCB_I2C_IDLE)
659 {
660 Cy_SCB_I2C_SlaveConfigWriteBuf(obj->base, (uint8_t *)data, size, &obj->context);
661 obj->rx_slave_buff.addr.u8 = (uint8_t *)data;
662 obj->rx_slave_buff.size = size;
663 result = CY_RSLT_SUCCESS;
664 }
665 else
666 {
667 result = CYHAL_I2C_RSLT_WARN_DEVICE_BUSY;
668 }
669 }
670 return result;
671 }
672
cyhal_i2c_slave_config_read_buffer(cyhal_i2c_t * obj,uint8_t * data,uint16_t size)673 cy_rslt_t cyhal_i2c_slave_config_read_buffer(cyhal_i2c_t *obj, uint8_t *data, uint16_t size)
674 {
675 cy_rslt_t result = CYHAL_I2C_RSLT_ERR_BAD_ARGUMENT;
676 if (size > 0 && data != NULL)
677 {
678 if (obj->context.state == CY_SCB_I2C_IDLE)
679 {
680 Cy_SCB_I2C_SlaveConfigReadBuf(obj->base, (uint8_t *)data, size, &obj->context);
681 obj->tx_slave_buff.addr.u8 = data;
682 obj->tx_slave_buff.size = size;
683 result = CY_RSLT_SUCCESS;
684 }
685 else
686 {
687 result = CYHAL_I2C_RSLT_WARN_DEVICE_BUSY;
688 }
689 }
690 return result;
691 }
692
cyhal_i2c_master_mem_write(cyhal_i2c_t * obj,uint16_t address,uint16_t mem_addr,uint16_t mem_addr_size,const uint8_t * data,uint16_t size,uint32_t timeout)693 cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, const uint8_t *data, uint16_t size, uint32_t timeout)
694 {
695 if (_cyhal_scb_pm_transition_pending())
696 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
697
698 uint8_t mem_addr_buf[2];
699 if (mem_addr_size == 1)
700 {
701 mem_addr_buf[0] = (uint8_t)mem_addr;
702 }
703 else if (mem_addr_size == 2)
704 {
705 mem_addr_buf[0] = (uint8_t)(mem_addr >> 8);
706 mem_addr_buf[1] = (uint8_t)mem_addr;
707 }
708 else
709 {
710 return CYHAL_I2C_RSLT_ERR_INVALID_ADDRESS_SIZE;
711 }
712
713 cy_rslt_t status = cyhal_i2c_master_write(obj, address, mem_addr_buf, mem_addr_size, timeout, false);
714
715 if (status == CY_RSLT_SUCCESS)
716 {
717 while (size > 0)
718 {
719 status = Cy_SCB_I2C_MasterWriteByte(obj->base, *data, timeout, &obj->context);
720 if (status != CY_SCB_I2C_SUCCESS)
721 {
722 break;
723 }
724 --size;
725 ++data;
726 }
727 /* SCB in I2C mode is very time sensitive. In practice we have to request STOP after */
728 /* each block, otherwise it may break the transmission */
729 Cy_SCB_I2C_MasterSendStop(obj->base, timeout, &obj->context);
730 }
731 return status;
732 }
733
cyhal_i2c_master_mem_read(cyhal_i2c_t * obj,uint16_t address,uint16_t mem_addr,uint16_t mem_addr_size,uint8_t * data,uint16_t size,uint32_t timeout)734 cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout)
735 {
736 if (_cyhal_scb_pm_transition_pending())
737 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
738
739 uint8_t mem_addr_buf[2];
740 if (mem_addr_size == 1)
741 {
742 mem_addr_buf[0] = (uint8_t)mem_addr;
743 }
744 else if (mem_addr_size == 2)
745 {
746 mem_addr_buf[0] = (uint8_t)(mem_addr >> 8);
747 mem_addr_buf[1] = (uint8_t)mem_addr;
748 }
749 else
750 {
751 return CYHAL_I2C_RSLT_ERR_INVALID_ADDRESS_SIZE;
752 }
753
754 cy_rslt_t status = cyhal_i2c_master_write(obj, address, mem_addr_buf, mem_addr_size, timeout, false);
755 if (status == CY_RSLT_SUCCESS)
756 {
757 status = cyhal_i2c_master_read(obj, address, data, size, timeout, true);
758 }
759 return status;
760 }
761
cyhal_i2c_slave_read(cyhal_i2c_t * obj,uint8_t * dst_buff,uint16_t * size,uint32_t timeout)762 cy_rslt_t cyhal_i2c_slave_read(cyhal_i2c_t *obj, uint8_t *dst_buff, uint16_t *size, uint32_t timeout)
763 {
764 cy_rslt_t status = CYHAL_I2C_RSLT_ERR_BAD_ARGUMENT;
765
766 if (obj->rx_slave_buff.addr.u8 == NULL)
767 {
768 status = CYHAL_I2C_RSLT_ERR_BUFFERS_NULL_PTR;
769 }
770 else if ((dst_buff != NULL) && (size != NULL))
771 {
772 /* Wait until the master completes writing */
773 status = _cyhal_i2c_slave_wait_for_status(obj, CY_SCB_I2C_SLAVE_WR_CMPLT, timeout);
774
775 if (CY_RSLT_SUCCESS == status)
776 {
777 *size = _CYHAL_SCB_BYTES_TO_COPY(cyhal_i2c_slave_readable(obj), *size);
778 /* Check if the destination buffer is not a I2C RX buffer. */
779 if (obj->rx_slave_buff.addr.u8 != dst_buff)
780 {
781 /* Copy command into the destination buffer */
782 (void) memcpy((void *)dst_buff, (const void *)obj->rx_slave_buff.addr.u8, *size);
783 }
784
785 /* Wait for device set the state to IDLE */
786 while (obj->context.state != CY_SCB_I2C_IDLE && !(obj->op_in_callback))
787 {
788 /* I2C PDL driver guarantee the slave will be in IDLE state
789 after the end of a transaction */
790 }
791
792 _cyhal_i2c_slave_clear_write_status(obj);
793 }
794 }
795 return status;
796 }
797
cyhal_i2c_slave_write(cyhal_i2c_t * obj,const uint8_t * src_buff,uint16_t * size,uint32_t timeout)798 cy_rslt_t cyhal_i2c_slave_write(cyhal_i2c_t *obj, const uint8_t *src_buff, uint16_t *size, uint32_t timeout)
799 {
800 cy_rslt_t status = CYHAL_I2C_RSLT_ERR_BAD_ARGUMENT;
801
802 if (obj->tx_slave_buff.addr.u8 == NULL)
803 {
804 status = CYHAL_I2C_RSLT_ERR_BUFFERS_NULL_PTR;
805 }
806 else if ((src_buff != NULL) && (size != NULL))
807 {
808 /* Wait for completion of a previous Master read transaction */
809 while (obj->context.state != CY_SCB_I2C_IDLE && !(obj->op_in_callback))
810 {
811 /* I2C PDL driver guarantee the slave will be in IDLE state
812 after the end of a previous transaction */
813 }
814
815 if (obj->context.state == CY_SCB_I2C_IDLE)
816 {
817 *size = _CYHAL_SCB_BYTES_TO_COPY(obj->tx_slave_buff.size, *size);
818 /* Check if the source buffer is not a I2C TX buffer. */
819 if (obj->tx_slave_buff.addr.u8 != src_buff)
820 {
821 /* Copy command into the TX buffer */
822 (void) memcpy((void *)obj->tx_slave_buff.addr.u8, (const void *)src_buff, *size);
823 }
824
825 /* Wait until the master completes reading */
826 status = _cyhal_i2c_slave_wait_for_status(obj, CY_SCB_I2C_SLAVE_RD_CMPLT, timeout);
827 if (CY_RSLT_SUCCESS == status)
828 {
829 _cyhal_i2c_slave_clear_read_status(obj);
830 }
831 }
832 }
833 return status;
834 }
835
cyhal_i2c_master_transfer_async(cyhal_i2c_t * obj,uint16_t address,const void * tx,size_t tx_size,void * rx,size_t rx_size)836 cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, const void *tx, size_t tx_size, void *rx, size_t rx_size)
837 {
838 if (_cyhal_scb_pm_transition_pending())
839 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
840
841 obj->rx_config.slaveAddress = (uint8_t)address;
842 obj->tx_config.slaveAddress = (uint8_t)address;
843
844 obj->rx_config.buffer = rx;
845 obj->rx_config.bufferSize = rx_size;
846
847 obj->tx_config.buffer = (void *)tx;
848 obj->tx_config.bufferSize = tx_size;
849
850 if (!obj->pending)
851 {
852 /* Validate input data and do appropriate action */
853 if (tx_size)
854 {
855 obj->pending = (rx_size)
856 ? _CYHAL_I2C_PENDING_TX_RX
857 : _CYHAL_I2C_PENDING_TX;
858 Cy_SCB_I2C_MasterWrite(obj->base, &obj->tx_config, &obj->context);
859 /* Receive covered by interrupt handler - _cyhal_i2c_irq_handler() */
860 }
861 else if (rx_size)
862 {
863 obj->pending = _CYHAL_I2C_PENDING_RX;
864 Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
865 }
866 else
867 {
868 return CYHAL_I2C_RSLT_ERR_TX_RX_BUFFERS_ARE_EMPTY;
869 }
870 }
871 else
872 {
873 return CYHAL_I2C_RSLT_ERR_PREVIOUS_ASYNCH_PENDING;
874 }
875 return CY_RSLT_SUCCESS;
876 }
877
cyhal_i2c_abort_async(cyhal_i2c_t * obj)878 cy_rslt_t cyhal_i2c_abort_async(cyhal_i2c_t *obj)
879 {
880 uint16_t timeout_us = 10000;
881 if (obj->pending != _CYHAL_I2C_PENDING_NONE)
882 {
883 if (obj->pending == _CYHAL_I2C_PENDING_RX)
884 {
885 Cy_SCB_I2C_MasterAbortRead(obj->base, &obj->context);
886 }
887 else
888 {
889 Cy_SCB_I2C_MasterAbortWrite(obj->base, &obj->context);
890 }
891 /* After abort, next I2C operation can be initiated only after CY_SCB_I2C_MASTER_BUSY is cleared,
892 * so waiting for that event to occur. */
893 while ((CY_SCB_I2C_MASTER_BUSY & obj->context.masterStatus) && (timeout_us != 0))
894 {
895 cyhal_system_delay_us(1);
896 timeout_us--;
897 }
898 if (0 == timeout_us)
899 {
900 return CYHAL_I2C_RSLT_ERR_ABORT_ASYNC_TIMEOUT;
901 }
902 obj->pending = _CYHAL_I2C_PENDING_NONE;
903 }
904 return CY_RSLT_SUCCESS;
905 }
906
cyhal_i2c_register_callback(cyhal_i2c_t * obj,cyhal_i2c_event_callback_t callback,void * callback_arg)907 void cyhal_i2c_register_callback(cyhal_i2c_t *obj, cyhal_i2c_event_callback_t callback, void *callback_arg)
908 {
909 uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
910 obj->callback_data.callback = (cy_israddress) callback;
911 obj->callback_data.callback_arg = callback_arg;
912 cyhal_system_critical_section_exit(savedIntrStatus);
913 Cy_SCB_I2C_RegisterEventCallback(obj->base, _cyhal_i2c_cb_wrapper, &(obj->context));
914
915 obj->irq_cause = CYHAL_I2C_EVENT_NONE;
916 }
917
cyhal_i2c_register_address_callback(cyhal_i2c_t * obj,cyhal_i2c_address_callback_t callback,void * callback_arg)918 void cyhal_i2c_register_address_callback(cyhal_i2c_t *obj, cyhal_i2c_address_callback_t callback, void *callback_arg)
919 {
920 uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
921 obj->addr_callback_data.callback = (cy_israddress) callback;
922 obj->addr_callback_data.callback_arg = callback_arg;
923 cyhal_system_critical_section_exit(savedIntrStatus);
924 Cy_SCB_I2C_RegisterAddrCallback(obj->base, _cyhal_i2c_cb_addr_wrapper, &(obj->context));
925
926 obj->addr_irq_cause = CYHAL_I2C_ADDR_EVENT_NONE;
927 }
928
cyhal_i2c_enable_event(cyhal_i2c_t * obj,cyhal_i2c_event_t event,uint8_t intr_priority,bool enable)929 void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intr_priority, bool enable)
930 {
931 uint8_t scb_arr_index = _cyhal_scb_get_block_index(obj->resource.block_num);
932 if (enable)
933 {
934 obj->irq_cause |= event;
935 }
936 else
937 {
938 obj->irq_cause &= ~event;
939 }
940
941 _cyhal_system_irq_t irqn = _CYHAL_SCB_IRQ_N[scb_arr_index];
942 _cyhal_irq_set_priority(irqn, intr_priority);
943 }
944
cyhal_i2c_enable_address_event(cyhal_i2c_t * obj,cyhal_i2c_addr_event_t event,uint8_t intr_priority,bool enable)945 void cyhal_i2c_enable_address_event(cyhal_i2c_t *obj, cyhal_i2c_addr_event_t event, uint8_t intr_priority, bool enable)
946 {
947 uint8_t scb_arr_index = _cyhal_scb_get_block_index(obj->resource.block_num);
948 if (enable)
949 {
950 obj->addr_irq_cause |= event;
951 }
952 else
953 {
954 obj->addr_irq_cause &= ~event;
955 }
956
957 _cyhal_system_irq_t irqn = _CYHAL_SCB_IRQ_N[scb_arr_index];
958 _cyhal_irq_set_priority(irqn, intr_priority);
959 }
960
cyhal_i2c_set_fifo_level(cyhal_i2c_t * obj,cyhal_i2c_fifo_type_t type,uint16_t level)961 cy_rslt_t cyhal_i2c_set_fifo_level(cyhal_i2c_t *obj, cyhal_i2c_fifo_type_t type, uint16_t level)
962 {
963 return _cyhal_scb_set_fifo_level(obj->base, (cyhal_scb_fifo_type_t)type, level);
964 }
965
cyhal_i2c_enable_output(cyhal_i2c_t * obj,cyhal_i2c_output_t output,cyhal_source_t * source)966 cy_rslt_t cyhal_i2c_enable_output(cyhal_i2c_t *obj, cyhal_i2c_output_t output, cyhal_source_t *source)
967 {
968 return _cyhal_scb_enable_output(obj->resource, (cyhal_scb_output_t)output, source);
969 }
970
cyhal_i2c_disable_output(cyhal_i2c_t * obj,cyhal_i2c_output_t output)971 cy_rslt_t cyhal_i2c_disable_output(cyhal_i2c_t *obj, cyhal_i2c_output_t output)
972 {
973 CY_UNUSED_PARAMETER(obj);
974 return _cyhal_scb_disable_output((cyhal_scb_output_t)output);
975 }
976
cyhal_i2c_slave_readable(cyhal_i2c_t * obj)977 uint32_t cyhal_i2c_slave_readable(cyhal_i2c_t *obj)
978 {
979 return Cy_SCB_I2C_SlaveGetWriteTransferCount(obj->base, &obj->context);
980 }
981
cyhal_i2c_slave_writable(cyhal_i2c_t * obj)982 uint32_t cyhal_i2c_slave_writable(cyhal_i2c_t *obj)
983 {
984 return (obj->tx_slave_buff.size - Cy_SCB_I2C_SlaveGetReadTransferCount(obj->base, &obj->context));
985 }
986
cyhal_i2c_clear(cyhal_i2c_t * obj)987 cy_rslt_t cyhal_i2c_clear(cyhal_i2c_t *obj)
988 {
989 Cy_SCB_ClearRxFifo(obj->base);
990 Cy_SCB_ClearTxFifo(obj->base);
991
992 _cyhal_i2c_slave_clear_write_status(obj);
993 _cyhal_i2c_slave_clear_read_status(obj);
994 return CY_RSLT_SUCCESS;
995 }
996
997 #if defined(__cplusplus)
998 }
999 #endif
1000
1001 #endif /* CYHAL_DRIVER_AVAILABLE_I2C */
1002