1 /***************************************************************************//**
2 * \file cy_mcwdt.c
3 * \version 1.70
4 *
5 * Description:
6 * Provides a system API for the MCWDT driver.
7 *
8 ********************************************************************************
9 * Copyright (c) (2016-2022), Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation.
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27
28 #if defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS40SRSS) && (CY_IP_MXS40SRSS_VERSION < 3) || defined (CY_IP_MXS22SRSS)
29
30 #include "cy_mcwdt.h"
31
32 #if defined(__cplusplus)
33 extern "C" {
34 #endif
35
36 /*******************************************************************************
37 * Function Name: Cy_MCWDT_Init
38 ****************************************************************************//**
39 *
40 * Initializes the MCWDT block.
41 *
42 * \param base
43 * The base pointer to a structure that describes the registers.
44 *
45 * \param config
46 * The pointer to a structure that contains component configuration data.
47 *
48 * \return cy_en_mcwdt_status_t
49 * *base checking result. If the pointer is NULL, returns error.
50 *
51 * \note
52 * This API should not be called when the counters are running. Prior to calling
53 * this API the counter should be disabled.
54 *
55 *******************************************************************************/
Cy_MCWDT_Init(MCWDT_STRUCT_Type * base,cy_stc_mcwdt_config_t const * config)56 cy_en_mcwdt_status_t Cy_MCWDT_Init(MCWDT_STRUCT_Type *base, cy_stc_mcwdt_config_t const *config)
57 {
58 cy_en_mcwdt_status_t ret = CY_MCWDT_BAD_PARAM;
59
60 if ((base != NULL) && (config != NULL))
61 {
62 CY_ASSERT_L2(CY_MCWDT_IS_MATCH_VALID(config->c0ClearOnMatch, config->c0Match));
63 CY_ASSERT_L2(CY_MCWDT_IS_MATCH_VALID(config->c1ClearOnMatch, config->c1Match));
64 CY_ASSERT_L2(CY_MCWDT_IS_BIT_VALID(config->c2ToggleBit));
65 CY_ASSERT_L3(CY_MCWDT_IS_MODE_VALID((cy_en_mcwdtmode_t)config->c0Mode));
66 CY_ASSERT_L3(CY_MCWDT_IS_MODE_VALID((cy_en_mcwdtmode_t)config->c1Mode));
67 CY_ASSERT_L3(CY_MCWDT_IS_MODE_VALID((cy_en_mcwdtmode_t)config->c2Mode));
68
69 MCWDT_MATCH(base) = _VAL2FLD(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH1, config->c1Match) |
70 _VAL2FLD(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0, config->c0Match);
71
72 MCWDT_CONFIG(base) = _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_BITS2, config->c2ToggleBit) |
73 _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE2, config->c2Mode) |
74 _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR0, config->c0ClearOnMatch) |
75 _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR1, config->c1ClearOnMatch) |
76 (config->c1c2Cascade ? MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE1_2_Msk : 0UL) |
77 _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE1, config->c1Mode) |
78 (config->c0c1Cascade ? MCWDT_STRUCT_MCWDT_CONFIG_WDT_CASCADE0_1_Msk : 0UL) |
79 _VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MODE0, config->c0Mode);
80
81 #if defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS22SRSS)
82 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_LOWER_MODE0, config->c0LowerLimitMode);
83 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_LOWER_MODE1, config->c1LowerLimitMode);
84 MCWDT_LOWER_LIMIT(base) = _VAL2FLD(MCWDT_STRUCT_MCWDT_LOWER_LIMIT_WDT_LOWER_LIMIT1, config->c1LowerLimit) |
85 _VAL2FLD(MCWDT_STRUCT_MCWDT_LOWER_LIMIT_WDT_LOWER_LIMIT0, config->c0LowerLimit);
86 #endif /* CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS, CY_IP_MXS22SRSS */
87
88 #if defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS22SRSS)
89 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CARRY0_1, config->c0c1carryoutconfig);
90 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CARRY1_2, config->c1c2carryoutconfig);
91
92 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MATCH0_1, config->c0c1matchconfig);
93 MCWDT_CONFIG(base) |=_VAL2FLD(MCWDT_STRUCT_MCWDT_CONFIG_WDT_MATCH1_2, config->c1c2matchconfig);
94 #endif /* CY_IP_MXS40SSRSS, CY_IP_MXS22SRSS */
95
96 ret = CY_MCWDT_SUCCESS;
97 }
98
99 return (ret);
100 }
101
102
103 /*******************************************************************************
104 * Function Name: Cy_MCWDT_DeInit
105 ****************************************************************************//**
106 *
107 * De-initializes the MCWDT block, returns register values to their default state.
108 *
109 * \param base
110 * The base pointer to a structure that describes the registers.
111 *
112 * \note
113 * This API should not be called when the counters are running. Prior to calling
114 * this API the counter should be disabled.
115 *
116 *******************************************************************************/
Cy_MCWDT_DeInit(MCWDT_STRUCT_Type * base)117 void Cy_MCWDT_DeInit(MCWDT_STRUCT_Type *base)
118 {
119 Cy_MCWDT_Unlock(base);
120
121 MCWDT_CNTLOW(base) = 0UL;
122 MCWDT_CNTHIGH(base) = 0UL;
123 MCWDT_MATCH(base) = 0UL;
124 MCWDT_CONFIG(base) = 0UL;
125 MCWDT_CTL(base) = 0UL;
126 MCWDT_INTR(base) = 0UL;
127 MCWDT_INTR_SET(base) = 0UL;
128 MCWDT_INTR_MASK(base) = 0UL;
129 #if defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS22SRSS)
130 MCWDT_LOWER_LIMIT(base) = 0UL;
131 #endif /* CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS, CY_IP_MXS22SRSS */
132 }
133
134
135 /*******************************************************************************
136 * Function Name: Cy_MCWDT_GetCountCascaded
137 ****************************************************************************//**
138 *
139 * Reports the current value of combined C1-C0 cascaded counters.
140 *
141 * \param base
142 * The base pointer to a structure that describes the registers.
143 *
144 * \note
145 * The user must enable both counters, and cascade C0 to C1,
146 * before calling this function. C2 is not reported.
147 * Instead, to get a 64-bit C2-C1-C0 cascaded value, the
148 * user must call this function followed by
149 * Cy_MCWDT_GetCount(base, CY_MCWDT_COUNTER2), and then combine the results.
150 * \note This function does not return the correct result when it is called
151 * after the Cy_MCWDT_Enable() or Cy_MCWDT_ResetCounters() function with
152 * a delay less than two lf_clk cycles. The recommended waitUs parameter
153 * value is 100 us.
154 *
155 * \return The value of combined C1-C0 cascaded counters.
156 *
157 *******************************************************************************/
Cy_MCWDT_GetCountCascaded(MCWDT_STRUCT_Type const * base)158 uint32_t Cy_MCWDT_GetCountCascaded(MCWDT_STRUCT_Type const *base)
159 {
160 uint32_t countVal = MCWDT_CNTLOW(base);
161 uint32_t counter1 = countVal >> MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR1_Pos;
162 uint32_t counter0 = countVal & MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR0_Msk;
163 uint32_t match0 = _FLD2VAL(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH0, MCWDT_MATCH(base));
164 uint32_t match1 = _FLD2VAL(MCWDT_STRUCT_MCWDT_MATCH_WDT_MATCH1, MCWDT_MATCH(base));
165 #if defined (CY_IP_MXS40SRSS_MCWDT)
166 /*
167 * The counter counter0 goes to zero when it reaches the match0
168 * value (c0ClearOnMatch = 1) or reaches the maximum
169 * value (c0ClearOnMatch = 0). The counter counter1 increments on
170 * the next rising edge of the MCWDT clock after
171 * the Clear On Match event takes place.
172 * The software increments counter1 to eliminate the case
173 * when the both counter0 and counter1 counters have zeros.
174 */
175 if (0UL == counter0)
176 {
177 counter1++;
178 }
179 #endif
180 /* Check if the counter0 is Free running */
181 if (0UL == _FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR0, MCWDT_CONFIG(base)))
182 {
183 /* Save match0 value with the correction when counter0
184 * goes to zero when it reaches the match0 value.
185 */
186 countVal = match0 + 1UL;
187
188 if (0UL != counter1)
189 {
190 /* Set match to the maximum value */
191 match0 = MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR0_Msk;
192 }
193
194 if (countVal < counter0)
195 {
196 /* Decrement counter1 when the counter0 is great than match0 value */
197 counter1--;
198 }
199 }
200
201 /* Add the correction to counter0 */
202 counter0 += counter1;
203
204 /* Set counter1 match value to 65535 when the counter1 is free running */
205 if (0UL == _FLD2VAL(MCWDT_STRUCT_MCWDT_CONFIG_WDT_CLEAR1, MCWDT_CONFIG(base)))
206 {
207 match1 = MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR1_Msk >> MCWDT_STRUCT_MCWDT_CNTLOW_WDT_CTR1_Pos;
208 }
209
210 /* Check for overflow */
211 if (match1 < counter1)
212 {
213 /* Reset counter0 to disable the added correction of the counter1 value */
214 counter0 = 0UL;
215
216 /* Reset counter1 to prevent the wrong cascaded value calculation
217 * because counter1 is updated only on the following clock edge after clearing counter0
218 */
219 counter1 = 0UL;
220 }
221
222 /* Calculate the combined value for C1-C0 cascaded counters */
223 countVal = counter0 + (counter1 * match0);
224
225 return (countVal);
226 }
227
228
229 #if defined(__cplusplus)
230 }
231 #endif
232
233 #endif /* CY_IP_MXS40SRSS_MCWDT, CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS, CY_IP_MXS22SRSS */
234
235 /* [] END OF FILE */
236