1 /**
2 * @file xmc1_scu.c
3 * @date 2019-03-20
4 *
5 * @cond
6 *********************************************************************************************************************
7 * XMClib v2.1.24 - XMC Peripheral Driver Library
8 *
9 * Copyright (c) 2015-2019, Infineon Technologies AG
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13 * following conditions are met:
14 *
15 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided with the distribution.
20 *
21 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22 * products derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33 * Infineon Technologies AG dave@infineon.com).
34 *********************************************************************************************************************
35 *
36 * Change History
37 * --------------
38 *
39 * 2015-02-20:
40 * - Initial <br>
41 *
42 * 2015-05-20:
43 * - XMC_SCU_StartTempMeasurement API is modified
44 * - XMC_ASSERT statements are added in XMC_SCU_INTERRUPT_SetEventHandler
45 *
46 * 2015-06-20:
47 * - XMC_SCU_INTERRUPT_EnableEvent,XMC_SCU_INTERRUPT_DisableEvent,
48 * - XMC_SCU_INTERRUPT_TriggerEvent,XMC_SCU_INTERUPT_GetEventStatus,
49 * - XMC_SCU_INTERRUPT_ClearEventStatus APIs are added
50 *
51 * 2015-09-23:
52 * - XMC1400 support added
53 *
54 * 2015-11-30:
55 * - Documentation improved
56 *
57 * 2016-02-29:
58 * - Fixed XMC_SCU_CLOCK_ScaleMCLKFrequency
59 * It solves issues with down clock frequency scaling
60 *
61 * 2016-04-15:
62 * - Fixed XMC_SCU_CLOCK_Init for XMC1400
63 * It solves issues when trying to disable the OSCHP and use the XTAL pins as GPIO
64 *
65 * 2017-02-09
66 * - At XMC_SCU_CLOCK_Init() fixed issue while reading oscillator watchdog status
67 *
68 * 2017-04-11:
69 * - Added XMC_SCU_SetBMI()
70 *
71 * 2017-06-24
72 * - Changed XMC_SCU_SetBMI() for XMC11/XMC12/XMC13 to set to 1 the bit 11 of BMI
73 *
74 * 2017-10-25
75 * - Move the following functions to xmc1_scu.h as STATCI_INLINE and make them available for XMC1 families
76 * XMC_SCU_CLOCK_EnableDCO1OscillatorWatchdog(),
77 * XMC_SCU_CLOCK_DisableDCO1OscillatorWatchdog(),
78 * XMC_SCU_CLOCK_ClearDCO1OscillatorWatchdogStatus(),
79 * XMC_SCU_CLOCK_IsDCO1ClockFrequencyUsable()
80 * - Changed XMC_SCU_SetBMI() for XMC11/XMC12/XMC13 to set to 1 the bits [7:6] of BMI
81 *
82 * 2018-06-21:
83 * - Changed XMC_SCU_CLOCK_Init() for XMC1400 adding a delay between disable/enable oscillator watchdog to avoid startup hangs when using external crystal oscillator
84 * - Changed XMC_SCU_CLOCK_Init() for XMC1400 adding a wait time of 5s after enabling the RTC_XTAL
85 *
86 * 2019-03-20:
87 * - Fix XMC_SCU_CLOCK_Init() if external XTAL is used for XMC1400 (clock watchdog issue, see errata SCU_CM.023)
88 * - Added DISABLE_WAIT_RTC_XTAL_OSC_STARTUP preprocessor guard:
89 * The RTC_XTAL can be used as clock source for RTC or as reference for DCO1 calibration
90 * In both cases if no wait is done in the startup after enabling the RTC_XTAL oscillator,
91 * the RTC_Enable() or the calibration will stall the MCU until the oscillator is stable (max. 5s according datasheet)
92 * - Added XMC_SCU_CLOCK_SetHighPerformanceOscillatorMode() and XMC_SCU_CLOCK_SetLowPerformanceOscillatorMode()
93 *
94 * @endcond
95 *
96 */
97
98 /**
99 *
100 * @brief SCU low level driver API prototype definition for XMC1 family of microcontrollers <br>
101 *
102 * <b>Detailed description of file</b> <br>
103 * APIs provided in this file cover the following functional blocks of SCU: <br>
104 * -- GCU (APIs prefixed with XMC_SCU_GEN_) <br>
105 * ----Temperature Monitoring, Voltage Monitoring, CCU Start etc
106 *
107 * -- CCU (APIs prefixed with XMC_SCU_CLOCK_)<br>
108 * ---- Clock initialization, Clock Gating, Sleep Management etc
109 *
110 * -- RCU (APIs prefixed with XMC_SCU_RESET_) <br>
111 * ---- Reset Init, Cause, Manual Reset Assert/Deassert etc
112 *
113 * -- INTERRUPT (APIs prefixed with XMC_SCU_INTERRUPT_)<br>
114 * ---- Initialization, Manual Assert/Deassert, Acknowledge etc
115 *
116 */
117
118 /*********************************************************************************************************************
119 * HEADER FILES
120 ********************************************************************************************************************/
121 #include <xmc_scu.h>
122
123 #if UC_FAMILY == XMC1
124
125 /*********************************************************************************************************************
126 * MACROS
127 ********************************************************************************************************************/
128 #define SCU_IRQ_NUM (3U) /**< array index value for list of events that can generate SCU interrupt */
129 #define SCU_GCU_PASSWD_PROT_ENABLE (195UL) /**< Password for enabling protection */
130 #define SCU_GCU_PASSWD_PROT_DISABLE (192UL) /**< Password for disabling protection */
131
132
133 #define XMC_SCU_CHECK_RTCCLKSRC(source) ( (source == XMC_SCU_CLOCK_RTCCLKSRC_DCO2) || \
134 (source == XMC_SCU_CLOCK_RTCCLKSRC_ERU_IOUT0) || \
135 (source == XMC_SCU_CLOCK_RTCCLKSRC_ACMP0_OUT) || \
136 (source == XMC_SCU_CLOCK_RTCCLKSRC_ACMP1_OUT) || \
137 (source == XMC_SCU_CLOCK_RTCCLKSRC_ACMP2_OUT) ) /**< Used to verify
138 whether provided RTC
139 clock source is valid
140 or not */
141 #define SCU_GENERAL_INTCR_INTSEL_Msk SCU_GENERAL_INTCR0_INTSEL0_Msk /**< Mask value of Interrupt Source Select
142 for Node 0 */
143 #define SCU_GENERAL_INTCR_INTSEL_Size SCU_GENERAL_INTCR0_INTSEL1_Pos /**< Bit position value of Interrupt Source Select
144 for Node 1 */
145
146 #define ANA_TSE_T1 (0x10000F30U) /**< d is a constant data can be retrieved from Flash sector 0 to calculate OFFSET
147 value for DCO calibration */
148 #define ANA_TSE_T2 (0x10000F31U) /**< e is a constant data can be retrieved from Flash sector 0 to calculate OFFSET
149 value for DCO calibration */
150 #define DCO_ADJLO_T1 (0x10000F32U) /**< b is a constant data can be retrieved from Flash sector 0 to calculate OFFSET
151 value for DCO calibration */
152 #define DCO_ADJLO_T2 (0x10000F33U) /**< a is a constant data can be retrieved from Flash sector 0 to calculate OFFSET
153 value for DCO calibration */
154
155 #if UC_SERIES == XMC14
156 #define XMC_SCU_INTERRUPT_EVENT_MAX (64U) /**< Maximum supported SCU events for XMC14 device. */
157 #else
158 #define XMC_SCU_INTERRUPT_EVENT_MAX (32U) /**< Maximum supported SCU events for XMC11/12/13 device. */
159 #endif
160
161 #if UC_SERIES == XMC14
162 #define DCO1_DIV2_FREQUENCY_KHZ_Q22_10 (48000U << 10) /**< used to configures main clock (MCLK) frequency to requested
163 frequency value during runtime for XMC14 device. */
164 #else
165 #define DCO1_DIV2_FREQUENCY_KHZ_Q24_8 (32000U << 8) /**< used to configures main clock (MCLK) frequency to requested
166 frequency value during runtime for XMC11/12/13 device. */
167 #endif
168
169 #define ROM_BmiInstallationReq \
170 (*((uint32_t (**)(uint32_t requestedBmiValue))0x00000108U)) /**< Pointer to Request BMI installation routine is
171 available inside ROM. */
172
173 #define ROM_CalcTemperature \
174 (*((uint32_t (**)(void))0x0000010cU)) /**< Pointer to Calculate chip temperature routine is
175 available inside ROM. */
176
177 #define ROM_CalcTSEVAR \
178 (*((uint32_t (**)(uint32_t temperature))0x00000120U)) /**< Pointer to Calculate target level for temperature
179 comparison routine is available inside ROM. */
180
181 /*********************************************************************************************************************
182 * LOCAL DATA
183 ********************************************************************************************************************/
184 static XMC_SCU_INTERRUPT_EVENT_HANDLER_t event_handler_list[XMC_SCU_INTERRUPT_EVENT_MAX]; /**< For registering callback
185 functions on SCU event
186 occurrence. */
187
188 static XMC_SCU_INTERRUPT_EVENT_t event_masks[SCU_IRQ_NUM] =
189 {
190 (XMC_SCU_INTERRUPT_EVENT_FLASH_ERROR |
191 XMC_SCU_INTERRUPT_EVENT_FLASH_COMPLETED |
192 XMC_SCU_INTERRUPT_EVENT_PESRAM |
193 XMC_SCU_INTERRUPT_EVENT_PEUSIC0 |
194 #if defined(USIC1)
195 XMC_SCU_INTERRUPT_EVENT_PEUSIC1 |
196 #endif
197 #if defined(CAN)
198 XMC_SCU_INTERRUPT_EVENT_PEMCAN |
199 #endif
200 #if UC_SERIES == XMC14
201 XMC_SCU_INTERRUPT_EVENT_LOSS_EXT_CLOCK |
202 #endif
203 XMC_SCU_INTERRUPT_EVENT_LOCI),
204
205 (XMC_SCU_INTERRUPT_EVENT_STDBYCLKFAIL |
206 #if UC_SERIES == XMC14
207 XMC_SCU_INTERRUPT_EVENT_DCO1_OUT_SYNC |
208 #endif
209 XMC_SCU_INTERRUPT_EVENT_VDDPI |
210 XMC_SCU_INTERRUPT_EVENT_VDROP |
211 XMC_SCU_INTERRUPT_EVENT_VCLIP |
212 XMC_SCU_INTERRUPT_EVENT_TSE_DONE |
213 XMC_SCU_INTERRUPT_EVENT_TSE_HIGH |
214 XMC_SCU_INTERRUPT_EVENT_TSE_LOW |
215 XMC_SCU_INTERRUPT_EVENT_WDT_WARN |
216 XMC_SCU_INTERRUPT_EVENT_RTC_PERIODIC |
217 XMC_SCU_INTERRUPT_EVENT_RTC_ALARM |
218 XMC_SCU_INTERRUPT_EVENT_RTCCTR_UPDATED |
219 XMC_SCU_INTERRUPT_EVENT_RTCATIM0_UPDATED |
220 XMC_SCU_INTERRUPT_EVENT_RTCATIM1_UPDATED |
221 XMC_SCU_INTERRUPT_EVENT_RTCTIM0_UPDATED |
222 XMC_SCU_INTERRUPT_EVENT_RTCTIM1_UPDATED),
223
224 (
225 #if UC_SERIES != XMC11
226 XMC_SCU_INTERRUPT_EVENT_ORC0 |
227 XMC_SCU_INTERRUPT_EVENT_ORC1 |
228 XMC_SCU_INTERRUPT_EVENT_ORC2 |
229 XMC_SCU_INTERRUPT_EVENT_ORC3 |
230 XMC_SCU_INTERRUPT_EVENT_ORC4 |
231 XMC_SCU_INTERRUPT_EVENT_ORC5 |
232 XMC_SCU_INTERRUPT_EVENT_ORC6 |
233 XMC_SCU_INTERRUPT_EVENT_ORC7 |
234 #endif
235 #if defined(COMPARATOR)
236 XMC_SCU_INTERRUPT_EVENT_ACMP0 |
237 XMC_SCU_INTERRUPT_EVENT_ACMP1 |
238 XMC_SCU_INTERRUPT_EVENT_ACMP2 |
239 #if UC_SERIES == XMC14
240 XMC_SCU_INTERRUPT_EVENT_ACMP3 |
241 #endif
242 #endif
243 0)
244 }; /**< Defines list of events that can generate SCU interrupt and also indicates SCU events mapping to corresponding
245 service request number. These event mask values can be used to verify which event is triggered that corresponds
246 to service request number during runtime. All the event items are tabulated as per service request sources list
247 table of SCU. */
248
249 /*********************************************************************************************************************
250 * LOCAL ROUTINES
251 ********************************************************************************************************************/
252 /* Utility routine to perform frequency up scaling */
253 static void XMC_SCU_CLOCK_lFrequencyUpScaling(uint32_t curr_idiv, uint32_t idiv);
254
255 /* Utility routine to perform frequency down scaling */
256 static void XMC_SCU_CLOCK_lFrequencyDownScaling(uint32_t curr_idiv, uint32_t idiv);
257
258 /* Calculates the value which must be installed in ANATSEIx register to get indication in
259 SCU_INTERRUPT->SRRAW bit when the chip temperature is above/below some target/threshold. */
XMC_SCU_CalcTSEVAR(uint32_t temperature)260 static uint32_t XMC_SCU_CalcTSEVAR(uint32_t temperature)
261 {
262 uint32_t limit;
263
264 XMC_ASSERT("XMC_SCU_CalcTSEVAR: temperature out of range", (temperature >= 233U) && (temperature <= 388U));
265
266 limit = ROM_CalcTSEVAR(temperature);
267 if (limit == 0U)
268 {
269 limit = ROM_CalcTSEVAR(temperature + 1U);
270 if (limit == 0U)
271 {
272 limit = ROM_CalcTSEVAR(temperature - 1U);
273 }
274 }
275
276 return (limit);
277 }
278
279 #if UC_SERIES == XMC14
280 /* This is a local function used to generate the delay until register get updated with new configured value. */
delay(uint32_t cycles)281 __STATIC_FORCEINLINE void delay(uint32_t cycles)
282 {
283 while(--cycles > 0U)
284 {
285 __NOP();
286 }
287 }
288 #endif
289
290 /*********************************************************************************************************************
291 * API IMPLEMENTATION
292 ********************************************************************************************************************/
293 #ifdef XMC_ASSERT_ENABLE
294 /* API to verify SCU event weather it is valid event or not */
XMC_SCU_INTERRUPT_IsValidEvent(XMC_SCU_INTERRUPT_EVENT_t event)295 __STATIC_INLINE bool XMC_SCU_INTERRUPT_IsValidEvent(XMC_SCU_INTERRUPT_EVENT_t event)
296 {
297 return ((event == XMC_SCU_INTERRUPT_EVENT_WDT_WARN) ||
298 (event == XMC_SCU_INTERRUPT_EVENT_RTC_PERIODIC) ||
299 (event == XMC_SCU_INTERRUPT_EVENT_RTC_ALARM) ||
300 (event == XMC_SCU_INTERRUPT_EVENT_VDDPI) ||
301 #if defined(USIC1)
302 (event == XMC_SCU_INTERRUPT_EVENT_PEUSIC1) ||
303 #endif
304 #if defined(CAN)
305 (event == XMC_SCU_INTERRUPT_EVENT_PEMCAN) ||
306 #endif
307 #if UC_SERIES == XMC14
308 (event == XMC_SCU_INTERRUPT_EVENT_LOSS_EXT_CLOCK) ||
309 (event == XMC_SCU_INTERRUPT_EVENT_DCO1_OUT_SYNC) ||
310 #endif
311 #if defined(COMPARATOR)
312 (event == XMC_SCU_INTERRUPT_EVENT_ACMP0) ||
313 (event == XMC_SCU_INTERRUPT_EVENT_ACMP1) ||
314 (event == XMC_SCU_INTERRUPT_EVENT_ACMP2) ||
315 #if UC_SERIES == XMC14
316 (event == XMC_SCU_INTERRUPT_EVENT_ACMP3) ||
317 #endif
318 #endif
319 (event == XMC_SCU_INTERRUPT_EVENT_VDROP) ||
320 #if UC_SERIES != XMC11
321 (event == XMC_SCU_INTERRUPT_EVENT_ORC0) ||
322 (event == XMC_SCU_INTERRUPT_EVENT_ORC1) ||
323 (event == XMC_SCU_INTERRUPT_EVENT_ORC2) ||
324 (event == XMC_SCU_INTERRUPT_EVENT_ORC3) ||
325 (event == XMC_SCU_INTERRUPT_EVENT_ORC4) ||
326 (event == XMC_SCU_INTERRUPT_EVENT_ORC5) ||
327 (event == XMC_SCU_INTERRUPT_EVENT_ORC6) ||
328 (event == XMC_SCU_INTERRUPT_EVENT_ORC7) ||
329 #endif
330 (event == XMC_SCU_INTERRUPT_EVENT_LOCI) ||
331 (event == XMC_SCU_INTERRUPT_EVENT_PESRAM) ||
332 (event == XMC_SCU_INTERRUPT_EVENT_PEUSIC0) ||
333 (event == XMC_SCU_INTERRUPT_EVENT_FLASH_ERROR) ||
334 (event == XMC_SCU_INTERRUPT_EVENT_FLASH_COMPLETED) ||
335 (event == XMC_SCU_INTERRUPT_EVENT_VCLIP) ||
336 (event == XMC_SCU_INTERRUPT_EVENT_STDBYCLKFAIL) ||
337 (event == XMC_SCU_INTERRUPT_EVENT_RTCCTR_UPDATED) ||
338 (event == XMC_SCU_INTERRUPT_EVENT_RTCATIM0_UPDATED) ||
339 (event == XMC_SCU_INTERRUPT_EVENT_RTCATIM1_UPDATED) ||
340 (event == XMC_SCU_INTERRUPT_EVENT_RTCTIM0_UPDATED) ||
341 (event == XMC_SCU_INTERRUPT_EVENT_RTCTIM1_UPDATED) ||
342 (event == XMC_SCU_INTERRUPT_EVENT_TSE_DONE) ||
343 (event == XMC_SCU_INTERRUPT_EVENT_TSE_HIGH) ||
344 (event == XMC_SCU_INTERRUPT_EVENT_TSE_LOW));
345 }
346 #endif
347
348 /* API to enable the SCU event */
XMC_SCU_INTERRUPT_EnableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)349 void XMC_SCU_INTERRUPT_EnableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
350 {
351 SCU_INTERRUPT->SRMSK |= (uint32_t)event;
352 #if UC_SERIES == XMC14
353 SCU_INTERRUPT->SRMSK1 |= (uint32_t)(event >> 32U);
354 #endif
355 }
356
357 /* API to disable the SCU event */
XMC_SCU_INTERRUPT_DisableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)358 void XMC_SCU_INTERRUPT_DisableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
359 {
360 SCU_INTERRUPT->SRMSK &= ~(uint32_t)event;
361 #if UC_SERIES == XMC14
362 SCU_INTERRUPT->SRMSK1 &= (uint32_t)~(event >> 32U);
363 #endif
364 }
365
366 /* API to trigger the SCU event */
XMC_SCU_INTERRUPT_TriggerEvent(const XMC_SCU_INTERRUPT_EVENT_t event)367 void XMC_SCU_INTERRUPT_TriggerEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
368 {
369 SCU_INTERRUPT->SRSET |= (uint32_t)event;
370 #if UC_SERIES == XMC14
371 SCU_INTERRUPT->SRSET1 |= (uint32_t)(event >> 32U);
372 #endif
373 }
374
375 /* API to get the SCU event status */
XMC_SCU_INTERUPT_GetEventStatus(void)376 XMC_SCU_INTERRUPT_EVENT_t XMC_SCU_INTERUPT_GetEventStatus(void)
377 {
378 XMC_SCU_INTERRUPT_EVENT_t tmp;
379
380 tmp = SCU_INTERRUPT->SRRAW;
381 #if UC_SERIES == XMC14
382 tmp |= ((int64_t)SCU_INTERRUPT->SRRAW1 << 32U);
383 #endif
384 return (tmp);
385 }
386
387 /* API to clear the SCU event status */
XMC_SCU_INTERRUPT_ClearEventStatus(const XMC_SCU_INTERRUPT_EVENT_t event)388 void XMC_SCU_INTERRUPT_ClearEventStatus(const XMC_SCU_INTERRUPT_EVENT_t event)
389 {
390 SCU_INTERRUPT->SRCLR |= (uint32_t)event;
391 #if UC_SERIES == XMC14
392 SCU_INTERRUPT->SRCLR1 |= (uint32_t)(event >> 32U);
393 #endif
394 }
395
396 /* API to lock protected bitfields from being modified */
XMC_SCU_LockProtectedBits(void)397 void XMC_SCU_LockProtectedBits(void)
398 {
399 SCU_GENERAL->PASSWD = SCU_GCU_PASSWD_PROT_ENABLE;
400 }
401
402 /* API to make protected bitfields available for modification */
XMC_SCU_UnlockProtectedBits(void)403 void XMC_SCU_UnlockProtectedBits(void)
404 {
405 SCU_GENERAL->PASSWD = SCU_GCU_PASSWD_PROT_DISABLE;
406
407 while(((SCU_GENERAL->PASSWD) & SCU_GENERAL_PASSWD_PROTS_Msk))
408 {
409 /* Loop until the lock is removed */
410 }
411 }
412
413 /* API to initialize power supply monitoring unit */
XMC_SCU_SupplyMonitorInit(const XMC_SCU_SUPPLYMONITOR_t * obj)414 void XMC_SCU_SupplyMonitorInit(const XMC_SCU_SUPPLYMONITOR_t *obj)
415 {
416 uint32_t anavdel;
417 uint32_t irqmask;
418
419 anavdel = 0UL;
420
421 anavdel |= (uint32_t)((obj-> ext_supply_threshold) << SCU_ANALOG_ANAVDEL_VDEL_SELECT_Pos);
422 anavdel |= (uint32_t)((obj->ext_supply_monitor_speed) << SCU_ANALOG_ANAVDEL_VDEL_TIM_ADJ_Pos);
423
424 if(true == (obj->enable_at_init))
425 {
426 anavdel |= (uint32_t)SCU_ANALOG_ANAVDEL_VDEL_EN_Msk;
427 }
428 SCU_ANALOG->ANAVDEL = (uint16_t) anavdel;
429
430 irqmask = 0UL;
431
432 if(true == (obj->enable_prewarning_int))
433 {
434 irqmask |= (uint32_t)SCU_INTERRUPT_SRMSK_VDDPI_Msk;
435 }
436
437 if(true == (obj->enable_vdrop_int))
438 {
439 irqmask |= (uint32_t)SCU_INTERRUPT_SRMSK_VDROPI_Msk;
440 }
441
442 if(true == (obj->enable_vclip_int))
443 {
444 irqmask |= (uint32_t)SCU_INTERRUPT_SRMSK_VCLIPI_Msk;
445 }
446 SCU_INTERRUPT->SRMSK |= (uint32_t)irqmask;
447 }
448
449 /* API to program lower temperature limit */
XMC_SCU_SetTempLowLimit(uint32_t limit)450 XMC_SCU_STATUS_t XMC_SCU_SetTempLowLimit(uint32_t limit)
451 {
452 XMC_SCU_STATUS_t status = XMC_SCU_STATUS_OK;
453
454 limit = XMC_SCU_CalcTSEVAR(limit);
455
456 if (limit != 0)
457 {
458 SCU_ANALOG->ANATSEIL = (uint16_t)limit;
459 }
460 else
461 {
462 status = XMC_SCU_STATUS_ERROR;
463 }
464
465 return (status);
466 }
467
468 /* API to program higher temperature limit */
XMC_SCU_SetTempHighLimit(uint32_t limit)469 XMC_SCU_STATUS_t XMC_SCU_SetTempHighLimit(uint32_t limit)
470 {
471 XMC_SCU_STATUS_t status = XMC_SCU_STATUS_OK;
472
473 limit = XMC_SCU_CalcTSEVAR(limit);
474
475 if (limit != 0)
476 {
477 SCU_ANALOG->ANATSEIH = (uint16_t)limit;
478 }
479 else
480 {
481 status = XMC_SCU_STATUS_ERROR;
482 }
483
484 return (status);
485 }
486
487 /* API to program temperature limits as raw digital values into temperature sensor */
XMC_SCU_SetRawTempLimits(const uint32_t lower_temp,const uint32_t upper_temp)488 void XMC_SCU_SetRawTempLimits(const uint32_t lower_temp, const uint32_t upper_temp)
489 {
490 SCU_ANALOG->ANATSEIH = (uint16_t)(upper_temp & SCU_ANALOG_ANATSEIH_TSE_IH_Msk);
491 SCU_ANALOG->ANATSEIL = (uint16_t)(lower_temp & SCU_ANALOG_ANATSEIL_TSE_IL_Msk);
492 }
493
494 /* API to start temperature measurement */
XMC_SCU_StartTempMeasurement(void)495 void XMC_SCU_StartTempMeasurement(void)
496 {
497 SCU_ANALOG->ANATSECTRL |= (uint16_t)SCU_ANALOG_ANATSECTRL_TSE_EN_Msk;
498 }
499
500 /* API to stop temperature measurement */
XMC_SCU_StopTempMeasurement(void)501 void XMC_SCU_StopTempMeasurement(void)
502 {
503 SCU_ANALOG->ANATSECTRL &= (uint16_t)~SCU_ANALOG_ANATSECTRL_TSE_EN_Msk;
504 }
505
506 /* API to check if the temperature has gone past the ceiling */
XMC_SCU_HighTemperature(void)507 bool XMC_SCU_HighTemperature(void)
508 {
509 return ((SCU_INTERRUPT->SRRAW & SCU_INTERRUPT_SRRAW_TSE_HIGH_Msk) == SCU_INTERRUPT_SRRAW_TSE_HIGH_Msk);
510 }
511
512 /* API to check if the temperature is lower than normal */
XMC_SCU_LowTemperature(void)513 bool XMC_SCU_LowTemperature(void)
514 {
515 return ((SCU_INTERRUPT->SRRAW & SCU_INTERRUPT_SRRAW_TSE_LOW_Msk) == SCU_INTERRUPT_SRRAW_TSE_LOW_Msk);
516 }
517
518 /* API to retrieve the device temperature */
XMC_SCU_GetTemperature(void)519 uint32_t XMC_SCU_GetTemperature(void)
520 {
521 uint32_t temperature;
522
523 temperature = (uint32_t)(SCU_ANALOG->ANATSEMON);
524
525 return (temperature);
526 }
527
528 /* Calculates the die temperature value using ROM function */
XMC_SCU_CalcTemperature(void)529 uint32_t XMC_SCU_CalcTemperature(void)
530 {
531 return (ROM_CalcTemperature());
532 }
533
534
535 /* API which initializes the clock tree ofthe device */
XMC_SCU_CLOCK_Init(const XMC_SCU_CLOCK_CONFIG_t * const config)536 void XMC_SCU_CLOCK_Init(const XMC_SCU_CLOCK_CONFIG_t *const config)
537 {
538 /* Remove protection */
539 XMC_SCU_UnlockProtectedBits();
540
541 #if (UC_SERIES == XMC14)
542 /* OSCHP source selection - OSC mode */
543
544 if (config->oschp_mode != XMC_SCU_CLOCK_OSCHP_MODE_DISABLED)
545 {
546 if (OSCHP_GetFrequency() > 20000000U)
547 {
548 SCU_ANALOG->ANAOSCHPCTRL |= (uint16_t)SCU_ANALOG_ANAOSCHPCTRL_HYSCTRL_Msk;
549 }
550
551 SCU_ANALOG->ANAOSCHPCTRL = (uint16_t)(SCU_ANALOG->ANAOSCHPCTRL & ~(SCU_ANALOG_ANAOSCHPCTRL_SHBY_Msk | SCU_ANALOG_ANAOSCHPCTRL_MODE_Msk)) |
552 config->oschp_mode;
553
554 do
555 {
556 /* clear the status bit before restarting the detection. */
557 SCU_INTERRUPT->SRCLR1 = SCU_INTERRUPT_SRCLR1_LOECI_Msk;
558
559 /* According to errata SCU_CM.023, to reset the XOWD it is needed to disable/enable the watchdog,
560 keeping in between at least one DCO2 cycle */
561
562 /* Disable XOWD */
563 SCU_CLK->OSCCSR &= ~SCU_CLK_OSCCSR_XOWDEN_Msk;
564
565 /* Clock domains synchronization, at least 1 DCO2 cycle */
566 /* delay value calculation assuming worst case DCO1=48Mhz and 3cycles per delay iteration */
567 delay(538);
568
569 /* Enable XOWD */
570 SCU_CLK->OSCCSR |= SCU_CLK_OSCCSR_XOWDEN_Msk | SCU_CLK_OSCCSR_XOWDRES_Msk;
571
572 /* OSCCSR.XOWDRES bit will be automatically reset to 0 after XOWD is reset */
573 while (SCU_CLK->OSCCSR & SCU_CLK_OSCCSR_XOWDRES_Msk);
574
575 /* Wait a at least 5 DCO2 cycles for the update of the XTAL OWD result */
576 /* delay value calculation assuming worst case DCO1=48Mhz and 3cycles per delay iteration */
577 delay(2685);
578
579 } while (SCU_INTERRUPT->SRRAW1 & SCU_INTERRUPT_SRRAW1_LOECI_Msk);
580 }
581 else /* (config->oschp_mode == XMC_SCU_CLOCK_OSCHP_MODE_DISABLED) */
582 {
583 SCU_ANALOG->ANAOSCHPCTRL |= SCU_ANALOG_ANAOSCHPCTRL_MODE_Msk;
584 }
585
586 SCU_ANALOG->ANAOSCLPCTRL = (uint16_t)config->osclp_mode;
587 #ifndef DISABLE_WAIT_RTC_XTAL_OSC_STARTUP
588 if (config->osclp_mode == XMC_SCU_CLOCK_OSCLP_MODE_OSC)
589 {
590 /* Wait oscillator startup time ~5s */
591 delay(6500000);
592 }
593 #endif
594
595 SCU_CLK->CLKCR1 = (SCU_CLK->CLKCR1 & ~SCU_CLK_CLKCR1_DCLKSEL_Msk) |
596 config->dclk_src;
597
598 #endif
599 /* Update PCLK selection mux. */
600 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_PCLKSEL_Msk | SCU_CLK_CLKCR_RTCCLKSEL_Msk)) |
601 config->rtc_src |
602 config->pclk_src;
603
604 /* Close the lock opened above. */
605 XMC_SCU_LockProtectedBits();
606
607 /* Update the dividers now */
608 XMC_SCU_CLOCK_ScaleMCLKFrequency(config->idiv, config->fdiv);
609
610 }
611
612 /* API which selects one of the available parent clock nodes for a given child clock node */
XMC_SCU_CLOCK_SetRtcClockSource(const XMC_SCU_CLOCK_RTCCLKSRC_t source)613 void XMC_SCU_CLOCK_SetRtcClockSource(const XMC_SCU_CLOCK_RTCCLKSRC_t source)
614 {
615 XMC_ASSERT("XMC_SCU_CLOCK_SetRtcSourceClock:Wrong Parent Clock", XMC_SCU_CHECK_RTCCLKSRC(source));
616
617 XMC_SCU_UnlockProtectedBits();
618
619 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~SCU_CLK_CLKCR_RTCCLKSEL_Msk) |
620 source;
621
622 XMC_SCU_LockProtectedBits();
623 }
624
625 /* API to program the divider placed between fperiph and its parent */
XMC_SCU_CLOCK_SetFastPeripheralClockSource(const XMC_SCU_CLOCK_PCLKSRC_t source)626 void XMC_SCU_CLOCK_SetFastPeripheralClockSource(const XMC_SCU_CLOCK_PCLKSRC_t source)
627 {
628 XMC_SCU_UnlockProtectedBits();
629
630 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~SCU_CLK_CLKCR_PCLKSEL_Msk) |
631 source;
632
633 XMC_SCU_LockProtectedBits();
634 }
635
636 /* API which gates a clock node at its source */
XMC_SCU_CLOCK_GatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)637 void XMC_SCU_CLOCK_GatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
638 {
639 XMC_SCU_UnlockProtectedBits();
640 SCU_CLK->CGATSET0 |= (uint32_t)peripheral;
641 XMC_SCU_LockProtectedBits();
642 }
643
644 /* API which ungates a clock note at its source */
XMC_SCU_CLOCK_UngatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)645 void XMC_SCU_CLOCK_UngatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
646 {
647 XMC_SCU_UnlockProtectedBits();
648 SCU_CLK->CGATCLR0 |= (uint32_t)peripheral;
649 while ((SCU_CLK->CLKCR) & SCU_CLK_CLKCR_VDDC2LOW_Msk)
650 {
651 /* Wait voltage suply stabilization */
652 }
653 XMC_SCU_LockProtectedBits();
654 }
655
656 /* Checks the status of peripheral clock gating */
XMC_SCU_CLOCK_IsPeripheralClockGated(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)657 bool XMC_SCU_CLOCK_IsPeripheralClockGated(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
658 {
659 return (bool)((SCU_CLK->CGATSTAT0 & peripheral) != 0);
660 }
661
662 /* This API configures main clock (MCLK) frequency to requested frequency value. */
XMC_SCU_CLOCK_SetMCLKFrequency(uint32_t freq_khz)663 void XMC_SCU_CLOCK_SetMCLKFrequency(uint32_t freq_khz)
664 {
665 uint32_t ratio;
666 uint32_t ratio_int;
667 uint32_t ratio_frac;
668
669 #if UC_SERIES == XMC14
670 if (((SCU_CLK->CLKCR1) & SCU_CLK_CLKCR1_DCLKSEL_Msk) == 0U)
671 {
672 ratio = DCO1_DIV2_FREQUENCY_KHZ_Q22_10 / freq_khz;
673 }
674 else
675 {
676 ratio = ((OSCHP_GetFrequency() / 1000U) << 10U) / freq_khz;
677 }
678
679 /* Manage overflow */
680 if (ratio > 0xffffffU)
681 {
682 ratio = 0xffffffU;
683 }
684
685 ratio_int = ratio >> 10U;
686 ratio_frac = ratio & 0x3ffU;
687 #else
688 ratio = DCO1_DIV2_FREQUENCY_KHZ_Q24_8 / freq_khz;
689
690 /* Manage overflow */
691 if (ratio > 0xffffU)
692 {
693 ratio = 0xffffU;
694 }
695
696 ratio_int = ratio >> 8U;
697 ratio_frac = ratio & 0xffU;
698 #endif
699
700 XMC_SCU_CLOCK_ScaleMCLKFrequency(ratio_int, ratio_frac);
701 }
702
703
704 /* A utility routine which updates the fractional dividers in steps */
XMC_SCU_CLOCK_ScaleMCLKFrequency(uint32_t idiv,uint32_t fdiv)705 void XMC_SCU_CLOCK_ScaleMCLKFrequency(uint32_t idiv, uint32_t fdiv)
706 {
707 /* Find out current and target value of idiv */
708 uint32_t curr_idiv;
709
710 XMC_SCU_UnlockProtectedBits();
711
712 /* Take a snapshot of value already programmed into IDIV */
713 curr_idiv = (SCU_CLK->CLKCR & SCU_CLK_CLKCR_IDIV_Msk) >> SCU_CLK_CLKCR_IDIV_Pos;
714
715 #if (UC_SERIES == XMC14)
716 SCU_CLK->CLKCR1 = (SCU_CLK->CLKCR1 & (uint32_t)~(SCU_CLK_CLKCR1_FDIV_Msk)) |
717 (uint32_t)((fdiv >> 8U) << SCU_CLK_CLKCR1_FDIV_Pos);
718
719 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_FDIV_Msk | SCU_CLK_CLKCR_CNTADJ_Msk)) |
720 (uint32_t)((fdiv & 0xffU) << SCU_CLK_CLKCR_FDIV_Pos) |
721 (uint32_t)(1023UL << SCU_CLK_CLKCR_CNTADJ_Pos);
722 #else
723 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_FDIV_Msk | SCU_CLK_CLKCR_CNTADJ_Msk)) |
724 (uint32_t)(fdiv << SCU_CLK_CLKCR_FDIV_Pos) |
725 (uint32_t)(1023UL << SCU_CLK_CLKCR_CNTADJ_Pos);
726 #endif
727
728 while ((SCU_CLK->CLKCR)& SCU_CLK_CLKCR_VDDC2LOW_Msk)
729 {
730 /* Spin until the core supply stabilizes */
731 }
732
733 if(curr_idiv <= idiv)
734 {
735 /* Requested IDIV is greater than currently programmed IDIV. So downscale the frequency */
736 XMC_SCU_CLOCK_lFrequencyDownScaling(curr_idiv, idiv);
737 }
738 else
739 {
740 /* Requested IDIV is lower than currently programmed IDIV. So upscale the frequency */
741 XMC_SCU_CLOCK_lFrequencyUpScaling(curr_idiv, idiv);
742 }
743
744 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_IDIV_Msk | SCU_CLK_CLKCR_CNTADJ_Msk)) |
745 (uint32_t)(idiv << SCU_CLK_CLKCR_IDIV_Pos) | (uint32_t)(1023UL << SCU_CLK_CLKCR_CNTADJ_Pos);
746
747 while ((SCU_CLK->CLKCR) & SCU_CLK_CLKCR_VDDC2LOW_Msk)
748 {
749 /* Wait voltage suply stabilization */
750 }
751
752 XMC_SCU_LockProtectedBits();
753
754 SystemCoreClockUpdate();
755
756 }
757
758 /* Utility routine to perform frequency up scaling */
XMC_SCU_CLOCK_lFrequencyUpScaling(uint32_t curr_idiv,uint32_t target_idiv)759 static void XMC_SCU_CLOCK_lFrequencyUpScaling(uint32_t curr_idiv, uint32_t target_idiv)
760 {
761 while (curr_idiv > (target_idiv * 4UL))
762 {
763 curr_idiv = (uint32_t)(curr_idiv >> 2UL); /* Divide by 4. */
764
765 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_IDIV_Msk | SCU_CLK_CLKCR_CNTADJ_Msk)) |
766 (uint32_t)(curr_idiv << SCU_CLK_CLKCR_IDIV_Pos) |
767 (uint32_t)(1023UL << SCU_CLK_CLKCR_CNTADJ_Pos);
768
769 while (SCU_CLK->CLKCR & SCU_CLK_CLKCR_VDDC2LOW_Msk)
770 {
771 /* Wait voltage suply stabilization */
772 }
773 }
774 }
775
776 /* Utility routine to perform frequency down scaling */
XMC_SCU_CLOCK_lFrequencyDownScaling(uint32_t curr_idiv,uint32_t target_idiv)777 static void XMC_SCU_CLOCK_lFrequencyDownScaling(uint32_t curr_idiv, uint32_t target_idiv)
778 {
779
780 while ((curr_idiv * 4UL) < target_idiv)
781 {
782 if(0U == curr_idiv)
783 {
784 curr_idiv = 1U;
785 }
786 curr_idiv = (uint32_t)(curr_idiv << 2UL); /* Multiply by 4. */
787 SCU_CLK->CLKCR = (SCU_CLK->CLKCR & (uint32_t)~(SCU_CLK_CLKCR_IDIV_Msk | SCU_CLK_CLKCR_CNTADJ_Msk)) |
788 (uint32_t)(curr_idiv << SCU_CLK_CLKCR_IDIV_Pos) |
789 (uint32_t)(1023UL << SCU_CLK_CLKCR_CNTADJ_Pos);
790
791 while (SCU_CLK->CLKCR & SCU_CLK_CLKCR_VDDC2LOW_Msk)
792 {
793 /* Wait voltage suply stabilization */
794 }
795 }
796 }
797
798 /*
799 * API to retrieve clock frequency of peripherals on the peripheral bus using a shared functional clock
800 */
XMC_SCU_CLOCK_GetPeripheralClockFrequency(void)801 uint32_t XMC_SCU_CLOCK_GetPeripheralClockFrequency(void)
802 {
803 return (SystemCoreClock);
804 }
805
806 /* Provides the clock frequency of peripherals on the peripheral bus that are using a shared functional clock */
XMC_SCU_CLOCK_GetFastPeripheralClockFrequency(void)807 uint32_t XMC_SCU_CLOCK_GetFastPeripheralClockFrequency(void)
808 {
809 return (SystemCoreClock << ((SCU_CLK->CLKCR & SCU_CLK_CLKCR_PCLKSEL_Msk) >> SCU_CLK_CLKCR_PCLKSEL_Pos));
810 }
811
812 /* DCO1 clock frequency can be calibrated during runtime to achieve a better accuracy */
XMC_SCU_CLOCK_CalibrateOscillatorOnTemperature(int32_t temperature)813 void XMC_SCU_CLOCK_CalibrateOscillatorOnTemperature(int32_t temperature)
814 {
815 int32_t a;
816 int32_t b;
817 int32_t d;
818 int32_t e;
819 int32_t offset;
820
821 a = *((uint8_t*)DCO_ADJLO_T2);
822 b = *((uint8_t*)DCO_ADJLO_T1);
823 d = *((uint8_t*)ANA_TSE_T1);
824 e = *((uint8_t*)ANA_TSE_T2);
825
826 offset = b + (((a - b) * (temperature - d)) / (e - d));
827 offset &= SCU_ANALOG_ANAOFFSET_ADJL_OFFSET_Msk;
828
829 XMC_SCU_UnlockProtectedBits();
830 SCU_ANALOG->ANAOFFSET = (uint16_t)offset;
831 XMC_SCU_LockProtectedBits();
832 }
833
834 /*
835 * API to assign the event handler function to be executed on occurrence of the selected event
836 */
XMC_SCU_INTERRUPT_SetEventHandler(XMC_SCU_INTERRUPT_EVENT_t event,XMC_SCU_INTERRUPT_EVENT_HANDLER_t handler)837 XMC_SCU_STATUS_t XMC_SCU_INTERRUPT_SetEventHandler(XMC_SCU_INTERRUPT_EVENT_t event, XMC_SCU_INTERRUPT_EVENT_HANDLER_t handler)
838 {
839 uint32_t index;
840 XMC_SCU_STATUS_t status;
841
842 XMC_ASSERT("XMC_SCU_INTERRUPT_SetEventHandler: Invalid event", XMC_SCU_INTERRUPT_IsValidEvent(event));
843 XMC_ASSERT("XMC_SCU_INTERRUPT_SetEventHandler: Invalid handler", handler != NULL);
844
845 index = 0U;
846
847 while (((event & ((XMC_SCU_INTERRUPT_EVENT_t)1 << index)) == 0U) && (index < XMC_SCU_INTERRUPT_EVENT_MAX))
848 {
849 index++;
850 }
851
852 if (index == XMC_SCU_INTERRUPT_EVENT_MAX)
853 {
854 status = XMC_SCU_STATUS_ERROR;
855 }
856 else
857 {
858 event_handler_list[index] = handler;
859 status = XMC_SCU_STATUS_OK;
860 }
861
862 return (status);
863 }
864
865 /*
866 * A common function to execute callback functions for multiple events
867 */
XMC_SCU_IRQHandler(uint32_t sr_num)868 void XMC_SCU_IRQHandler(uint32_t sr_num)
869 {
870 XMC_ASSERT("XMC_SCU_IRQHandler: Invalid sr_num", sr_num < SCU_IRQ_NUM);
871
872 uint32_t index;
873 XMC_SCU_INTERRUPT_EVENT_t event;
874 XMC_SCU_INTERRUPT_EVENT_HANDLER_t event_handler;
875
876 index = 0U;
877 event = XMC_SCU_INTERUPT_GetEventStatus() & event_masks[sr_num];
878 XMC_SCU_INTERRUPT_ClearEventStatus(event);
879
880 while ((event != 0) && (index < XMC_SCU_INTERRUPT_EVENT_MAX))
881 {
882 if ((event & ((XMC_SCU_INTERRUPT_EVENT_t)1 << index)) != 0U)
883 {
884 event &= ~((XMC_SCU_INTERRUPT_EVENT_t)1 << index);
885 event_handler = event_handler_list[index];
886 if (event_handler != NULL)
887 {
888 event_handler();
889 }
890
891 /* break; XMC1: Only PULSE interrupts */
892 }
893 index++;
894 }
895 }
896
897 /* Install BMI */
XMC_SCU_SetBMI(uint32_t flags,uint8_t timeout)898 uint32_t XMC_SCU_SetBMI(uint32_t flags, uint8_t timeout)
899 {
900 #if (UC_SERIES == XMC14)
901 return ROM_BmiInstallationReq((flags & 0x0fffU) | ((timeout << 12) & 0xf000U));
902 #else
903 return ROM_BmiInstallationReq((flags & 0x07ffU) | ((timeout << 12) & 0xf000U) | 0x08c0U);
904 #endif
905 }
906
907 #if (UC_SERIES == XMC14)
908 /* DCO1 clock frequency can be calibrated during runtime to achieve a better accuracy */
XMC_SCU_CLOCK_EnableDCO1ExtRefCalibration(XMC_SCU_CLOCK_SYNC_CLKSRC_t sync_clk,uint32_t prescaler,uint32_t syn_preload)909 void XMC_SCU_CLOCK_EnableDCO1ExtRefCalibration(XMC_SCU_CLOCK_SYNC_CLKSRC_t sync_clk, uint32_t prescaler, uint32_t syn_preload)
910 {
911
912 XMC_SCU_UnlockProtectedBits();
913 SCU_ANALOG->ANASYNC2 = (uint16_t)(prescaler << SCU_ANALOG_ANASYNC2_PRESCALER_Pos);
914 SCU_ANALOG->ANASYNC1 = (uint16_t)(syn_preload |
915 sync_clk |
916 SCU_ANALOG_ANASYNC1_SYNC_DCO_EN_Msk);
917
918 XMC_SCU_LockProtectedBits();
919
920 }
921
922 /* This function stops the automatic DCO1 calibration based on the selected clock source */
XMC_SCU_CLOCK_DisableDCO1ExtRefCalibration(void)923 void XMC_SCU_CLOCK_DisableDCO1ExtRefCalibration(void)
924 {
925 XMC_SCU_UnlockProtectedBits();
926 SCU_ANALOG->ANASYNC2 = 0U;
927 SCU_ANALOG->ANASYNC1 = 0U;
928 XMC_SCU_LockProtectedBits();
929 }
930
931 /* This functions checks the status of the synchronisation */
XMC_SCU_CLOCK_IsDCO1ExtRefCalibrationReady(void)932 bool XMC_SCU_CLOCK_IsDCO1ExtRefCalibrationReady(void)
933 {
934 return (bool)((SCU_ANALOG->ANASYNC2 & SCU_ANALOG_ANASYNC2_SYNC_READY_Msk) != 0U);
935 }
936
937 /* This function selects service request source for a NVIC interrupt node */
XMC_SCU_SetInterruptControl(uint8_t irq_number,XMC_SCU_IRQCTRL_t source)938 void XMC_SCU_SetInterruptControl(uint8_t irq_number, XMC_SCU_IRQCTRL_t source)
939 {
940 XMC_ASSERT("XMC_SCU_SetInterruptControl: Invalid irq_number", irq_number < 32);
941 XMC_ASSERT("XMC_SCU_SetInterruptControl: Invalid source", (source >> 8) == irq_number);
942
943 source &= 0x3U;
944 if (irq_number < 16U)
945 {
946 SCU_GENERAL->INTCR0 = (SCU_GENERAL->INTCR0 & ~(SCU_GENERAL_INTCR_INTSEL_Msk << (irq_number * SCU_GENERAL_INTCR_INTSEL_Size))) |
947 (source << (irq_number * SCU_GENERAL_INTCR_INTSEL_Size));
948 }
949 else
950 {
951 irq_number &= 0x0fU;
952 SCU_GENERAL->INTCR1 = (SCU_GENERAL->INTCR1 & ~(SCU_GENERAL_INTCR_INTSEL_Msk << (irq_number * SCU_GENERAL_INTCR_INTSEL_Size))) |
953 (source << (irq_number * SCU_GENERAL_INTCR_INTSEL_Size));
954 }
955 }
956
XMC_SCU_CLOCK_SetHighPerformanceOscillatorMode(XMC_SCU_CLOCK_OSCHP_MODE_t mode)957 void XMC_SCU_CLOCK_SetHighPerformanceOscillatorMode(XMC_SCU_CLOCK_OSCHP_MODE_t mode)
958 {
959 XMC_SCU_UnlockProtectedBits();
960 SCU_ANALOG->ANAOSCHPCTRL = (SCU_ANALOG->ANAOSCHPCTRL & (uint32_t)~(SCU_ANALOG_ANAOSCHPCTRL_MODE_Msk | SCU_ANALOG_ANAOSCHPCTRL_SHBY_Msk))
961 | mode;
962 XMC_SCU_LockProtectedBits();
963 }
964
XMC_SCU_CLOCK_SetLowPerformanceOscillatorMode(XMC_SCU_CLOCK_OSCLP_MODE_t mode)965 void XMC_SCU_CLOCK_SetLowPerformanceOscillatorMode(XMC_SCU_CLOCK_OSCLP_MODE_t mode)
966 {
967 SCU_ANALOG->ANAOSCLPCTRL = mode;
968 }
969
970
971
972 #endif
973 #endif /* UC_FAMILY == XMC1 */
974