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