1 /***************************************************************************//**
2 * \file cy_trigmux.c
3 * \version 1.60.1
4 *
5 * \brief Trigger mux API.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if defined (CY_IP_MXSPERI) || defined (CY_IP_MXPERI)
28 
29 #include "cy_trigmux.h"
30 
31 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 14.3', 4, \
32 'CY_PERI_V1 is not available for CAT1B devices.')
33 
34 #define CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType)  (((trigType) == TRIGGER_TYPE_EDGE) || \
35                                                  ((trigType) == TRIGGER_TYPE_LEVEL))
36 
37 #define CY_TRIGMUX_V1_IS_CYCLES_VALID(cycles)   (CY_TRIGGER_INFINITE >= (cycles))
38 #define CY_TRIGMUX_V2_IS_CYCLES_VALID(cycles)   ((CY_TRIGGER_DEACTIVATE == (cycles)) || \
39                                                  (CY_TRIGGER_TWO_CYCLES == (cycles)) || \
40                                                  (CY_TRIGGER_INFINITE   == (cycles)))
41 #define CY_TRIGMUX_IS_CYCLES_VALID(cycles)      ((CY_PERI_V1 && CY_TRIGMUX_V1_IS_CYCLES_VALID(cycles)) || \
42                                                                 CY_TRIGMUX_V2_IS_CYCLES_VALID(cycles))
43 
44 # if defined (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES == 2)
45 #define CY_TRIGMUX_INTRIG_MASK                  (PERI_TR_CMD_GROUP_SEL_Msk | PERI_TR_GR_TR_OUT_CTL_TR_SEL_Msk | PERI_INSTANCE_1_IDENT_Msk)
46 #else
47 #define CY_TRIGMUX_INTRIG_MASK                  (PERI_TR_CMD_GROUP_SEL_Msk | PERI_TR_GR_TR_OUT_CTL_TR_SEL_Msk)
48 #endif /* (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES==2) */
49 #define CY_TRIGMUX_IS_INTRIG_VALID(inTrg)       (0UL == ((inTrg) & (uint32_t)~CY_TRIGMUX_INTRIG_MASK))
50 
51 # if defined (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES == 2)
52 #define CY_TRIGMUX_OUTTRIG_MASK                 (PERI_TR_CMD_OUT_SEL_Msk | PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk | PERI_INSTANCE_1_IDENT_Msk)
53 #else
54 #define CY_TRIGMUX_OUTTRIG_MASK                 (PERI_TR_CMD_OUT_SEL_Msk | PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
55 #endif /* (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES==2) */
56 #define CY_TRIGMUX_IS_OUTTRIG_VALID(outTrg)     ((0UL == ((outTrg) & (uint32_t)~CY_TRIGMUX_OUTTRIG_MASK)) && \
57                                                  (0UL != ((outTrg) & PERI_TR_CMD_OUT_SEL_Msk)))
58 
59 #define CY_TRIGMUX_ONETRIG_MASK                 (PERI_V2_TR_CMD_OUT_SEL_Msk | PERI_V2_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
60 
61 #if defined (CY_IP_MXSPERI) || (CY_IP_MXPERI_VERSION >= 3)
62 #define CY_TRIGMUX_ONETRIG_GR_START                0x10UL /* trigger 1-1 group [16-31] */
63 #define CY_TRIGMUX_IS_ONETRIG_VALID(oneTrg)     ((0UL == ((oneTrg) & (uint32_t)~CY_TRIGMUX_ONETRIG_MASK)) && \
64                                                  (0UL != ((oneTrg) & PERI_V2_TR_CMD_OUT_SEL_Msk)) && \
65                                                  (0UL != (_FLD2VAL(PERI_V2_TR_CMD_GROUP_SEL, oneTrg) & (uint32_t)CY_TRIGMUX_ONETRIG_GR_START)))
66 #else
67 #define CY_TRIGMUX_IS_ONETRIG_VALID(oneTrg)     ((0UL == ((oneTrg) & (uint32_t)~CY_TRIGMUX_ONETRIG_MASK)) && \
68                                                  (0UL != ((oneTrg) & PERI_V2_TR_CMD_OUT_SEL_Msk)) && \
69                                                  (0UL != ((oneTrg) & (PERI_V2_TR_CMD_GROUP_SEL_Msk & (uint32_t)~PERI_TR_CMD_GROUP_SEL_Msk))))
70 #endif
71 
72 # if defined (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES == 2U)
73 #define CY_TRIGMUX_TRIGLINE_MASK                (PERI_TR_CMD_OUT_SEL_Msk | CY_PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk | PERI_INSTANCE_1_IDENT_Msk)
74 #else
75 #define CY_TRIGMUX_TRIGLINE_MASK                (PERI_TR_CMD_OUT_SEL_Msk | CY_PERI_TR_CMD_GROUP_SEL_Msk | CY_PERI_TR_CTL_SEL_Msk)
76 #endif /* (CY_IP_MXSPERI) && (CY_IP_MXSPERI_INSTANCES == 2U) */
77 #define CY_TRIGMUX_IS_TRIGLINE_VALID(trgLn)     (0U == ((trgLn) & (uint32_t)~CY_TRIGMUX_TRIGLINE_MASK))
78 
79 #define CY_TRIGMUX_TR_CTL(outTrig)              (PERI_TR_GR_TR_CTL(_FLD2VAL(CY_PERI_TR_CMD_GROUP_SEL, outTrig), \
80                                                                    _FLD2VAL(CY_PERI_TR_CTL_SEL,       outTrig)))
81 
82 
83 /*******************************************************************************
84 * Function Name: Cy_TrigMux_Connect
85 ****************************************************************************//**
86 *
87 * Connects an input trigger source and output trigger.
88 *
89 * \param inTrig
90 * An input selection for the trigger mux.
91 * - Bit 30 should be cleared.
92 * - Bit 12 should be cleared.
93 * - Bits 11:8 represent the trigger group selection.
94 * - Bits 7:0 select the input trigger signal for the specified trigger multiplexer.
95 *
96 * \param outTrig
97 * The output of the trigger mux. This refers to the consumer of the trigger mux.
98 * - Bit 30 should be set.
99 * - Bit 12 should be cleared.
100 * - Bits 11:8 represent the trigger group selection.<br>
101 *  For PERI_ver1:
102 * - Bits 6:0 select the output trigger number in the trigger group.<br>
103 *  For PERI_ver2:
104 * - Bits 7:0 select the output trigger number in the trigger group.
105 *
106 * \param invert
107 * - true: The output trigger is inverted.
108 * - false: The output trigger is not inverted.
109 *
110 * \param trigType The trigger signal type.
111 * - TRIGGER_TYPE_EDGE: The trigger is synchronized to the consumer blocks clock
112 *   and a two-cycle pulse is generated on this clock.
113 * - TRIGGER_TYPE_LEVEL: The trigger is a simple level output.
114 *
115 * \return status:
116 * - CY_TRIGMUX_SUCCESS: The connection is made successfully.
117 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
118 *
119 * \funcusage
120 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Connect
121 *
122 *******************************************************************************/
Cy_TrigMux_Connect(uint32_t inTrig,uint32_t outTrig,bool invert,en_trig_type_t trigType)123 cy_en_trigmux_status_t Cy_TrigMux_Connect(uint32_t inTrig, uint32_t outTrig, bool invert, en_trig_type_t trigType)
124 {
125     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
126     CY_ASSERT_L3(CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType));
127     CY_ASSERT_L2(CY_TRIGMUX_IS_INTRIG_VALID(inTrig));
128     CY_ASSERT_L2(CY_TRIGMUX_IS_OUTTRIG_VALID(outTrig));
129 
130     /* inTrig and outTrig should be in the same group */
131     if ((inTrig & PERI_TR_CMD_GROUP_SEL_Msk) == (outTrig & PERI_TR_CMD_GROUP_SEL_Msk))
132     {
133         uint32_t interruptState = Cy_SysLib_EnterCriticalSection();
134 
135         CY_TRIGMUX_TR_CTL(outTrig) = (CY_TRIGMUX_TR_CTL(outTrig) &
136                                       (uint32_t)~(PERI_TR_GR_TR_OUT_CTL_TR_SEL_Msk |
137                                                   PERI_TR_GR_TR_OUT_CTL_TR_INV_Msk |
138                                                   PERI_TR_GR_TR_OUT_CTL_TR_EDGE_Msk)) |
139                                         (_VAL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_SEL, inTrig) |
140                                         _BOOL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_INV, invert) |
141                                          _VAL2FLD(PERI_TR_GR_TR_OUT_CTL_TR_EDGE, trigType));
142 
143         Cy_SysLib_ExitCriticalSection(interruptState);
144 
145         retVal = CY_TRIGMUX_SUCCESS;
146     }
147 
148     return retVal;
149 }
150 
151 
152 /*******************************************************************************
153 * Function Name: Cy_TrigMux_Select
154 ****************************************************************************//**
155 *
156 * Enables and configures the specified 1-to-1 trigger line. For PERI_ver2 only.
157 *
158 * \param outTrig
159 * The 1to1 trigger line.
160 * - Bit 30 should be set.
161 * - Bit 12 should be set.
162 * - Bits 11:8 represent the 1-to-1 trigger group selection.
163 * - Bits 7:0 select the trigger line number in the trigger group.
164 *
165 * \param invert
166 * - true: The trigger signal is inverted.
167 * - false: The trigger signal is not inverted.
168 *
169 * \param trigType The trigger signal type.
170 * - TRIGGER_TYPE_EDGE: The trigger is synchronized to the consumer blocks clock
171 *   and a two-cycle pulse is generated on this clock.
172 * - TRIGGER_TYPE_LEVEL: The trigger is a simple level output.
173 *
174 * \return status:
175 * - CY_TRIGMUX_SUCCESS: The selection is made successfully.
176 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
177 *
178 * \funcusage
179 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Select
180 *
181 *******************************************************************************/
Cy_TrigMux_Select(uint32_t outTrig,bool invert,en_trig_type_t trigType)182 cy_en_trigmux_status_t Cy_TrigMux_Select(uint32_t outTrig, bool invert, en_trig_type_t trigType)
183 {
184     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
185 
186     CY_ASSERT_L3(CY_TRIGMUX_IS_TRIGTYPE_VALID(trigType));
187     CY_ASSERT_L2(CY_TRIGMUX_IS_ONETRIG_VALID(outTrig));
188 
189     if (CY_PERI_V1 == 0U) /* !mxperi_v1 */
190     {
191         uint32_t interruptState;
192 
193         interruptState = Cy_SysLib_EnterCriticalSection();
194 
195         CY_TRIGMUX_TR_CTL(outTrig) = (CY_TRIGMUX_TR_CTL(outTrig) &
196                           (uint32_t)~(PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV_Msk |
197                                       PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE_Msk)) |
198                                      (PERI_TR_1TO1_GR_V2_TR_CTL_TR_SEL_Msk      |
199                             _BOOL2FLD(PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV, invert) |
200                              _VAL2FLD(PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE, trigType));
201 
202         Cy_SysLib_ExitCriticalSection(interruptState);
203 
204         retVal = CY_TRIGMUX_SUCCESS;
205     }
206 
207     return retVal;
208 }
209 
210 
211 /*******************************************************************************
212 * Function Name: Cy_TrigMux_Deselect
213 ****************************************************************************//**
214 *
215 * Disables the specified 1-to-1 trigger line. For PERI_ver2 only.
216 *
217 * \param outTrig
218 * The 1to1 trigger line.
219 * - Bit 30 should be set.
220 * - Bit 12 should be set.
221 * - Bits 11:8 represent the 1-to-1 trigger group selection.
222 * - Bits 7:0 select the trigger line number in the trigger group.
223 *
224 * \return status:
225 * - CY_TRIGMUX_SUCCESS: The deselection is made successfully.
226 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
227 *
228 * \funcusage
229 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_Deselect
230 *
231 *******************************************************************************/
Cy_TrigMux_Deselect(uint32_t outTrig)232 cy_en_trigmux_status_t Cy_TrigMux_Deselect(uint32_t outTrig)
233 {
234     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
235 
236     CY_ASSERT_L2(CY_TRIGMUX_IS_ONETRIG_VALID(outTrig));
237 
238     if (CY_PERI_V1 == 0U) /* !mxperi_v1 */
239     {
240         uint32_t interruptState;
241 
242         interruptState = Cy_SysLib_EnterCriticalSection();
243 
244         CY_TRIGMUX_TR_CTL(outTrig) &= (uint32_t)~(PERI_TR_1TO1_GR_V2_TR_CTL_TR_SEL_Msk |
245                                                   PERI_TR_1TO1_GR_V2_TR_CTL_TR_INV_Msk |
246                                                   PERI_TR_1TO1_GR_V2_TR_CTL_TR_EDGE_Msk);
247 
248         Cy_SysLib_ExitCriticalSection(interruptState);
249 
250         retVal = CY_TRIGMUX_SUCCESS;
251     }
252 
253     return retVal;
254 }
255 
256 
257 /*******************************************************************************
258 * Function Name: Cy_TrigMux_SetDebugFreeze
259 ****************************************************************************//**
260 *
261 * Enables/disables the Debug Freeze feature for the specified trigger
262 * multiplexer or 1-to-1 trigger line. For PERI_ver2 only.
263 *
264 * \param outTrig
265 * The output of the trigger mux or dedicated 1-to-1 trigger line.
266 * - Bit 30 should be set.
267 * - For PERI_ver1 Bits 11:8 represent the trigger group selection.
268 * - For PERI_ver2 Bits 12:8 represent the trigger group selection.
269 * - Bits 7:0 select the output trigger number in the trigger group.
270 *
271 * \param enable
272 * - true: The Debug Freeze feature is enabled.
273 * - false: The Debug Freeze feature is disabled.
274 *
275 * \return status:
276 * - CY_TRIGMUX_SUCCESS: The operation is made successfully.
277 * - CY_TRIGMUX_BAD_PARAM: The outTrig parameter is invalid.
278 *
279 * \funcusage
280 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_SetDebugFreeze
281 *
282 *******************************************************************************/
Cy_TrigMux_SetDebugFreeze(uint32_t outTrig,bool enable)283 cy_en_trigmux_status_t Cy_TrigMux_SetDebugFreeze(uint32_t outTrig, bool enable)
284 {
285     cy_en_trigmux_status_t retVal = CY_TRIGMUX_BAD_PARAM;
286 
287     if (CY_PERI_V1 == 0U) /* !mxperi_v1 */
288     {
289         uint32_t interruptState;
290 
291         interruptState = Cy_SysLib_EnterCriticalSection();
292 
293         if (enable)
294         {
295             CY_TRIGMUX_TR_CTL(outTrig) |= PERI_TR_GR_V2_TR_CTL_DBG_FREEZE_EN_Msk;
296         }
297         else
298         {
299             CY_TRIGMUX_TR_CTL(outTrig) &= (uint32_t)~PERI_TR_GR_V2_TR_CTL_DBG_FREEZE_EN_Msk;
300         }
301 
302         Cy_SysLib_ExitCriticalSection(interruptState);
303 
304         retVal = CY_TRIGMUX_SUCCESS;
305     }
306 
307     return retVal;
308 }
309 
310 
311 /*******************************************************************************
312 * Function Name: Cy_TrigMux_SwTrigger
313 ****************************************************************************//**
314 *
315 * This function generates a software trigger on an input trigger line.
316 * All output triggers connected to this input trigger will be triggered.
317 * The function also verifies that there is no activated trigger before
318 * generating another activation.
319 *
320 * \param trigLine
321 * The input of the trigger mux.
322 * - Bit 30 represents if the signal is an input/output. When this bit is set,
323 *   the trigger activation is for an output trigger from the trigger multiplexer.
324 *   When this bit is reset, the trigger activation is for an input trigger to
325 *   the trigger multiplexer.<br>
326 * - For PERI_ver1 Bits 11:8 represent the trigger group selection.<br>
327 * - For PERI_ver2 Bits 12:8 represent the trigger group selection.<br>
328 * In case of output trigger line (bit 30 is set):<br>
329 * For PERI_ver1:
330 * - Bits 6:0 select the output trigger number in the trigger group.<br>
331 * For PERI_ver2:
332 * - Bits 7:0 select the output trigger number in the trigger group.<br>
333 * In case of input trigger line (bit 30 is unset):
334 * - Bits 7:0 select the input trigger signal for the trigger multiplexer.
335 *
336 * \param cycles
337 *  The number of "Clk_Peri" cycles during which the trigger remains activated.<br>
338 *  For PERI_ver1: The valid range of cycles is 1 ... 254.<br>
339 *  For PERI_ver2: The only valid value of cycles is 2 (\ref CY_TRIGGER_TWO_CYCLES).<br>
340 *  Also there are special values (supported with both PERI_ver1 and PERI_ver2):
341 *   - CY_TRIGGER_INFINITE - trigger remains activated until the user deactivates it by
342 *   calling this function with CY_TRIGGER_DEACTIVATE parameter.
343 *   - CY_TRIGGER_DEACTIVATE - this is used to deactivate the trigger activated by
344 *   calling this function with CY_TRIGGER_INFINITE parameter.
345 *
346 * \return status:
347 * - CY_TRIGMUX_SUCCESS: The trigger is successfully activated/deactivated.
348 * - CY_TRIGMUX_INVALID_STATE: The trigger is already activated/not active.
349 * - CY_TRIGMUX_BAD_PARAM: Some parameter is invalid.
350 *
351 * \funcusage
352 * \snippet trigmux/snippet/main.c snippet_Cy_TrigMux_SwTrigger
353 *
354 *******************************************************************************/
Cy_TrigMux_SwTrigger(uint32_t trigLine,uint32_t cycles)355 cy_en_trigmux_status_t Cy_TrigMux_SwTrigger(uint32_t trigLine, uint32_t cycles)
356 {
357     cy_en_trigmux_status_t retVal = CY_TRIGMUX_INVALID_STATE;
358 
359     CY_ASSERT_L2(CY_TRIGMUX_IS_TRIGLINE_VALID(trigLine));
360     CY_ASSERT_L2(CY_TRIGMUX_IS_CYCLES_VALID(cycles));
361 
362     if (CY_TRIGGER_DEACTIVATE != cycles)
363     {
364         /* Activate the trigger if it is not in the active state. */
365         if (PERI_TR_CMD_ACTIVATE_Msk != (PERI_TR_CMD & PERI_TR_CMD_ACTIVATE_Msk))
366         {
367 
368             uint32_t trCmd = (trigLine & (PERI_TR_CMD_TR_SEL_Msk |
369                                           PERI_TR_CMD_OUT_SEL_Msk |
370                                        CY_PERI_TR_CMD_GROUP_SEL_Msk)) |
371                                           PERI_TR_CMD_ACTIVATE_Msk;
372 
373             retVal = CY_TRIGMUX_SUCCESS;
374 
375             if (CY_PERI_V1 != 0U) /* mxperi_v1 */
376             {
377                 PERI_TR_CMD = trCmd | _VAL2FLD(PERI_TR_CMD_COUNT, cycles);
378             }
379             else if (CY_TRIGGER_TWO_CYCLES == cycles) /* mxperi_v2 or later, 2 cycles pulse */
380             {
381 #if defined(CY_IP_MXSPERI_INSTANCES) && (CY_IP_MXSPERI_INSTANCES == 2U)
382                 if (0UL != (trigLine & PERI_INSTANCE_1_IDENT_Msk))
383                 {
384                     PERI1_TR_CMD = trCmd | PERI_V2_TR_CMD_TR_EDGE_Msk;
385                 }
386                 else
387                 {
388                     PERI_TR_CMD = trCmd | PERI_V2_TR_CMD_TR_EDGE_Msk;
389                 }
390 #else
391                 PERI_TR_CMD = trCmd | PERI_V2_TR_CMD_TR_EDGE_Msk;
392 #endif
393             }
394             else if (CY_TRIGGER_INFINITE == cycles) /* mxperi_v2 or later, infinite activating */
395             {
396                 PERI_TR_CMD = trCmd;
397             }
398             else /* mxperi_v2 or later, invalid cycles value */
399             {
400                 retVal = CY_TRIGMUX_BAD_PARAM;
401             }
402         }
403     }
404     else
405     {
406         /* Forcibly deactivate the trigger if it is in the active state. */
407         if (PERI_TR_CMD_ACTIVATE_Msk == (PERI_TR_CMD & PERI_TR_CMD_ACTIVATE_Msk))
408         {
409             PERI_TR_CMD = 0UL;
410 
411             retVal = CY_TRIGMUX_SUCCESS;
412         }
413     }
414 
415     return retVal;
416 }
417 
418 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 14.3')
419 
420 #endif /* CY_IP_MXSPERI, CY_IP_MXPERI */
421 
422 /* [] END OF FILE */
423