1 /**
2  * @file    mxc_sys.h
3  * @brief   System level header file.
4  */
5 
6 /******************************************************************************
7  *
8  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
9  * Analog Devices, Inc.),
10  * Copyright (C) 2023-2024 Analog Devices, Inc.
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 
26 #ifndef LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32570_MXC_SYS_H_
27 #define LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32570_MXC_SYS_H_
28 
29 #include "mxc_device.h"
30 #include "gcr_regs.h"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /**
37  * @defgroup mxc_sys System Configuration (MXC_SYS)
38  * @ingroup syscfg
39  * @details API for system configuration including clock source selection and entering critical sections of code.
40  * @{
41  */
42 
43 /** @brief System reset0 and reset1 enumeration. Used in MXC_SYS_PeriphReset0 function */
44 typedef enum {
45     MXC_SYS_RESET0_DMA = MXC_F_GCR_RST0_DMA_POS, /**< Reset DMA */
46     MXC_SYS_RESET0_WDT = MXC_F_GCR_RST0_WDT0_POS, /**< Reset WDT */
47     MXC_SYS_RESET0_GPIO0 = MXC_F_GCR_RST0_GPIO0_POS, /**< Reset GPIO0 */
48     MXC_SYS_RESET0_GPIO1 = MXC_F_GCR_RST0_GPIO1_POS, /**< Reset GPIO1 */
49     MXC_SYS_RESET0_GPIO2 = MXC_F_GCR_RST0_GPIO2_POS, /**< Reset GPIO2 */
50     MXC_SYS_RESET0_TMR0 = MXC_F_GCR_RST0_TMR0_POS, /**< Reset TMR0 */
51     MXC_SYS_RESET0_TMR1 = MXC_F_GCR_RST0_TMR1_POS, /**< Reset TMR1 */
52     MXC_SYS_RESET0_TMR2 = MXC_F_GCR_RST0_TMR2_POS, /**< Reset TMR2 */
53     MXC_SYS_RESET0_TMR3 = MXC_F_GCR_RST0_TMR3_POS, /**< Reset TMR3 */
54     MXC_SYS_RESET0_TMR4 = MXC_F_GCR_RST0_TMR4_POS, /**< Reset TMR4 */
55     MXC_SYS_RESET0_TMR5 = MXC_F_GCR_RST0_TMR5_POS, /**< Reset TMR5 */
56     MXC_SYS_RESET0_TMR6 = MXC_F_GCR_RST0_TMR6_POS, /**< Reset TMR6 */
57     MXC_SYS_RESET0_TMR7 = MXC_F_GCR_RST0_TMR7_POS, /**< Reset TMR7 */
58     MXC_SYS_RESET0_UART0 = MXC_F_GCR_RST0_UART0_POS, /**< Reset UART0 */
59     MXC_SYS_RESET0_UART1 = MXC_F_GCR_RST0_UART1_POS, /**< Reset UART1 */
60     MXC_SYS_RESET0_SPI0 = MXC_F_GCR_RST0_SPI0_POS, /**< Reset SPI0 */
61     MXC_SYS_RESET0_SPI1 = MXC_F_GCR_RST0_SPI1_POS, /**< Reset SPI1 */
62     MXC_SYS_RESET0_SPI2 = MXC_F_GCR_RST0_SPI2_POS, /**< Reset SPI2 */
63     MXC_SYS_RESET0_I2C0 = MXC_F_GCR_RST0_I2C0_POS, /**< Reset I2C0 */
64     MXC_SYS_RESET0_RTC = MXC_F_GCR_RST0_RTC_POS, /**< Reset RTC */
65     MXC_SYS_RESET0_CTB = MXC_F_GCR_RST0_CRYPTO_POS, /**< Reset CRYPTO */
66     MXC_SYS_RESET0_CLCD = MXC_F_GCR_RST0_CLCD_POS, /**< Reset CLCD */
67     MXC_SYS_RESET0_USB = MXC_F_GCR_RST0_USB_POS, /**< Reset USB */
68     MXC_SYS_RESET0_ADC = MXC_F_GCR_RST0_ADC_POS, /**< Reset ADC */
69     MXC_SYS_RESET0_UART2 = MXC_F_GCR_RST0_UART2_POS, /**< Reset UART2 */
70     MXC_SYS_RESET0_SRST = MXC_F_GCR_RST0_SOFT_POS, /**< Soft reset */
71     MXC_SYS_RESET0_PRST = MXC_F_GCR_RST0_PERIPH_POS, /**< Peripheral reset */
72     MXC_SYS_RESET0_SYS = MXC_F_GCR_RST0_SYS_POS, /**< System reset */
73     /* RESET1 Below this line we add 32 to separate RESET0 and RESET1 */
74     MXC_SYS_RESET1_I2C1 = (MXC_F_GCR_RST1_I2C1_POS + 32), /**< Reset I2C1 */
75     MXC_SYS_RESET1_PT = (MXC_F_GCR_RST1_PT_POS + 32), /**< Reset PT */
76     MXC_SYS_RESET1_SPIXIP = (MXC_F_GCR_RST1_SPIXIP_POS + 32), /**< Reset SPIXIP */
77     MXC_SYS_RESET1_XSPIM = (MXC_F_GCR_RST1_XSPIM_POS + 32), /**< Reset XSPIM */
78     MXC_SYS_RESET1_SDHC = (MXC_F_GCR_RST1_SDHC_POS + 32), /**< Reset SDHC */
79     MXC_SYS_RESET1_GPIO3 = (MXC_F_GCR_RST1_GPIO3_POS + 32), /**< Reset GPIO3 */
80     MXC_SYS_RESET1_OWIRE = (MXC_F_GCR_RST1_OWIRE_POS + 32), /**< Reset OWIRE */
81     MXC_SYS_RESET1_WDT1 = (MXC_F_GCR_RST1_WDT1_POS + 32), /**< Reset WDT1 */
82     MXC_SYS_RESET1_SPI3 = (MXC_F_GCR_RST1_SPI3_POS + 32), /**< Reset SPI3 */
83     MXC_SYS_RESET1_SPIXMEM = (MXC_F_GCR_RST1_SPIXMEM_POS + 32), /**< Reset SPIXMEM */
84     MXC_SYS_RESET1_I2C2 = (MXC_F_GCR_RST1_I2C2_POS + 32), /**< Reset I2C2*/
85     MXC_SYS_RESET1_UART3 = (MXC_F_GCR_RST1_UART3_POS + 32), /**< Reset UART3*/
86     MXC_SYS_RESET1_UART4 = (MXC_F_GCR_RST1_UART4_POS + 32), /**< Reset USRT4*/
87     MXC_SYS_RESET1_UART5 = (MXC_F_GCR_RST1_UART5_POS + 32), /**< Reset UART5*/
88     MXC_SYS_RESET1_KBD = (MXC_F_GCR_RST1_KBD_POS + 32), /**< Reset KBD*/
89     MXC_SYS_RESET1_ADC9 = (MXC_F_GCR_RST1_ADC9_POS + 32), /**< Reset ADC9*/
90     MXC_SYS_RESET1_SC0 = (MXC_F_GCR_RST1_SC0_POS + 32), /**< Reset SC0*/
91     MXC_SYS_RESET1_SC1 = (MXC_F_GCR_RST1_SC1_POS + 32), /**< Reset SC1*/
92     MXC_SYS_RESET1_NFC = (MXC_F_GCR_RST1_NFC_POS + 32), /**< Reset NFC*/
93     MXC_SYS_RESET1_EMAC = (MXC_F_GCR_RST1_EMAC_POS + 32), /**< Reset EMAC*/
94     MXC_SYS_RESET1_PCIF = (MXC_F_GCR_RST1_PCIF_POS + 32), /**< Reset PCIF*/
95     MXC_SYS_RESET1_HTMR0 = (MXC_F_GCR_RST1_HTMR0_POS + 32), /**< Reset HTMR0*/
96     MXC_SYS_RESET1_HTMR1 = (MXC_F_GCR_RST1_HTMR1_POS + 32), /**< Reset HTMR1*/
97     MXC_SYS_RESET1_AC = (MXC_F_GCR_RST1_AC_POS + 32), /**< Reset AC*/
98 } mxc_sys_reset_t;
99 
100 /** @brief System clock disable enumeration. Used in MXC_SYS_ClockDisable and MXC_SYS_ClockEnable functions */
101 typedef enum {
102     MXC_SYS_PERIPH_CLOCK_GPIO0 =
103         MXC_F_GCR_PCLKDIS0_GPIO0_POS, /**< Disable MXC_F_GCR_PCLKDIS0_GPIO0 clock */
104     MXC_SYS_PERIPH_CLOCK_GPIO1 =
105         MXC_F_GCR_PCLKDIS0_GPIO1_POS, /**< Disable MXC_F_GCR_PCLKDIS0_GPIO1 clock */
106     MXC_SYS_PERIPH_CLOCK_GPIO2 =
107         MXC_F_GCR_PCLKDIS0_GPIO2_POS, /**< Disable MXC_F_GCR_PCLKDIS0_GPIO2 clock */
108     MXC_SYS_PERIPH_CLOCK_USB =
109         MXC_F_GCR_PCLKDIS0_USB_POS, /**< Disable MXC_F_GCR_PCLKDIS0_USB clock */
110     MXC_SYS_PERIPH_CLOCK_CLCD =
111         MXC_F_GCR_PCLKDIS0_CLCD_POS, /**< Disable MXC_F_GCR_PCLKDIS0_CLC clock */
112     MXC_SYS_PERIPH_CLOCK_DMA =
113         MXC_F_GCR_PCLKDIS0_DMA_POS, /**< Disable MXC_F_GCR_PCLKDIS0_DMA clock */
114     MXC_SYS_PERIPH_CLOCK_SPI0 =
115         MXC_F_GCR_PCLKDIS0_SPI0_POS, /**< Disable MXC_F_GCR_PCLKDIS0_SPI0 clock */
116     MXC_SYS_PERIPH_CLOCK_SPI1 =
117         MXC_F_GCR_PCLKDIS0_SPI1_POS, /**< Disable MXC_F_GCR_PCLKDIS0_SPI1 clock */
118     MXC_SYS_PERIPH_CLOCK_SPI2 =
119         MXC_F_GCR_PCLKDIS0_SPI2_POS, /**< Disable MXC_F_GCR_PCLKDIS0_SPI2 clock */
120     MXC_SYS_PERIPH_CLOCK_UART0 =
121         MXC_F_GCR_PCLKDIS0_UART0_POS, /**< Disable MXC_F_GCR_PCLKDIS0_UART0 clock */
122     MXC_SYS_PERIPH_CLOCK_UART1 =
123         MXC_F_GCR_PCLKDIS0_UART1_POS, /**< Disable MXC_F_GCR_PCLKDIS0_UART1 clock */
124     MXC_SYS_PERIPH_CLOCK_I2C0 =
125         MXC_F_GCR_PCLKDIS0_I2C0_POS, /**< Disable MXC_F_GCR_PCLKDIS0_I2C0 clock */
126     MXC_SYS_PERIPH_CLOCK_CTB =
127         MXC_F_GCR_PCLKDIS0_CRYPTO_POS, /**< Disable MXC_F_GCR_PCLKDIS0_CRYPTO clock */
128     MXC_SYS_PERIPH_CLOCK_TMR0 =
129         MXC_F_GCR_PCLKDIS0_TMR0_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR0 clock */
130     MXC_SYS_PERIPH_CLOCK_TMR1 =
131         MXC_F_GCR_PCLKDIS0_TMR1_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR1 clock */
132     MXC_SYS_PERIPH_CLOCK_TMR2 =
133         MXC_F_GCR_PCLKDIS0_TMR2_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR2 clock */
134     MXC_SYS_PERIPH_CLOCK_TMR3 =
135         MXC_F_GCR_PCLKDIS0_TMR3_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR3 clock */
136     MXC_SYS_PERIPH_CLOCK_TMR4 =
137         MXC_F_GCR_PCLKDIS0_TMR4_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR4 clock */
138     MXC_SYS_PERIPH_CLOCK_TMR5 =
139         MXC_F_GCR_PCLKDIS0_TMR5_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR5 clock */
140     MXC_SYS_PERIPH_CLOCK_TMR6 =
141         MXC_F_GCR_PCLKDIS0_TMR6_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR6 clock */
142     MXC_SYS_PERIPH_CLOCK_TMR7 =
143         MXC_F_GCR_PCLKDIS0_TMR7_POS, /**< Disable MXC_F_GCR_PCLKDIS0_TMR7 clock */
144     MXC_SYS_PERIPH_CLOCK_KBD =
145         MXC_F_GCR_PCLKDIS0_KBD_POS, /**< Disable MXC_F_GCR_PCLKDIS0_ADC clock */
146     MXC_SYS_PERIPH_CLOCK_ADC =
147         MXC_F_GCR_PCLKDIS0_ADC_POS, /**< Disable MXC_F_GCR_PCLKDIS0_ADC clock */
148     MXC_SYS_PERIPH_CLOCK_HTMR0 =
149         MXC_F_GCR_PCLKDIS0_HTMR0_POS, /**< Disable MXC_F_GCR_PCLKDIS1_HTMR0 clock */
150     MXC_SYS_PERIPH_CLOCK_HTMR1 =
151         MXC_F_GCR_PCLKDIS0_HTMR1_POS, /**< Disable MXC_F_GCR_PCLKDIS1_HTMR1 clock */
152     MXC_SYS_PERIPH_CLOCK_I2C1 =
153         MXC_F_GCR_PCLKDIS0_I2C1_POS, /**< Disable MXC_F_GCR_PCLKDIS0_I2C1 clock */
154     MXC_SYS_PERIPH_CLOCK_PT = MXC_F_GCR_PCLKDIS0_PT_POS, /**< Disable MXC_F_GCR_PCLKDIS0_PT clock */
155     MXC_SYS_PERIPH_CLOCK_SPIXIP =
156         MXC_F_GCR_PCLKDIS0_SPIXIP_POS, /**< Disable MXC_F_GCR_PCLKDIS0_SPIXIP clock */
157     MXC_SYS_PERIPH_CLOCK_SPIXFC =
158         MXC_F_GCR_PCLKDIS0_SPIM_POS, /**< Disable MXC_F_GCR_PCLKDIS0_SPIM clock */
159     /* PCLKDIS1 Below this line we add 32 to separate PCLKDIS0 and PCLKDIS1 */
160     MXC_SYS_PERIPH_CLOCK_UART2 =
161         (MXC_F_GCR_PCLKDIS1_UART2_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_UART2 clock */
162     MXC_SYS_PERIPH_CLOCK_TRNG =
163         (MXC_F_GCR_PCLKDIS1_TRNG_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_TRNG clock */
164     MXC_SYS_PERIPH_CLOCK_WDT0 =
165         (MXC_F_GCR_PCLKDIS1_WDT0_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_WDT0 clock */
166     MXC_SYS_PERIPH_CLOCK_WDT1 =
167         (MXC_F_GCR_PCLKDIS1_WDT1_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_WDT1 clock */
168     MXC_SYS_PERIPH_CLOCK_GPIO3 =
169         (MXC_F_GCR_PCLKDIS1_GPIO3_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_GPIO3 clock */
170     MXC_SYS_PERIPH_CLOCK_SCACHE =
171         (MXC_F_GCR_PCLKDIS1_SCACHE_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SCACHE clock */
172     MXC_SYS_PERIPH_CLOCK_HA0 =
173         (MXC_F_GCR_PCLKDIS1_HA0_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_HA0 clock */
174     MXC_SYS_PERIPH_CLOCK_SDHC =
175         (MXC_F_GCR_PCLKDIS1_SDHC_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SDHC clock */
176     MXC_SYS_PERIPH_CLOCK_ICACHE =
177         (MXC_F_GCR_PCLKDIS1_ICC0_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_ICACHE clock */
178     MXC_SYS_PERIPH_CLOCK_ICACHEXIP =
179         (MXC_F_GCR_PCLKDIS1_ICCXIP_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_ICACHEXIP clock */
180     MXC_SYS_PERIPH_CLOCK_OWIRE =
181         (MXC_F_GCR_PCLKDIS1_OWIRE_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_OWIRE clock */
182     MXC_SYS_PERIPH_CLOCK_SPI3 =
183         (MXC_F_GCR_PCLKDIS1_SPI3_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SPI3 clock */
184     MXC_SYS_PERIPH_CLOCK_SPIXIPD =
185         (MXC_F_GCR_PCLKDIS1_SPIXIP_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SPIXIP clock */
186     MXC_SYS_PERIPH_CLOCK_I2C2 =
187         (MXC_F_GCR_PCLKDIS1_I2C2_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_I2C2 clock */
188     MXC_SYS_PERIPH_CLOCK_UART3 =
189         (MXC_F_GCR_PCLKDIS1_UART3_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_UART3 clock */
190     MXC_SYS_PERIPH_CLOCK_UART4 =
191         (MXC_F_GCR_PCLKDIS1_UART4_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_UART4 clock */
192     MXC_SYS_PERIPH_CLOCK_UART5 =
193         (MXC_F_GCR_PCLKDIS1_UART5_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_UART5 clock */
194     MXC_SYS_PERIPH_CLOCK_ADC9 =
195         (MXC_F_GCR_PCLKDIS1_ADC9_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_ADC9 clock */
196     MXC_SYS_PERIPH_CLOCK_SC0 =
197         (MXC_F_GCR_PCLKDIS1_SC0_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SC0 clock */
198     MXC_SYS_PERIPH_CLOCK_SC1 =
199         (MXC_F_GCR_PCLKDIS1_SC1_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_SC1 clock */
200     MXC_SYS_PERIPH_CLOCK_NFC =
201         (MXC_F_GCR_PCLKDIS1_NFC_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_NFC clock */
202     MXC_SYS_PERIPH_CLOCK_EMAC =
203         (MXC_F_GCR_PCLKDIS1_EMAC_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_EMAC clock */
204     MXC_SYS_PERIPH_CLOCK_HA1 =
205         (MXC_F_GCR_PCLKDIS1_HA1_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_HA1 clock */
206     MXC_SYS_PERIPH_CLOCK_PCIF =
207         (MXC_F_GCR_PCLKDIS1_PCIF_POS + 32), /**<Disable MXC_F_GCR_PCLKDIS1_PCIF clock */
208 } mxc_sys_periph_clock_t;
209 
210 /** @brief Enumeration to select System Clock source */
211 typedef enum {
212     MXC_SYS_CLOCK_IPO =
213         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_IPO, /**< Select the Internal Primary Oscillator (IPO) */
214     MXC_SYS_CLOCK_IBRO =
215         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_IBRO, /**< Select the Internal Baud Rate Oscillator (IBRO) */
216     MXC_SYS_CLOCK_ISO =
217         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_ISO, /**< Select the Internal Secondary Oscillator (ISO) */
218     MXC_SYS_CLOCK_ERFO =
219         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_ERFO, /**< Select the External RF Crystal Oscillator */
220     MXC_SYS_CLOCK_INRO =
221         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_INRO, /**< Select the Internal Nanoring Oscillator (INRO) */
222     MXC_SYS_CLOCK_ERTCO =
223         MXC_V_GCR_CLKCTRL_SYSCLK_SEL_ERTCO, /**< Select the External RTC Crystal Oscillator */
224 } mxc_sys_system_clock_t;
225 
226 typedef enum {
227     MXC_SYS_CLOCK_DIV_1 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV1,
228     MXC_SYS_CLOCK_DIV_2 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV2,
229     MXC_SYS_CLOCK_DIV_4 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV4,
230     MXC_SYS_CLOCK_DIV_8 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV8,
231     MXC_SYS_CLOCK_DIV_16 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV16,
232     MXC_SYS_CLOCK_DIV_32 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV32,
233     MXC_SYS_CLOCK_DIV_64 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV64,
234     MXC_SYS_CLOCK_DIV_128 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV128
235 } mxc_sys_system_clock_div_t;
236 
237 #define MXC_SYS_SCACHE_CLK 1 // Enable SCACHE CLK
238 #define MXC_SYS_CTB_CLK 1 // Enable CTB CLK
239 
240 /***** Function Prototypes *****/
241 
242 typedef struct {
243     int ie_status;
244     int in_critical;
245 } mxc_crit_state_t;
246 
247 static mxc_crit_state_t _state = { .ie_status = (int)0xFFFFFFFF, .in_critical = 0 };
248 
_mxc_crit_get_state(void)249 static inline void _mxc_crit_get_state(void)
250 {
251 #ifndef __riscv
252     /*
253         On ARM M the 0th bit of the Priority Mask register indicates
254         whether interrupts are enabled or not.
255 
256         0 = enabled
257         1 = disabled
258     */
259     uint32_t primask = __get_PRIMASK();
260     _state.ie_status = (primask == 0);
261 #else
262     /*
263         On RISC-V bit position 3 (Machine Interrupt Enable) of the
264         mstatus register indicates whether interrupts are enabled.
265 
266         0 = disabled
267         1 = enabled
268     */
269     uint32_t mstatus = get_mstatus();
270     _state.ie_status = ((mstatus & (1 << 3)) != 0);
271 #endif
272 }
273 
274 /**
275  * @brief Enter a critical section of code that cannot be interrupted.  Call @ref MXC_SYS_Crit_Exit to exit the critical section.
276  * @details Ex:
277  * @code
278  * MXC_SYS_Crit_Enter();
279  * printf("Hello critical section!\n");
280  * MXC_SYS_Crit_Exit();
281  * @endcode
282  * The @ref MXC_CRITICAL macro is also provided as a convencience macro for wrapping a code section in this way.
283  * @returns None
284  */
MXC_SYS_Crit_Enter(void)285 static inline void MXC_SYS_Crit_Enter(void)
286 {
287     _mxc_crit_get_state();
288     if (_state.ie_status)
289         __disable_irq();
290     _state.in_critical = 1;
291 }
292 
293 /**
294  * @brief Exit a critical section of code from @ref MXC_SYS_Crit_Enter
295  * @returns None
296  */
MXC_SYS_Crit_Exit(void)297 static inline void MXC_SYS_Crit_Exit(void)
298 {
299     if (_state.ie_status) {
300         __enable_irq();
301     }
302     _state.in_critical = 0;
303     _mxc_crit_get_state();
304     /*
305         ^ Reset the state again to prevent edge case
306         where interrupts get disabled, then Crit_Exit() gets
307         called, which would inadvertently re-enable interrupts
308         from old state.
309     */
310 }
311 
312 /**
313  * @brief Polls whether code is currently executing from a critical section.
314  * @returns 1 if code is currently in a critical section (interrupts are disabled).
315  *          0 if code is not in a critical section.
316  */
MXC_SYS_In_Crit_Section(void)317 static inline int MXC_SYS_In_Crit_Section(void)
318 {
319     return _state.in_critical;
320 }
321 
322 // clang-format off
323 /**
324  * @brief Macro for wrapping a section of code to make it critical (interrupts disabled).  Note: this macro
325  * does not support nesting.
326  * @details
327  * Ex:
328  * \code
329  * MXC_CRITICAL(
330  *      printf("Hello critical section!\n");
331  * )
332  * \endcode
333  * This macro places a call to @ref MXC_SYS_Crit_Enter before the code, and a call to @ref MXC_SYS_Crit_Exit after.
334  * @param code The code section to wrap.
335  */
336 #define MXC_CRITICAL(code) {\
337     MXC_SYS_Crit_Enter();\
338     code;\
339     MXC_SYS_Crit_Exit();\
340 }
341 // clang-format on
342 
343 /**
344  * @brief Determines if the selected peripheral clock is enabled.
345  * @param clock   Enumeration for desired clock.
346  * @returns       0 is the clock is disabled, non 0 if the clock is enabled.
347  */
348 int MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock);
349 
350 /**
351  * @brief Disables the selected peripheral clock.
352  * @param clock   Enumeration for desired clock.
353  */
354 void MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock);
355 
356 /**
357  * @brief Enables the selected peripheral clock.
358  * @param clock   Enumeration for desired clock.
359  */
360 void MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock);
361 
362 /**
363  * @brief Enables the 32kHz oscillator
364  * @param mxc_sys_cfg   Not used, may be NULL.
365  */
366 void MXC_SYS_RTCClockEnable(void);
367 
368 /**
369  * @brief Disables the 32kHz oscillator
370  * @returns         E_NO_ERROR if everything is successful
371  */
372 int MXC_SYS_RTCClockDisable(void);
373 
374 /**
375  * @brief Enable System Clock Source without switching to it
376  * @param      clock The clock to enable
377  * @return     E_NO_ERROR if everything is successful
378  */
379 int MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock);
380 
381 /**
382  * @brief Disable System Clock Source
383  * @param      clock The clock to disable
384  * @return     E_NO_ERROR if everything is successful
385  */
386 int MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock);
387 
388 /**
389  * @brief Select the system clock.
390  * @param clock     Enumeration for desired clock.
391  * @returns         E_NO_ERROR if everything is successful.
392  */
393 int MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock);
394 
395 /**
396  * @brief Set the system clock divider.
397  * @param div       Enumeration for desired clock divider.
398  */
399 void MXC_SYS_SetClockDiv(mxc_sys_system_clock_div_t div);
400 
401 /**
402  * @brief Get the system clock divider.
403  * @returns         System clock divider.
404  */
405 mxc_sys_system_clock_div_t MXC_SYS_GetClockDiv(void);
406 
407 /**
408  * @brief Wait for a clock to enable with timeout
409  * @param      ready The clock to wait for
410  * @return     E_NO_ERROR if ready, E_TIME_OUT if timeout
411  */
412 int MXC_SYS_Clock_Timeout(uint32_t ready);
413 
414 /**
415  * @brief Reset the peripherals and/or CPU in the RST0 or RST1 register.
416  * @param           Enumeration for what to reset. Can reset multiple items at once.
417  */
418 void MXC_SYS_Reset_Periph(mxc_sys_reset_t reset);
419 
420 /**
421  * @brief      Get the revision of the chip
422  * @returns    the chip revision
423  */
424 uint8_t MXC_SYS_GetRev(void);
425 
426 /**
427  * @brief      Get the USN of the chip
428  * @param      serialNumber buffer to store the USN
429  * @param      len          length of the USN buffer
430  * @returns    #E_NO_ERROR if everything is successful.
431  */
432 int MXC_SYS_GetUSN(uint8_t *serialNumber, int len);
433 
434 /**
435  * @brief This function PERMANENTLY locks the Debug Access Port.
436  *
437  * @warning After executing this function you will never be able
438  *          to reprogram the target micro.
439  */
440 int MXC_SYS_LockDAP_Permanent(void);
441 
442 #ifdef __cplusplus
443 }
444 #endif
445 
446 #endif // LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32570_MXC_SYS_H_
447