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