1 /***************************************************************************//**
2 * \file cyhal_interconnect.c
3 *
4 * \brief
5 * Provides a high level interface for interacting with the internal digital
6 * routing on the chip. This is 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_interconnect.h"
29 #include "cyhal_gpio_impl.h"
30
31 #if defined(__cplusplus)
32 extern "C"
33 {
34 #endif
35
36 #if (CYHAL_DRIVER_AVAILABLE_INTERCONNECT)
37
38 typedef enum
39 {
40 CYHAL_CONNECT_TYPE_VALIDATE,
41 CYHAL_CONNECT_TYPE_CONNECT,
42 CYHAL_CONNECT_TYPE_DISCONNECT,
43 } cyhal_connect_type_t;
44
45 // Only define if there are actual trigger signals
46 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
47 //Need to take peri #
48 #ifdef CY_IP_M0S8PERI_INSTANCES
49 #define _CYHAL_PERI_INSTANCES (CY_IP_M0S8PERI_INSTANCES)
50 #elif defined(CY_IP_MXSPERI_INSTANCES)
51 #define _CYHAL_PERI_INSTANCES (CY_IP_MXSPERI_INSTANCES)
52 #elif defined(CY_IP_MXPERI_TR_INSTANCES)
53 #define _CYHAL_PERI_INSTANCES (CY_IP_MXPERI_TR_INSTANCES)
54 #endif
55 #ifdef _CYHAL_PERI_INSTANCES
56 static uint8_t _CYHAL_INTERCONNECT_BASE_IDX[_CYHAL_PERI_INSTANCES] = {
57 0,
58 #if (_CYHAL_PERI_INSTANCES == 2)
59 PERI0_TR_GROUP_NR,
60 #elif (_CYHAL_PERI_INSTANCES > 2)
61 #error "Max amount of PERI instances is 2"
62 //For current devices there is a maximum of 2 PERI instances possible
63 #endif
64 };
65
get_peri_block_from_trigger(uint8_t mux_group)66 static uint32_t get_peri_block_from_trigger(uint8_t mux_group)
67 {
68 uint32_t blk_idx = 0;
69 for(uint8_t i = 0; i < _CYHAL_PERI_INSTANCES;i++)
70 {
71 if(mux_group > _CYHAL_INTERCONNECT_BASE_IDX[i])
72 {
73 blk_idx=i;
74 }
75 }
76 return blk_idx;
77 }
78
get_local_peri_group_num_from_trigger(uint8_t mux_group)79 static uint32_t get_local_peri_group_num_from_trigger(uint8_t mux_group)
80 {
81 return ((uint32_t)(mux_group - _CYHAL_INTERCONNECT_BASE_IDX[get_peri_block_from_trigger(mux_group)]));
82 }
83 // Helpers for creating Cy_TrigMux_* inputs //helper for local peri based group
84 #define CY_TRIGMUX_INPUT_LINE(mux_group, source_idx) (uint32_t)(((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (source_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
85 #define CY_TRIGMUX_OUTPUT_LINE(mux_group, dest_idx) (uint32_t)(0x40000000 | ((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (dest_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
86 #define CY_SELECT_OUTPUT_LINE(mux_group, dest_idx) (uint32_t)(0x40001000 | ((get_local_peri_group_num_from_trigger(mux_group))) << 8 | (dest_idx) | (get_peri_block_from_trigger(mux_group) << 16u))
87 #else
88 #error "No PERI Instances"
89 #endif
90 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
_cyhal_get_first_1to1_mux_idx(void)91 static int8_t _cyhal_get_first_1to1_mux_idx(void)
92 {
93 for(uint8_t idx = 0; idx < (sizeof(cyhal_is_mux_1to1)/sizeof(cyhal_is_mux_1to1[0])); idx++)
94 {
95 if(cyhal_is_mux_1to1[idx])
96 return idx;
97 }
98
99 return -1;
100 }
101 #endif
102
103 // Reads peri trigmux register and returns the selected input line (0 is
104 // default if no line has been selected)
_cyhal_read_mux_input_idx(uint8_t mux_group,uint8_t mux_output_idx)105 static uint8_t _cyhal_read_mux_input_idx(uint8_t mux_group, uint8_t mux_output_idx)
106 {
107 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
108 const int8_t MUX_GROUP_1TO1_OFFSET = _cyhal_get_first_1to1_mux_idx();
109 const uint8_t FIRST_1TO1_MUX_GROUP_IDX = 16;
110 #endif
111
112 uint32_t mux_reg = 0;
113 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION == 1u) || (CY_IP_MXSPERI >= 1u)
114 // M0S8 has no 1to1 muxes but the table is still valid
115 if(cyhal_is_mux_1to1[mux_group])
116 {
117 // There are up to 16 regular mux groups and up to 16 1to1 mux groups
118 // (in PSoC™ 6). PERI_TR_GR_TR_CTL starts at the first regular mux so
119 // offset by 16 if reading a 1to1 mux.
120 mux_reg = PERI_TR_GR_TR_CTL(mux_group - MUX_GROUP_1TO1_OFFSET + FIRST_1TO1_MUX_GROUP_IDX, mux_output_idx);
121 }
122 else
123 {
124 mux_reg = PERI_TR_GR_TR_CTL(mux_group, mux_output_idx);
125 }
126 #else // CY_IP_MXPERI_VERSION == 1
127 mux_reg = PERI_TR_GR_TR_CTL(mux_group, mux_output_idx);
128 #endif
129
130
131 #if (CY_IP_MXPERI_VERSION >= 1u) || (CY_IP_MXSPERI >= 1u)
132 return _FLD2VAL(PERI_TR_GR_TR_OUT_CTL_TR_SEL, mux_reg);
133 #elif CY_IP_M0S8PERI_VERSION == 1u
134 return _FLD2VAL(PERI_TR_CTL_TR_SEL, mux_reg);
135 #endif
136 }
137
138 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_M0S8PERI_VERSION == 1u) || (CY_IP_MXSPERI >= 1u)
_cyhal_interconnect_change_connection_direct(uint8_t mux_group,uint8_t mux_group_1to1_offset,uint8_t source_idx,uint8_t dest_idx,cyhal_signal_type_t type,bool connect)139 static cy_rslt_t _cyhal_interconnect_change_connection_direct(
140 uint8_t mux_group, uint8_t mux_group_1to1_offset, uint8_t source_idx, uint8_t dest_idx, cyhal_signal_type_t type, bool connect)
141 {
142 #if CY_IP_M0S8PERI_VERSION == 1u
143 CY_UNUSED_PARAMETER(type);
144 CY_UNUSED_PARAMETER(mux_group_1to1_offset);
145 #endif
146
147 if(cyhal_is_mux_1to1[mux_group])
148 {
149 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_MXSPERI >= 1u)
150 // Cy_TrigMux_Select assumes the mux_group idx param starts from the
151 // first 1to1 mux (so first 1to1 mux is 0)
152 uint32_t out_trig = CY_SELECT_OUTPUT_LINE(mux_group - mux_group_1to1_offset, dest_idx);
153
154 if(connect)
155 return Cy_TrigMux_Select(out_trig, false, (en_trig_type_t)type);
156 else
157 return Cy_TrigMux_Deselect(out_trig);
158 #else
159 return (connect)
160 ? CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION
161 : CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
162 #endif
163 }
164 else
165 {
166 uint32_t in_trig = CY_TRIGMUX_INPUT_LINE(mux_group, source_idx);
167 uint32_t out_trig = CY_TRIGMUX_OUTPUT_LINE(mux_group, dest_idx);
168
169 if(connect)
170 {
171 #if (CY_IP_MXPERI_VERSION >= 2u) || (CY_IP_MXSPERI >= 1u)
172 return Cy_TrigMux_Connect(in_trig, out_trig, false, (en_trig_type_t)type);
173 #else
174 return Cy_TrigMux_Connect(in_trig, out_trig);
175 #endif
176 }
177 else
178 {
179 // No Cy_TrigMux_Disconnect so just clear register of found
180 // mux input line.
181 PERI_TR_GR_TR_CTL(mux_group, dest_idx) = 0;
182 return CY_RSLT_SUCCESS;
183 }
184 }
185 }
186 #elif CY_IP_MXPERI_VERSION == 1u
187 /* Change a HAL trigger connection where a mux is involved */
_cyhal_interconnect_change_connection_direct(uint8_t mux,uint8_t input_idx,uint8_t output_idx,cyhal_signal_type_t type,bool connect)188 static cy_rslt_t _cyhal_interconnect_change_connection_direct(uint8_t mux, uint8_t input_idx, uint8_t output_idx, cyhal_signal_type_t type, bool connect)
189 {
190 if (connect)
191 {
192 uint32_t in_trig = CY_TRIGMUX_INPUT_LINE(mux, input_idx);
193 uint32_t out_trig = CY_TRIGMUX_OUTPUT_LINE(mux, output_idx);
194
195 return Cy_TrigMux_Connect(in_trig, out_trig, false, (en_trig_type_t)type);
196 }
197 else
198 {
199 PERI_TR_GR_TR_CTL(mux, output_idx) = 0;
200 return CY_RSLT_SUCCESS;
201 }
202 }
203
204 /* Change a HAL trigger connection where 2 muxes are involved */
_cyhal_interconnect_change_connection_indirect(uint8_t source_mux_group,uint8_t source_mux_input_idx,uint8_t source_mux_output_idx,uint8_t dest_mux_group,uint8_t dest_mux_input_idx,uint8_t dest_mux_output_idx,cyhal_signal_type_t type,bool connect)205 static cy_rslt_t _cyhal_interconnect_change_connection_indirect(uint8_t source_mux_group, uint8_t source_mux_input_idx, uint8_t source_mux_output_idx,
206 uint8_t dest_mux_group, uint8_t dest_mux_input_idx, uint8_t dest_mux_output_idx, cyhal_signal_type_t type, bool connect)
207 {
208 if(connect)
209 {
210 // Construct Cy_TrigMux_Connect trigger inputs for both source and dest muxes
211 uint32_t source_mux_in_trig = CY_TRIGMUX_INPUT_LINE(source_mux_group, source_mux_input_idx);
212 uint32_t source_mux_out_trig = CY_TRIGMUX_OUTPUT_LINE(source_mux_group, source_mux_output_idx);
213
214 uint32_t dest_mux_in_trig = CY_TRIGMUX_INPUT_LINE(dest_mux_group, dest_mux_input_idx);
215 uint32_t dest_mux_out_trig = CY_TRIGMUX_OUTPUT_LINE(dest_mux_group, dest_mux_output_idx);
216
217 if(_cyhal_read_mux_input_idx(dest_mux_group, dest_mux_output_idx) != 0)
218 {
219 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
220 }
221
222 cy_rslt_t result = Cy_TrigMux_Connect(source_mux_in_trig, source_mux_out_trig, false, (en_trig_type_t)type);
223 if (CY_RSLT_SUCCESS == result)
224 result = Cy_TrigMux_Connect(dest_mux_in_trig, dest_mux_out_trig, false, (en_trig_type_t)type);
225 return result;
226 }
227 else
228 {
229 // No Cy_TrigMux_Disconnect so just clear registers of found muxes
230 PERI_TR_GR_TR_CTL(source_mux_group, source_mux_output_idx) = 0;
231 PERI_TR_GR_TR_CTL(dest_mux_group, dest_mux_output_idx) = 0;
232 return CY_RSLT_SUCCESS;
233 }
234 }
235 #endif /* #if CY_IP_MXPERI_VERSION >= 2u || CY_IP_M0S8PERI_VERSION == 1u */
236
237 // Since both connect and disconnect need to derive mux group(s) and trigger
238 // indices, use this func to avoid duplicate code.
_cyhal_interconnect_check_connection(cyhal_source_t source,cyhal_dest_t dest,cyhal_connect_type_t connect)239 static cy_rslt_t _cyhal_interconnect_check_connection(cyhal_source_t source, cyhal_dest_t dest, cyhal_connect_type_t connect)
240 {
241 cyhal_internal_source_t internal_src = _CYHAL_TRIGGER_GET_SOURCE_SIGNAL(source);
242 cyhal_signal_type_t type = _CYHAL_TRIGGER_GET_SOURCE_TYPE(source);
243 #if CY_IP_MXPERI_VERSION >= 2u || CY_IP_M0S8PERI_VERSION >= 1u || CY_IP_MXSPERI >= 1u
244 const int8_t mux_group_1to1_offset = _cyhal_get_first_1to1_mux_idx();
245
246 // cyhal_dest_to_mux stores 1to1 triggers with bit 8 set and the lower 7
247 // bits as the offset into the 1to1 triggers (so 128 is 1to1 mux index 0)
248 // but here we need the actual group offset for all the triggers.
249 uint8_t mux_group = cyhal_dest_to_mux[dest];
250 if(mux_group & 0x80)
251 mux_group = mux_group_1to1_offset + (mux_group & ~0x80);
252
253 uint8_t dest_idx = cyhal_mux_dest_index[dest];
254
255 // Search through table of mux input trigger lines
256 for (uint16_t source_idx = 0; source_idx < cyhal_sources_per_mux[mux_group]; source_idx++)
257 {
258 if(cyhal_mux_to_sources[mux_group][source_idx] == internal_src)
259 {
260 // 1to1 triggers muxes source and dest indices must match
261 if(cyhal_is_mux_1to1[mux_group] && (source_idx != dest_idx))
262 {
263 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
264 }
265
266 // Check if the mux is already configured (possibly from a
267 // different source)
268 if(CYHAL_CONNECT_TYPE_DISCONNECT != connect
269 && _cyhal_read_mux_input_idx(mux_group, dest_idx) != 0)
270 {
271 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
272 }
273
274 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
275 ? CY_RSLT_SUCCESS
276 : _cyhal_interconnect_change_connection_direct(mux_group, mux_group_1to1_offset, source_idx, dest_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
277 }
278 }
279 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
280 #elif CY_IP_MXPERI_VERSION == 1u
281 uint8_t dest_mux_group = cyhal_dest_to_mux[dest];
282 uint8_t dest_mux_output_idx = cyhal_mux_dest_index[dest];
283
284 // Special case 1: DW sources connect to USB_DMA_BURSTEND destinations directly
285 // through mux 9 so handle here.
286 if(dest_mux_group == 9)
287 {
288 if((internal_src < _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) || (internal_src > _CYHAL_TRIGGER_CPUSS_DW1_TR_OUT15))
289 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
290
291 if((dest < CYHAL_TRIGGER_USB_DMA_BURSTEND0) || (dest > CYHAL_TRIGGER_USB_DMA_BURSTEND7))
292 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
293
294 uint16_t mux9_input_idx = (uint16_t)(internal_src - _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) + 1;
295 uint16_t mux9_output_idx = (uint16_t)(dest - CYHAL_TRIGGER_USB_DMA_BURSTEND0);
296
297 uint8_t set_input_idx = _cyhal_read_mux_input_idx(9, mux9_output_idx);
298 if ((CYHAL_CONNECT_TYPE_DISCONNECT != connect) && (set_input_idx != 0))
299 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
300 else if ((CYHAL_CONNECT_TYPE_DISCONNECT == connect) && (set_input_idx == 0))
301 return CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
302 else
303 {
304 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
305 ? CY_RSLT_SUCCESS
306 : _cyhal_interconnect_change_connection_direct(9, mux9_input_idx, mux9_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
307 }
308 }
309
310 // Special case 2: UDB_TR_DW_ACK destinations have no destinations side mux
311 // and are instead only connected through mux 10. Handle those connections
312 // here (while handling all other connections through mux 10 later).
313 if((dest_mux_group == 10) && (dest >= CYHAL_TRIGGER_UDB_TR_DW_ACK0) && (dest <= CYHAL_TRIGGER_UDB_TR_DW_ACK7))
314 {
315 if((internal_src < _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) || (internal_src > _CYHAL_TRIGGER_CPUSS_DW1_TR_OUT15))
316 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
317
318 uint16_t mux10_input_idx = (uint16_t)(internal_src - _CYHAL_TRIGGER_CPUSS_DW0_TR_OUT0) + 1;
319 uint16_t mux10_output_idx = (uint16_t)(dest - CYHAL_TRIGGER_UDB_TR_DW_ACK0);
320
321 uint8_t set_input_idx = _cyhal_read_mux_input_idx(10, mux10_output_idx);
322 if ((CYHAL_CONNECT_TYPE_DISCONNECT != connect) && (set_input_idx != 0))
323 return CYHAL_INTERCONNECT_RSLT_ALREADY_CONNECTED;
324 else if ((CYHAL_CONNECT_TYPE_DISCONNECT == connect) && (set_input_idx == 0))
325 return CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT;
326 else
327 {
328 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
329 ? CY_RSLT_SUCCESS
330 : _cyhal_interconnect_change_connection_direct(10, mux10_input_idx, mux10_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
331 }
332 }
333
334 // Since PSoC™ 6 BLE devices w/ trigmux vers1 have a 1to1 relationship
335 // between peripheral sources and reduction trigger muxes (besides DW which
336 // connects to trig mux 9 and 10, handled above) it is possible to search
337 // through source mux tables to find the idx required.
338 uint16_t source_mux_group = 0;
339 uint16_t source_mux_input_idx = 0;
340 bool found_source_mux_info = false;
341 for(source_mux_group = 10; source_mux_group < 15; source_mux_group++)
342 {
343 for(source_mux_input_idx = 0; source_mux_input_idx < cyhal_sources_per_mux[source_mux_group]; source_mux_input_idx++)
344 {
345 if(cyhal_mux_to_sources[source_mux_group][source_mux_input_idx] == internal_src)
346 {
347 found_source_mux_info = true;
348 break;
349 }
350 }
351 if(found_source_mux_info)
352 break;
353 }
354
355 if(!found_source_mux_info)
356 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
357
358 // Construct the cyhal_internal_source_t range that contains all possible inputs
359 // from the source mux to the dest mux. Not every cyhal_internal_source_t in this
360 // range will go to the dest mux but dest_mux_input_line_low and
361 // dest_mux_input_line_high will be used in the next step to find which inputs can.
362 cyhal_internal_source_t dest_mux_input_line_low;
363 cyhal_internal_source_t dest_mux_input_line_high;
364 switch (source_mux_group)
365 {
366 case 10:
367 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP10_OUTPUT0;
368 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP10_OUTPUT7;
369 break;
370 case 11:
371 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP11_OUTPUT0;
372 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP11_OUTPUT15;
373 break;
374 case 12:
375 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP12_OUTPUT0;
376 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP12_OUTPUT9;
377 break;
378 case 13:
379 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP13_OUTPUT0;
380 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP13_OUTPUT17;
381 break;
382 case 14:
383 dest_mux_input_line_low = _CYHAL_TRIGGER_TR_GROUP14_OUTPUT0;
384 dest_mux_input_line_high = _CYHAL_TRIGGER_TR_GROUP14_OUTPUT15;
385 break;
386 default:
387 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
388 }
389
390 // Search through the dest mux source table to find the low and high
391 // indices of the valid inputs from the source mux to the dest mux. These
392 // indices will correspond to, and be between, dest_mux_input_line_low and
393 // dest_mux_input_line_high (but not necessarily the whole range). If e.g
394 // only source mux output lines 8-9 go to the dest mux this will be
395 // reflected by setting source_mux_start_idx to 8
396 uint16_t dest_mux_input_line_low_idx = 10000;
397 uint16_t dest_mux_input_line_high_idx = 0;
398 uint16_t source_mux_start_idx = 0;
399 for(uint16_t i = 0; i < cyhal_sources_per_mux[dest_mux_group]; i++)
400 {
401 if((cyhal_mux_to_sources[dest_mux_group][i] >= dest_mux_input_line_low) &&
402 (cyhal_mux_to_sources[dest_mux_group][i] <= dest_mux_input_line_high))
403 {
404 if(dest_mux_input_line_low_idx > i)
405 {
406 dest_mux_input_line_low_idx = i;
407 source_mux_start_idx = (uint16_t)(cyhal_mux_to_sources[dest_mux_group][i] - dest_mux_input_line_low);
408 }
409
410 if(dest_mux_input_line_high_idx < i)
411 dest_mux_input_line_high_idx = i;
412 }
413 }
414
415 // Construct possible output trigger lines from the source mux starting at
416 // the first input line found in the previous step. Since source mux output
417 // lines can be arbitrarily selected and may already be in use, read the
418 // source mux register to check if an output is free.
419 uint8_t source_mux_output_idx = 0;
420 uint8_t dest_mux_input_idx = 0;
421 bool found_connection = false;
422 for(source_mux_output_idx = source_mux_start_idx; source_mux_output_idx < (source_mux_start_idx + (dest_mux_input_line_high_idx - dest_mux_input_line_low_idx + 1)); source_mux_output_idx++)
423 {
424 // If connecting: Check if possible output trigger is free.
425 if((connect != CYHAL_CONNECT_TYPE_DISCONNECT) && _cyhal_read_mux_input_idx(source_mux_group, source_mux_output_idx) == 0)
426 {
427 dest_mux_input_idx = dest_mux_input_line_low_idx + source_mux_output_idx - source_mux_start_idx;
428
429 found_connection = true;
430 break;
431 }
432 // If disconnecting: We have already used this source mux output line
433 // and it matches the inputted source. Since disconnecting only
434 // requires output idx info (for both muxes) nothing needs to be
435 // calculated here.
436 else if((connect == CYHAL_CONNECT_TYPE_DISCONNECT) && _cyhal_read_mux_input_idx(source_mux_group, source_mux_output_idx) == source_mux_input_idx)
437 {
438 found_connection = true;
439 break;
440 }
441 }
442
443 if(!found_connection)
444 {
445 return (connect == CYHAL_CONNECT_TYPE_DISCONNECT)
446 ? CYHAL_INTERCONNECT_RSLT_CANNOT_DISCONNECT
447 : CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
448 }
449
450 return (connect == CYHAL_CONNECT_TYPE_VALIDATE)
451 ? CY_RSLT_SUCCESS
452 : _cyhal_interconnect_change_connection_indirect(source_mux_group, source_mux_input_idx, source_mux_output_idx,
453 dest_mux_group, dest_mux_input_idx, dest_mux_output_idx, type, connect == CYHAL_CONNECT_TYPE_CONNECT);
454 #else
455 #error Unrecognized PERI version
456 #endif
457 }
458
459 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
460
_cyhal_connect_signal(cyhal_source_t source,cyhal_dest_t dest)461 cy_rslt_t _cyhal_connect_signal(cyhal_source_t source, cyhal_dest_t dest)
462 {
463 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
464 return _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_CONNECT);
465 #else
466 CY_UNUSED_PARAMETER(source);
467 CY_UNUSED_PARAMETER(dest);
468 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
469 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
470 }
471
_cyhal_disconnect_signal(cyhal_source_t source,cyhal_dest_t dest)472 cy_rslt_t _cyhal_disconnect_signal(cyhal_source_t source, cyhal_dest_t dest)
473 {
474 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
475 return _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_DISCONNECT);
476 #else
477 CY_UNUSED_PARAMETER(source);
478 CY_UNUSED_PARAMETER(dest);
479 return CYHAL_INTERCONNECT_RSLT_INVALID_CONNECTION;
480 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
481 }
482
_cyhal_can_connect_signal(cyhal_source_t source,cyhal_dest_t dest)483 bool _cyhal_can_connect_signal(cyhal_source_t source, cyhal_dest_t dest)
484 {
485 #if defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)
486 return (CY_RSLT_SUCCESS == _cyhal_interconnect_check_connection(source, dest, CYHAL_CONNECT_TYPE_VALIDATE));
487 #else
488 CY_UNUSED_PARAMETER(source);
489 CY_UNUSED_PARAMETER(dest);
490 return false;
491 #endif /* defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI) */
492 }
493
494 #endif /* CYHAL_DRIVER_AVAILABLE_INTERCONNECT */
495
cyhal_connect_pin(const cyhal_resource_pin_mapping_t * pin_connection,uint8_t drive_mode)496 cy_rslt_t cyhal_connect_pin(const cyhal_resource_pin_mapping_t *pin_connection, uint8_t drive_mode)
497 {
498 cyhal_gpio_t pin = pin_connection->pin;
499 GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(CYHAL_GET_PORT(pin));
500 en_hsiom_sel_t hsiom = pin_connection->hsiom;
501
502 Cy_GPIO_Pin_FastInit(port, CYHAL_GET_PIN(pin), drive_mode, 1, hsiom);
503 // Force output to enable pulls.
504 switch (drive_mode)
505 {
506 case CY_GPIO_DM_PULLUP:
507 Cy_GPIO_Write(port, CYHAL_GET_PIN(pin), 1);
508 break;
509 case CY_GPIO_DM_PULLDOWN:
510 Cy_GPIO_Write(port, CYHAL_GET_PIN(pin), 0);
511 break;
512 default:
513 /* do nothing */
514 break;
515 }
516
517 return CY_RSLT_SUCCESS;
518 }
519
cyhal_disconnect_pin(cyhal_gpio_t pin)520 cy_rslt_t cyhal_disconnect_pin(cyhal_gpio_t pin)
521 {
522 GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(CYHAL_GET_PORT(pin));
523
524 Cy_GPIO_Pin_FastInit(port, CYHAL_GET_PIN(pin), CY_GPIO_DM_HIGHZ, 1, HSIOM_SEL_GPIO);
525
526 return CY_RSLT_SUCCESS;
527 }
528
529 #if defined(__cplusplus)
530 }
531 #endif
532