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