1 /***************************************************************************//**
2 * \file cyhal_gpio.c
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Infineon GPIO. 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 "cyhal_gpio_impl.h"
29 #include "cyhal_interconnect.h"
30 #include "cyhal_system.h"
31 #include "cyhal_hwmgr.h"
32 #include "cyhal_irq_impl.h"
33
34 #if (CYHAL_DRIVER_AVAILABLE_GPIO)
35
36 #if defined(__cplusplus)
37 extern "C" {
38 #endif /* __cplusplus */
39
40
41 /*******************************************************************************
42 * Internal
43 *******************************************************************************/
44 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
45 #define _CYHAL_GPIO_DIRECTION_OUTPUT_MASK (0x07UL) /**< Mask to disable the input buffer */
46 #elif defined(COMPONENT_CAT2)
47 #define _CYHAL_GPIO_DIRECTION_OUTPUT_MASK (0x08UL) /**< Mask to disable the input buffer */
48 #endif
49
50 /* Callback array for GPIO interrupts */
51 static bool _cyhal_gpio_arrays_initialized = false;
52 CY_NOINIT static cyhal_gpio_callback_data_t* _cyhal_gpio_callbacks[IOSS_GPIO_GPIO_PORT_NR];
53 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
54 #define _CYHAL_GPIO_SOURCE_SIGNAL_COUNT (sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t))
55 CY_NOINIT static cyhal_source_t _cyhal_gpio_source_signals[_CYHAL_GPIO_SOURCE_SIGNAL_COUNT];
56 #endif
57
58 #if defined(CY_DEVICE_PMG1S3)
59 /* PMG1-S3: Work-around as device does not support any GPIO port specific interrupts. */
60 #define ioss_interrupts_gpio_0_IRQn (ioss_interrupt_gpio_IRQn)
61 #endif
62
63 /*******************************************************************************
64 * Internal Interrupt Service Routine
65 *******************************************************************************/
66
_cyhal_gpio_irq_handler(void)67 static void _cyhal_gpio_irq_handler(void)
68 {
69 _cyhal_system_irq_t irqn = _cyhal_irq_get_active();
70 #if defined(COMPONENT_CAT1D)
71 uint32_t port;
72 if(irqn >= ioss_interrupts_gpio_0_IRQn && irqn < ioss_interrupts_gpio_2_IRQn)
73 {
74 port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn);
75 }
76 else if(irqn >= ioss_interrupts_gpio_2_IRQn && irqn < ioss_interrupts_gpio_5_IRQn)
77 {
78 port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn + 1);
79 }
80 else if(irqn >= ioss_interrupts_gpio_5_IRQn && irqn <= ioss_interrupts_gpio_21_IRQn)
81 {
82 port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn + 2);
83 }
84 else
85 {
86 port = 0u;
87 CY_ASSERT(false); /* Unknown port */
88 }
89 #elif defined(COMPONENT_CAT1C)
90 #if defined(CY_DEVICE_TVIIBH4M) || defined(CY_DEVICE_TVIIBH8M)
91 /* Port 0-23 and 28-32 (inclusive) are DeepSleep capable. Port 24-27 and 33-34
92 * (inclusive) are active mode only. The interrupt numbers are grouped by power
93 * domain which means the numbers are non-contiguous - and die specific */
94 uint32_t port;
95 if(irqn <= ioss_interrupts_gpio_dpslp_23_IRQn)
96 {
97 port = (uint32_t)(irqn - ioss_interrupts_gpio_dpslp_0_IRQn);
98 }
99 else if((irqn >= ioss_interrupts_gpio_act_24_IRQn) && (irqn <= ioss_interrupts_gpio_act_27_IRQn))
100 {
101 port = 24u + (uint32_t)(irqn - ioss_interrupts_gpio_act_24_IRQn);
102 }
103 else if((irqn >= ioss_interrupts_gpio_dpslp_28_IRQn) && (irqn <= ioss_interrupts_gpio_dpslp_32_IRQn))
104 {
105 port = 28u + (uint32_t)(irqn - ioss_interrupts_gpio_dpslp_28_IRQn);
106 }
107 #if defined(CY_DEVICE_TVIIBH8M) /* Ports 33 and 34 don't exist on the 4M part */
108 else if((irqn >= ioss_interrupts_gpio_act_33_IRQn) && (irqn <= ioss_interrupts_gpio_act_34_IRQn))
109 {
110 port = 33u + (uint32_t)(irqn - ioss_interrupts_gpio_act_33_IRQn);
111 }
112 #endif /* defined(CY_DEVICE_TVIIBH8M) */
113 else
114 {
115 port = 0u;
116 CY_ASSERT(false); /* Unknown port */
117 }
118 #else
119 #error "Unknown base die"
120 #endif /* defined(CY_DEVICE_TVIIBH4M) || defined(CY_DEVICE_TVIIBH8M) */
121
122 #else /* other components */
123 uint32_t port = (uint32_t)(irqn - ioss_interrupts_gpio_0_IRQn);
124 #endif /* defined(COMPONENT_CAT1D) */
125 uint32_t intr_cause = 1 << port;
126 #if defined(COMPONENT_CAT2)
127 if (irqn == ioss_interrupt_gpio_IRQn)
128 {
129 intr_cause = Cy_GPIO_GetInterruptCause();
130 }
131 #endif
132
133 while(intr_cause != 0)
134 {
135 uint32_t curr_port = (uint32_t) (31U - __CLZ(intr_cause));
136 GPIO_PRT_Type *portAddr = Cy_GPIO_PortToAddr(curr_port);
137 cyhal_gpio_callback_data_t* cb_data = _cyhal_gpio_callbacks[curr_port];
138 while (NULL != cb_data)
139 {
140 uint8_t pin = CYHAL_GET_PIN(cb_data->pin);
141 /* Each supported architecture much have a way to check the interrupt status of a pin on a port. */
142 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
143 if (Cy_GPIO_GetInterruptStatusMasked(portAddr, pin))
144 #elif defined(COMPONENT_CAT2)
145 if (Cy_GPIO_GetInterruptStatus(portAddr, pin))
146 #else
147 #error "Unsupported architecture"
148 #endif
149 {
150 /* Call registered callbacks here */
151 cyhal_gpio_event_t event, edge = (cyhal_gpio_event_t)Cy_GPIO_GetInterruptEdge(portAddr, pin);
152 switch (edge)
153 {
154 case CYHAL_GPIO_IRQ_RISE:
155 case CYHAL_GPIO_IRQ_FALL:
156 event = edge;
157 break;
158 default:
159 event = (Cy_GPIO_Read(portAddr, pin) != 0) ? CYHAL_GPIO_IRQ_RISE : CYHAL_GPIO_IRQ_FALL;
160 break;
161 }
162 cb_data->callback(cb_data->callback_arg, event);
163 }
164
165 cb_data = cb_data->next;
166 }
167 // Since the HAL has taken over the interrupt, make sure we clear any triggers to avoid an
168 // infinite loop.
169 for (uint8_t i = 0; i < CY_GPIO_PINS_MAX; i++)
170 {
171 Cy_GPIO_ClearInterrupt(portAddr, i);
172 }
173 intr_cause &= ~(1 << curr_port);
174 }
175 }
176
_cyhal_gpio_convert_drive_mode(cyhal_gpio_drive_mode_t drive_mode,cyhal_gpio_direction_t direction)177 static uint32_t _cyhal_gpio_convert_drive_mode(cyhal_gpio_drive_mode_t drive_mode, cyhal_gpio_direction_t direction)
178 {
179 uint32_t drvMode;
180 switch (drive_mode)
181 {
182 /* For DRIVE_NONE and DRIVE_ANALOG: Return immediately so drvMode is
183 * not modified after switch statement based on direction as direction
184 * does not make sense for input only drive modes */
185 case CYHAL_GPIO_DRIVE_NONE:
186 drvMode = CY_GPIO_DM_HIGHZ;
187 return drvMode;
188 case CYHAL_GPIO_DRIVE_ANALOG:
189 drvMode = CY_GPIO_DM_ANALOG;
190 return drvMode;
191 case CYHAL_GPIO_DRIVE_PULLUP:
192 drvMode = CY_GPIO_DM_PULLUP;
193 break;
194 case CYHAL_GPIO_DRIVE_PULLDOWN:
195 drvMode = CY_GPIO_DM_PULLDOWN;
196 break;
197 case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW:
198 drvMode = CY_GPIO_DM_OD_DRIVESLOW;
199 break;
200 case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH:
201 drvMode = CY_GPIO_DM_OD_DRIVESHIGH;
202 break;
203 case CYHAL_GPIO_DRIVE_STRONG:
204 drvMode = CY_GPIO_DM_STRONG;
205 break;
206 case CYHAL_GPIO_DRIVE_PULLUPDOWN:
207 drvMode = CY_GPIO_DM_PULLUP_DOWN;
208 break;
209 case CYHAL_GPIO_DRIVE_PULL_NONE:
210 if ((direction == CYHAL_GPIO_DIR_OUTPUT) || (direction == CYHAL_GPIO_DIR_BIDIRECTIONAL))
211 {
212 drvMode = CY_GPIO_DM_STRONG;
213 }
214 else
215 {
216 drvMode = CY_GPIO_DM_HIGHZ;
217 }
218 break;
219 default:
220 CY_ASSERT(false);
221 drvMode = CY_GPIO_DM_HIGHZ;
222 }
223
224 if (direction == CYHAL_GPIO_DIR_OUTPUT)
225 {
226 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
227 drvMode &= _CYHAL_GPIO_DIRECTION_OUTPUT_MASK;
228 #elif defined(COMPONENT_CAT2)
229 drvMode |= _CYHAL_GPIO_DIRECTION_OUTPUT_MASK;
230 #endif
231 }
232 return drvMode;
233 }
234
235 /*******************************************************************************
236 * HAL Implementation
237 *******************************************************************************/
238
cyhal_gpio_init(cyhal_gpio_t pin,cyhal_gpio_direction_t direction,cyhal_gpio_drive_mode_t drive_mode,bool init_val)239 cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode, bool init_val)
240 {
241 if (!_cyhal_gpio_arrays_initialized)
242 {
243 for (uint8_t i = 0; i < IOSS_GPIO_GPIO_PORT_NR; i++)
244 {
245 _cyhal_gpio_callbacks[i] = NULL;
246 }
247 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
248 for (uint8_t i = 0; i < _CYHAL_GPIO_SOURCE_SIGNAL_COUNT; i++)
249 {
250 _cyhal_gpio_source_signals[i] = CYHAL_TRIGGER_CPUSS_ZERO;
251 }
252 #endif
253 _cyhal_gpio_arrays_initialized = true;
254 }
255
256 /* Mbed creates GPIOs for pins that are dedicated to other peripherals in some cases. */
257 #ifndef __MBED__
258 cyhal_resource_inst_t pinRsc = _cyhal_utils_get_gpio_resource(pin);
259 cy_rslt_t status = cyhal_hwmgr_reserve(&pinRsc);
260 #else
261 cy_rslt_t status = CY_RSLT_SUCCESS;
262 #endif
263
264 if (status == CY_RSLT_SUCCESS)
265 {
266 uint32_t pdl_drive_mode = _cyhal_gpio_convert_drive_mode(drive_mode, direction);
267 Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdl_drive_mode, init_val, HSIOM_SEL_GPIO);
268 }
269
270 return status;
271 }
272
cyhal_gpio_free(cyhal_gpio_t pin)273 void cyhal_gpio_free(cyhal_gpio_t pin)
274 {
275 if(_cyhal_gpio_arrays_initialized)
276 {
277 if (pin != CYHAL_NC_PIN_VALUE)
278 {
279 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
280 Cy_GPIO_SetInterruptMask(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), 0);
281 #elif defined(COMPONENT_CAT2)
282 Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), CY_GPIO_INTR_DISABLE);
283 #endif
284 cyhal_gpio_register_callback(pin, NULL);
285
286 (void)cyhal_gpio_disable_output(pin);
287 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined(CY_IP_MXS22IOSS)
288 for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
289 {
290 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
291 if(mapping.pin == pin)
292 {
293 if (CYHAL_TRIGGER_CPUSS_ZERO != _cyhal_gpio_source_signals[i])
294 {
295 (void)cyhal_gpio_disconnect_digital(pin, _cyhal_gpio_source_signals[i]);
296 }
297 }
298 }
299 #endif
300
301 Cy_GPIO_Pin_FastInit(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), CY_GPIO_DM_ANALOG, 0UL, HSIOM_SEL_GPIO);
302
303 /* Do not attempt to free the resource we don't reserve in mbed. */
304 #ifndef __MBED__
305 cyhal_resource_inst_t pinRsc = _cyhal_utils_get_gpio_resource(pin);
306 cyhal_hwmgr_free(&pinRsc);
307 #endif
308 }
309 }
310 else
311 {
312 CY_ASSERT(false); /* Should not be freeing if we never initialized anything */
313 }
314 }
315
cyhal_gpio_configure(cyhal_gpio_t pin,cyhal_gpio_direction_t direction,cyhal_gpio_drive_mode_t drive_mode)316 cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode)
317 {
318 uint32_t pdldrive_mode = _cyhal_gpio_convert_drive_mode(drive_mode, direction);
319 Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), pdldrive_mode);
320
321 return CY_RSLT_SUCCESS;
322 }
323
cyhal_gpio_register_callback(cyhal_gpio_t pin,cyhal_gpio_callback_data_t * callback_data)324 void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_callback_data_t* callback_data)
325 {
326 uint32_t savedIntrStatus = cyhal_system_critical_section_enter();
327
328 // Remove if already registered;
329 cyhal_gpio_callback_data_t** ptr = &(_cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)]);
330 while (NULL != *ptr)
331 {
332 if ((*ptr)->pin == pin)
333 {
334 *ptr = (*ptr)->next;
335 break;
336 }
337 ptr = &((*ptr)->next);
338 }
339 // Add if requested
340 if (NULL != callback_data)
341 {
342 CY_ASSERT(NULL != callback_data->callback);
343 callback_data->pin = pin;
344 callback_data->next = _cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)];
345 _cyhal_gpio_callbacks[CYHAL_GET_PORT(pin)] = callback_data;
346 }
347
348 cyhal_system_critical_section_exit(savedIntrStatus);
349 }
350
cyhal_gpio_enable_event(cyhal_gpio_t pin,cyhal_gpio_event_t event,uint8_t intr_priority,bool enable)351 void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intr_priority, bool enable)
352 {
353 #if (_CYHAL_IRQ_MUXING)
354 /* We may be in a critical section. Only clear the interrupt status if there isn't a pending interrupt */
355 if ((Cy_GPIO_GetInterruptStatus(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin)) == 0) || enable)
356 #endif
357 {
358 Cy_GPIO_ClearInterrupt(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin));
359 }
360 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D)
361 Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), (uint32_t)event);
362 Cy_GPIO_SetInterruptMask(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), (uint32_t)enable);
363 #if defined(COMPONENT_CAT1D)
364 uint32_t port = CYHAL_GET_PORT(pin);
365 _cyhal_system_irq_t irqn;
366 if(port <= 2u)
367 {
368 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + port);
369 }
370 else if(port <= 4u)
371 {
372 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + (port - 1u));
373 }
374 else if(port <= 21u)
375 {
376 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + (port - 2u));
377 }
378 else
379 {
380 irqn = (_cyhal_system_irq_t)0u;
381 CY_ASSERT(false); /* Unknown port */
382 }
383 #elif defined(COMPONENT_CAT1C)
384 uint32_t port = CYHAL_GET_PORT(pin);
385 /* Port 0-23 and 28-32 (inclusive) are DeepSleep capable. Port 24-27 and 33-34
386 * (inclusive) are active mode only. The interrupt numbers are grouped by power
387 * domain which means the numbers are non-contiguous - and die specific */
388 _cyhal_system_irq_t irqn;
389 if(port <= 23u)
390 {
391 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_dpslp_0_IRQn + port);
392 }
393 else if(port <= 27u)
394 {
395 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_act_24_IRQn + (port - 24u));
396 }
397 else if(port <= 32u)
398 {
399 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_dpslp_28_IRQn + (port - 28u));
400 }
401 #if defined(CY_DEVICE_TVIIBH8M) /* Ports 33 and 34 don't exist on the 4M part */
402 else if(port <= 34u)
403 {
404 irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_act_33_IRQn + (port - 33u));
405 }
406 #endif /* defined(CY_DEVICE_TVIIBH8M) */
407 else
408 {
409 irqn = (_cyhal_system_irq_t)0u;
410 CY_ASSERT(false); /* Unknown port */
411 }
412 #else /* other components */
413 _cyhal_system_irq_t irqn = (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + CYHAL_GET_PORT(pin));
414 #endif /* defined(COMPONENT_CAT1D) */
415 #elif defined(COMPONENT_CAT2)
416 uint32_t intr_val = enable ? (uint32_t)event : CY_GPIO_INTR_DISABLE;
417 Cy_GPIO_SetInterruptEdge(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), intr_val);
418 _cyhal_system_irq_t irqn = ((ioss_interrupts_gpio_0_IRQn + CYHAL_GET_PORT(pin)) < ioss_interrupt_gpio_IRQn)
419 ? (_cyhal_system_irq_t)(ioss_interrupts_gpio_0_IRQn + CYHAL_GET_PORT(pin))
420 : (_cyhal_system_irq_t)(ioss_interrupt_gpio_IRQn);
421 #endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) || defined(COMPONENT_CAT1C) || defined(COMPONENT_CAT1D) */
422
423 /* Only enable if it's not already enabled */
424 if (false == _cyhal_irq_is_enabled(irqn))
425 {
426 _cyhal_irq_register(irqn, intr_priority, _cyhal_gpio_irq_handler);
427 _cyhal_irq_enable(irqn);
428 }
429 else
430 {
431 _cyhal_irq_set_priority(irqn, intr_priority);
432 }
433 }
434
435 #if defined(CY_IP_MXS40IOSS) || defined(CY_IP_MXS40SIOSS) || defined (CY_IP_MXS22IOSS)
cyhal_gpio_connect_digital(cyhal_gpio_t pin,cyhal_source_t source)436 cy_rslt_t cyhal_gpio_connect_digital(cyhal_gpio_t pin, cyhal_source_t source)
437 {
438 // Search through cyhal_pin_map_peri_tr_io_output to determine if a trigger
439 // can be routed to it. (Note: tr_io_output refers to trigger mux output,
440 // not peripheral output. A trigger mux output is routed to a peripheral
441 // input.)
442 for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
443 {
444 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
445 if(mapping.pin == pin)
446 {
447 Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), mapping.hsiom);
448
449 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
450 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_PERI_TR_IO_OUTPUT0 + mapping.channel_num);
451 #elif defined(COMPONENT_CAT1B)
452 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_IOSS_PERI_TR_IO_OUTPUT_OUT0 + mapping.channel_num);
453 #elif defined(COMPONENT_CAT1D)
454 cyhal_dest_t dest;
455 if(0u == mapping.block_num)
456 {
457 dest = CYHAL_TRIGGER_IOSS_PERI0_TR_IO_OUTPUT_OUT0;
458 }
459 else
460 {
461 CY_ASSERT(1u == mapping.block_num);
462 dest = CYHAL_TRIGGER_IOSS_PERI1_TR_IO_OUTPUT_OUT0;
463 }
464
465 dest = (cyhal_dest_t)(dest + mapping.channel_num);
466 #endif
467
468 cy_rslt_t rslt = _cyhal_connect_signal(source, dest);
469 if (CY_RSLT_SUCCESS == rslt)
470 {
471 _cyhal_gpio_source_signals[i] = source;
472 }
473 return rslt;
474 }
475 }
476
477 return CYHAL_GPIO_RSLT_ERR_NO_INPUT_SIGNAL;
478 }
479
cyhal_gpio_enable_output(cyhal_gpio_t pin,cyhal_signal_type_t type,cyhal_source_t * source)480 cy_rslt_t cyhal_gpio_enable_output(cyhal_gpio_t pin, cyhal_signal_type_t type, cyhal_source_t *source)
481 {
482 // Search through cyhal_pin_map_peri_tr_io_input to determine if pin can be
483 // used to drive a trigger line. (Note: tr_io_input refers to trigger mux
484 // input, not peripheral input. A peripheral output is routed to a trigger
485 // mux input.)
486 for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_input)/sizeof(cyhal_resource_pin_mapping_t)); i++)
487 {
488 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_input[i];
489 if(mapping.pin == pin)
490 {
491 Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), mapping.hsiom);
492
493 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
494 cyhal_internal_source_t int_src = (cyhal_internal_source_t)(_CYHAL_TRIGGER_PERI_TR_IO_INPUT0 + mapping.channel_num);
495 #elif defined(COMPONENT_CAT1B)
496 cyhal_internal_source_t int_src = (cyhal_internal_source_t)(_CYHAL_TRIGGER_IOSS_PERI_TR_IO_INPUT_IN0 + mapping.channel_num);
497 #elif defined(COMPONENT_CAT1D)
498 cyhal_internal_source_t int_src;
499 if(0u == mapping.block_num)
500 {
501 int_src = _CYHAL_TRIGGER_IOSS_PERI0_TR_IO_INPUT_IN0;
502 }
503 else
504 {
505 CY_ASSERT(1u == mapping.block_num);
506 int_src = _CYHAL_TRIGGER_IOSS_PERI1_TR_IO_INPUT_IN0;
507 }
508
509 int_src = (cyhal_internal_source_t)(int_src + mapping.channel_num);
510 #endif
511 *source = (cyhal_source_t)_CYHAL_TRIGGER_CREATE_SOURCE(int_src, type);
512
513 return CY_RSLT_SUCCESS;
514 }
515 }
516
517 return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
518 }
519
cyhal_gpio_disconnect_digital(cyhal_gpio_t pin,cyhal_source_t source)520 cy_rslt_t cyhal_gpio_disconnect_digital(cyhal_gpio_t pin, cyhal_source_t source)
521 {
522 for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_output)/sizeof(cyhal_resource_pin_mapping_t)); i++)
523 {
524 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_output[i];
525 if(mapping.pin == pin)
526 {
527 Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), HSIOM_SEL_GPIO);
528
529 #if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1C)
530 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_PERI_TR_IO_OUTPUT0 + mapping.channel_num);
531 #elif defined(COMPONENT_CAT1B)
532 cyhal_dest_t dest = (cyhal_dest_t)(CYHAL_TRIGGER_IOSS_PERI_TR_IO_OUTPUT_OUT0 + mapping.channel_num);
533 #elif defined(COMPONENT_CAT1D)
534 cyhal_dest_t dest;
535 if(0u == mapping.block_num)
536 {
537 dest = CYHAL_TRIGGER_IOSS_PERI0_TR_IO_OUTPUT_OUT0;
538 }
539 else
540 {
541 CY_ASSERT(1u == mapping.block_num);
542 dest = CYHAL_TRIGGER_IOSS_PERI1_TR_IO_OUTPUT_OUT0;
543 }
544
545 dest = (cyhal_dest_t)(dest + mapping.channel_num);
546 #endif
547
548 cy_rslt_t rslt = _cyhal_disconnect_signal(source, dest);
549 if (CY_RSLT_SUCCESS == rslt)
550 {
551 _cyhal_gpio_source_signals[i] = CYHAL_TRIGGER_CPUSS_ZERO;
552 }
553 return rslt;
554 }
555 }
556
557 return CYHAL_GPIO_RSLT_ERR_NO_INPUT_SIGNAL;
558 }
559
cyhal_gpio_disable_output(cyhal_gpio_t pin)560 cy_rslt_t cyhal_gpio_disable_output(cyhal_gpio_t pin)
561 {
562 for(uint8_t i = 0; i < (uint8_t)(sizeof(cyhal_pin_map_peri_tr_io_input)/sizeof(cyhal_resource_pin_mapping_t)); i++)
563 {
564 cyhal_resource_pin_mapping_t mapping = cyhal_pin_map_peri_tr_io_input[i];
565 if(mapping.pin == pin)
566 {
567 Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), HSIOM_SEL_GPIO);
568
569 return CY_RSLT_SUCCESS;
570 }
571 }
572
573 return CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL;
574 }
575 #elif defined(CY_IP_M0S8IOSS)
576 // M0S8 devices do not have gpio triggers
cyhal_gpio_connect_digital(cyhal_gpio_t pin,cyhal_source_t source)577 cy_rslt_t cyhal_gpio_connect_digital(cyhal_gpio_t pin, cyhal_source_t source)
578 {
579 CY_UNUSED_PARAMETER(pin);
580 CY_UNUSED_PARAMETER(source);
581 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
582 }
583
cyhal_gpio_enable_output(cyhal_gpio_t pin,cyhal_signal_type_t type,cyhal_source_t * source)584 cy_rslt_t cyhal_gpio_enable_output(cyhal_gpio_t pin, cyhal_signal_type_t type, cyhal_source_t *source)
585 {
586 CY_UNUSED_PARAMETER(pin);
587 CY_UNUSED_PARAMETER(source);
588 CY_UNUSED_PARAMETER(type);
589 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
590 }
591
cyhal_gpio_disconnect_digital(cyhal_gpio_t pin,cyhal_source_t source)592 cy_rslt_t cyhal_gpio_disconnect_digital(cyhal_gpio_t pin, cyhal_source_t source)
593 {
594 CY_UNUSED_PARAMETER(pin);
595 CY_UNUSED_PARAMETER(source);
596 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
597 }
598
cyhal_gpio_disable_output(cyhal_gpio_t pin)599 cy_rslt_t cyhal_gpio_disable_output(cyhal_gpio_t pin)
600 {
601 CY_UNUSED_PARAMETER(pin);
602 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
603 }
604 #endif
605
606 #if defined(__cplusplus)
607 }
608 #endif /* __cplusplus */
609
610 #endif /* CYHAL_DRIVER_AVAILABLE_GPIO */
611