1 /**
2 * @file xmc4_scu.c
3 * @date 2018-06-21
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_ASSERT() hanging issues have fixed. <br>
44 * - Line indentation aligned with 120 characters. <br>
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 are added
50 * - Added Weak implementation for OSCHP_GetFrequency()
51 *
52 * 2015-11-30:
53 * - Documentation improved <br>
54 * - Following API functionalities are improved
55 * XMC_SCU_CLOCK_GatePeripheralClock, XMC_SCU_CLOCK_UngatePeripheralClock, XMC_SCU_CLOCK_IsPeripheralClockGated
56 * XMC_SCU_RESET_AssertPeripheralReset, XMC_SCU_RESET_DeassertPeripheralReset, XMC_SCU_RESET_IsPeripheralResetAsserted
57 *
58 * 2015-12-08:
59 * - XMC_SCU_GetTemperature renamed to XMC_SCU_GetTemperatureMeasurement
60 *
61 * 2016-03-09:
62 * - Optimize write only registers
63 * - Added XMC_SCU_HIB_SetPinMode
64 * - Added XMC_SCU_HIB_GetHibernateControlStatus,
65 * XMC_SCU_HIB_GetEventStatus, XMC_SCU_HIB_ClearEventStatus, XMC_SCU_HIB_TriggerEvent,
66 * XMC_SCU_HIB_EnableEvent, XMC_SCU_HIB_DisableEvent
67 * - Added XMC_SCU_HIB_SetWakeupTriggerInput, XMC_SCU_HIB_SetPinMode, XMC_SCU_HIB_SetOutputPinLevel,
68 * XMC_SCU_HIB_SetInput0, XMC_SCU_HIB_EnterHibernateState
69 *
70 * 2016-04-06:
71 * - Fixed XMC_SCU_ReadFromRetentionMemory functionality
72 *
73 * 2016-05-19:
74 * - Changed XMC_SCU_CLOCK_StartSystemPll to avoid using floating point calculation which might have an impact on interrupt latency if ISR uses also the FPU
75 * - Added XMC_SCU_CLOCK_IsLowPowerOscillatorStable() and XMC_SCU_CLOCK_IsHighPerformanceOscillatorStable()
76 * - Added XMC_SCU_CLOCK_EnableLowPowerOscillatorGeneralPurposeInput(),
77 * XMC_SCU_CLOCK_DisableLowPowerOscillatorGeneralPurposeInput(),
78 * XMC_SCU_CLOCK_GetLowPowerOscillatorGeneralPurposeInputStatus()
79 * - Added XMC_SCU_CLOCK_EnableHighPerformanceOscillatorGeneralPurposeInput(),
80 * XMC_SCU_CLOCK_DisableHighPerformanceOscillatorGeneralPurposeInput(),
81 * XMC_SCU_CLOCK_GetHighPerformanceOscillatorGeneralPurposeInputStatus()
82 *
83 * 2016-06-15:
84 * - Added XMC_SCU_HIB_EnterHibernateStateEx() which allows to select between external or internal hibernate mode. This last mode only available in XMC44, XMC42 and XMC41 series.
85 * - Extended wakeup hibernate events using LPAC wakeup on events. Only available in XMC44, XMC42 and XMC41 series
86 * - Added LPAC APIs. Only available in XMC44, XMC42 and XMC41 series.
87 *
88 * 2018-06-21:
89 * - Fixed XMC_SCU_HIB_SetSR1Input()
90 * - Fixed XMC_SCU_CLOCK_EnableLowPowerOscillator()
91 *
92 * @endcond
93 *
94 */
95
96 /**
97 *
98 * @brief SCU low level driver API prototype definition for XMC4 family of microcontrollers.
99 *
100 * <b>Detailed description of file:</b> <br>
101 * APIs provided in this file cover the following functional blocks of SCU: <br>
102 * -- GCU (APIs prefixed with XMC_SCU_GEN_) <br>
103 * ------ Temperature Monitoring, Bootmode selection, CCU Start, Comparator configuration etc <br>
104 * -- CCU (APIs prefixed with XMC_SCU_CLOCK_) <br>
105 * ------ Clock sources init, Clock tree init, Clock gating, Sleep Management etc <br>
106 * -- RCU (APIs prefixed with XMC_SCU_RESET_) <br>
107 * ------ Reset Init, Cause, Manual Reset Assert/Deassert <br>
108 * -- INTERRUPT (APIs prefixed with XMC_SCU_INTERRUPT_) <br>
109 * ------ Init, Manual Assert/Deassert, Acknowledge etc <br>
110 * -- PARITY (APIs prefixed with XMC_SCU_PARITY_) <br>
111 * ------ Init, Acknowledge etc <br>
112 * -- HIBERNATION (APIs prefixed with XMC_SCU_HIB_) <br>
113 * ------ Hibernation entry/exit config, entry/wakeup sequences, LPAC configuration etc <br>
114 * -- TRAP (APIs prefixed with XMC_SCU_TRAP_) <br>
115 * ------ Init, Enable/Disable, Acknowledge etc <br>
116 *
117 */
118
119 /*********************************************************************************************************************
120 * HEADER FILES
121 ********************************************************************************************************************/
122 #include <xmc_scu.h>
123
124 #if UC_FAMILY == XMC4
125
126 /*********************************************************************************************************************
127 * MACROS
128 ********************************************************************************************************************/
129 #define FOSCREF (2500000UL) /**< Oscillator reference frequency (fOSCREF) monitored by Oscillator watchdog */
130 #define FREQ_1MHZ (1000000UL) /**< Used during calculation. */
131
132 #ifndef OFI_FREQUENCY
133 #define OFI_FREQUENCY (24000000UL) /**< Fast internal backup clock source. */
134 #endif
135
136 #ifndef OSI_FREQUENCY
137 #define OSI_FREQUENCY (32768UL) /**< Internal slow clock source. */
138 #endif
139
140 #ifndef OSCHP_FREQUENCY
141 #define OSCHP_FREQUENCY (12000000U) /**< External crystal High Precision Oscillator. */
142 #endif
143
144 #define XMC_SCU_PLL_PLLSTAT_OSC_USABLE (SCU_PLL_PLLSTAT_PLLHV_Msk | \
145 SCU_PLL_PLLSTAT_PLLLV_Msk | \
146 SCU_PLL_PLLSTAT_PLLSP_Msk) /**< Used to verify the OSC frequency is
147 usable or not.*/
148
149 #define XMC_SCU_ORC_ADC_START_GROUP (0UL) /**< The ADC group whose channel input is compared by Out of Range
150 Comparator (ORC) to serves the purpose of overvoltage monitoring
151 for analog input pins of the chip and ORC start measurements from
152 this group number. */
153 #define XMC_SCU_ORC_ADC_END_GROUP (1UL) /**< The ADC group whose channel input is compared by Out of Range
154 Comparator (ORC) to serves the purpose of overvoltage monitoring
155 for analog input pins of the chip and ORC end measurements at
156 this group number. */
157 #define XMC_SCU_ORC_START_ADC_CHANNEL (6UL) /**< The ADC channel whose channel input is compared by Out of Range
158 Comparator (ORC) to serves the purpose of overvoltage monitoring
159 for analog input pins of the chip and ORC start measurements from
160 this channel number. */
161 #define XMC_SCU_ORC_END_ADC_CHANNEL (7UL) /**< The ADC channel whose channel input is compared by Out of Range
162 Comparator (ORC) to serves the purpose of overvoltage monitoring
163 for analog input pins of the chip and ORC ends measurements at
164 this channel number. */
165
166 #define XMC_SCU_CHECK_GRPNUM(GROUP_NUM) (((GROUP_NUM) == XMC_SCU_ORC_ADC_START_GROUP) || \
167 ((GROUP_NUM) == XMC_SCU_ORC_ADC_END_GROUP) ) /**< Used to verify whether
168 provided ADC group number lies
169 within specified ADC start and
170 end group number or not. */
171
172 #define XMC_SCU_CHECK_CHNUM(CH_NUM) (((CH_NUM) == XMC_SCU_ORC_START_ADC_CHANNEL) || \
173 ((CH_NUM) == XMC_SCU_ORC_END_ADC_CHANNEL) ) /**< Used to verify whether
174 provided ADC channel number lies
175 within specified ADC start and
176 end channel number or not. */
177
178 #define XMC_SCU_INTERRUPT_EVENT_MAX (32U) /**< Maximum supported SCU events. */
179
180 #define SCU_HIBERNATE_HDCR_HIBIOSEL_Size (4U)
181
182 #define SCU_HIBERNATE_OSCULCTRL_MODE_OSC_POWER_DOWN (0x2U)
183
184 #define XMC_SCU_POWER_LSB13V (0.0058F)
185 #define XMC_SCU_POWER_LSB33V (0.0225F)
186
187 /*********************************************************************************************************************
188 * LOCAL DATA
189 ********************************************************************************************************************/
190 XMC_SCU_INTERRUPT_EVENT_HANDLER_t event_handler_list[XMC_SCU_INTERRUPT_EVENT_MAX]; /**< For registering callback
191 functions on SCU event
192 occurrence. */
193
194 /*********************************************************************************************************************
195 * LOCAL ROUTINES
196 ********************************************************************************************************************/
197 #if defined(UC_ID)
198 /* This is a non-weak function, which retrieves high precision external oscillator frequency. */
OSCHP_GetFrequency(void)199 __WEAK uint32_t OSCHP_GetFrequency(void)
200 {
201 return (OSCHP_FREQUENCY);
202 }
203 #endif
204
205 /* This is a local function used to generate the delay until register get updated with new configured value. */
206 static void XMC_SCU_lDelay(uint32_t cycles);
207
208 /*********************************************************************************************************************
209 * API IMPLEMENTATION
210 ********************************************************************************************************************/
211 /* This is a local function used to generate the delay until register get updated with new configured value. */
XMC_SCU_lDelay(uint32_t delay)212 void XMC_SCU_lDelay(uint32_t delay)
213 {
214 uint32_t i;
215
216 SystemCoreClockUpdate();
217 delay = delay * (uint32_t)(SystemCoreClock / FREQ_1MHZ);
218
219 for (i = 0U; i < delay; ++i)
220 {
221 __NOP();
222 }
223 }
224
225 /* API to enable the SCU event */
XMC_SCU_INTERRUPT_EnableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)226 void XMC_SCU_INTERRUPT_EnableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
227 {
228 SCU_INTERRUPT->SRMSK |= (uint32_t)event;
229 }
230
231 /* API to disable the SCU event */
XMC_SCU_INTERRUPT_DisableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)232 void XMC_SCU_INTERRUPT_DisableEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
233 {
234 SCU_INTERRUPT->SRMSK &= (uint32_t)~event;
235 }
236
237 /* API to trigger the SCU event */
XMC_SCU_INTERRUPT_TriggerEvent(const XMC_SCU_INTERRUPT_EVENT_t event)238 void XMC_SCU_INTERRUPT_TriggerEvent(const XMC_SCU_INTERRUPT_EVENT_t event)
239 {
240 SCU_INTERRUPT->SRSET |= (uint32_t)event;
241 }
242
243 /* API to retrieve the SCU event status */
XMC_SCU_INTERUPT_GetEventStatus(void)244 XMC_SCU_INTERRUPT_EVENT_t XMC_SCU_INTERUPT_GetEventStatus(void)
245 {
246 return (SCU_INTERRUPT->SRRAW);
247 }
248
249 /* API to clear the SCU event status */
XMC_SCU_INTERRUPT_ClearEventStatus(const XMC_SCU_INTERRUPT_EVENT_t event)250 void XMC_SCU_INTERRUPT_ClearEventStatus(const XMC_SCU_INTERRUPT_EVENT_t event)
251 {
252 SCU_INTERRUPT->SRCLR = (uint32_t)event;
253 }
254
255
256 /* API to retrieve the currently deployed device bootmode */
XMC_SCU_GetBootMode(void)257 uint32_t XMC_SCU_GetBootMode(void)
258 {
259 return (uint32_t)(SCU_GENERAL->STCON & SCU_GENERAL_STCON_SWCON_Msk);
260 }
261
262 /* API to program a new device bootmode */
XMC_SCU_SetBootMode(const XMC_SCU_BOOTMODE_t bootmode)263 void XMC_SCU_SetBootMode(const XMC_SCU_BOOTMODE_t bootmode)
264 {
265 SCU_GENERAL->STCON = (uint32_t)bootmode;
266 }
267
268 /* API to read from General purpose register */
XMC_SCU_ReadGPR(const uint32_t index)269 uint32_t XMC_SCU_ReadGPR(const uint32_t index)
270 {
271 return (SCU_GENERAL->GPR[index]);
272 }
273
274 /* API to write to GPR */
XMC_SCU_WriteGPR(const uint32_t index,const uint32_t data)275 void XMC_SCU_WriteGPR(const uint32_t index, const uint32_t data)
276 {
277 SCU_GENERAL->GPR[index] = data;
278 }
279
280 /* API to enable Out of Range Comparator(ORC) for a desired group and a desired channel input */
XMC_SCU_EnableOutOfRangeComparator(const uint32_t group,const uint32_t channel)281 void XMC_SCU_EnableOutOfRangeComparator(const uint32_t group, const uint32_t channel)
282 {
283 XMC_ASSERT("XMC_SCU_EnableOutOfangeComparator:Wrong Group Number",XMC_SCU_CHECK_GRPNUM(group));
284 XMC_ASSERT("XMC_SCU_EnableOutOfangeComparator:Wrong Channel Number",XMC_SCU_CHECK_CHNUM(channel));
285
286 SCU_GENERAL->GORCEN[group] |= (uint32_t)(1UL << channel);
287 }
288
289 /* API to enable Out of Range Comparator(ORC) for a desired group and a desired channel input */
XMC_SCU_DisableOutOfRangeComparator(const uint32_t group,const uint32_t channel)290 void XMC_SCU_DisableOutOfRangeComparator(const uint32_t group, const uint32_t channel)
291 {
292 XMC_ASSERT("XMC_SCU_DisableOutOfRangeComparator:Wrong Group Number",XMC_SCU_CHECK_GRPNUM(group));
293 XMC_ASSERT("XMC_SCU_DisableOutOfRangeComparator:Wrong Channel Number",XMC_SCU_CHECK_CHNUM(channel));
294
295 SCU_GENERAL->GORCEN[group] &= (uint32_t)~(1UL << channel);
296 }
297
298 /* API to calibrate temperature sensor */
XMC_SCU_CalibrateTemperatureSensor(uint32_t offset,uint32_t gain)299 void XMC_SCU_CalibrateTemperatureSensor(uint32_t offset, uint32_t gain)
300 {
301 SCU_GENERAL->DTSCON = ((uint32_t)(offset << SCU_GENERAL_DTSCON_OFFSET_Pos) |
302 (uint32_t)(gain << SCU_GENERAL_DTSCON_GAIN_Pos) |
303 (uint32_t)(0x4UL << SCU_GENERAL_DTSCON_REFTRIM_Pos) |
304 (uint32_t)(0x8UL << SCU_GENERAL_DTSCON_BGTRIM_Pos));
305 }
306 /* API to enable die temperature measurement by powering the DTS module. */
XMC_SCU_EnableTemperatureSensor(void)307 void XMC_SCU_EnableTemperatureSensor(void)
308 {
309 SCU_GENERAL->DTSCON &= (uint32_t)~(SCU_GENERAL_DTSCON_PWD_Msk);
310 }
311
312 /* API to disable die temperature measurement by powering the DTS module off. */
XMC_SCU_DisableTemperatureSensor(void)313 void XMC_SCU_DisableTemperatureSensor(void)
314 {
315 SCU_GENERAL->DTSCON |= (uint32_t)SCU_GENERAL_DTSCON_PWD_Msk;
316 }
317
318 /* API to provide the die temperature sensor power status. */
XMC_SCU_IsTemperatureSensorEnabled(void)319 bool XMC_SCU_IsTemperatureSensorEnabled(void)
320 {
321 return ((SCU_GENERAL->DTSCON & SCU_GENERAL_DTSCON_PWD_Msk) == 0U);
322 }
323
324 /* API to check if the die temperature sensor is ready to start a measurement. */
XMC_SCU_IsTemperatureSensorReady(void)325 bool XMC_SCU_IsTemperatureSensorReady(void)
326 {
327 return ((SCU_GENERAL->DTSSTAT & SCU_GENERAL_DTSSTAT_RDY_Msk) != 0U);
328 }
329 /* API to start device temperature measurements */
XMC_SCU_StartTemperatureMeasurement(void)330 XMC_SCU_STATUS_t XMC_SCU_StartTemperatureMeasurement(void)
331 {
332 XMC_SCU_STATUS_t status = XMC_SCU_STATUS_OK;
333
334 if (XMC_SCU_IsTemperatureSensorEnabled() == false)
335 {
336 status = XMC_SCU_STATUS_ERROR;
337 }
338
339 if (XMC_SCU_IsTemperatureSensorBusy() == true)
340 {
341 status = XMC_SCU_STATUS_BUSY;
342 }
343
344 /* And start the measurement */
345 SCU_GENERAL->DTSCON |= (uint32_t)SCU_GENERAL_DTSCON_START_Msk;
346
347 return (status);
348 }
349
350 /* API to retrieve the temperature measured */
XMC_SCU_GetTemperatureMeasurement(void)351 uint32_t XMC_SCU_GetTemperatureMeasurement(void)
352 {
353 uint32_t temperature;
354
355 if (XMC_SCU_IsTemperatureSensorEnabled() == false)
356 {
357 temperature = 0x7FFFFFFFUL;
358 }
359 else
360 {
361 temperature = (uint32_t)((SCU_GENERAL->DTSSTAT & SCU_GENERAL_DTSSTAT_RESULT_Msk) >> SCU_GENERAL_DTSSTAT_RESULT_Pos);
362 }
363
364 return ((uint32_t)temperature);
365 }
366
367 /* API to know whether Die temperature sensor is busy */
XMC_SCU_IsTemperatureSensorBusy(void)368 bool XMC_SCU_IsTemperatureSensorBusy(void)
369 {
370 return ((SCU_GENERAL->DTSSTAT & SCU_GENERAL_DTSSTAT_BUSY_Msk) != 0U);
371 }
372
373
374 #if defined(SCU_GENERAL_DTEMPLIM_LOWER_Msk) && defined(SCU_GENERAL_DTEMPLIM_UPPER_Msk)
375 /* API to determine if device temperature has gone past the ceiling */
XMC_SCU_HighTemperature(void)376 bool XMC_SCU_HighTemperature(void)
377 {
378 bool ret_val;
379 uint32_t dtscon;
380 uint32_t dtempalarm;
381 dtscon = SCU_GENERAL->DTSCON;
382 dtscon = dtscon & SCU_GENERAL_DTSCON_PWD_Msk;
383
384 ret_val = false;
385
386 /* Any audit makes sense only if the DTS were powered up */
387 if(dtscon)
388 {
389 /* Powered down - return false */
390 ret_val = false;
391 }
392 else
393 {
394 /* Powered up - Read the overflow bit and decide accordingly*/
395 dtempalarm = SCU_GENERAL->DTEMPALARM;
396 dtempalarm = dtempalarm & SCU_GENERAL_DTEMPALARM_OVERFL_Msk;
397
398 if(dtempalarm)
399 {
400 ret_val = true;
401 }
402 else
403 {
404 ret_val = false;
405 }
406 }
407 return (ret_val);
408 }
409
410 /* API to program raw values of temperature limits into the DTS */
XMC_SCU_SetRawTempLimits(const uint32_t lower_temp,const uint32_t upper_temp)411 void XMC_SCU_SetRawTempLimits(const uint32_t lower_temp, const uint32_t upper_temp)
412 {
413 /* Power up the DTS module */
414 SCU_GENERAL->DTSCON &= (uint32_t)~SCU_GENERAL_DTSCON_PWD_Msk;
415 SCU_GENERAL->DTEMPLIM = 0;
416 SCU_GENERAL->DTEMPLIM = (lower_temp & SCU_GENERAL_DTEMPLIM_LOWER_Msk);
417 SCU_GENERAL->DTEMPLIM |= (uint32_t)((upper_temp & SCU_GENERAL_DTEMPLIM_LOWER_Msk) << SCU_GENERAL_DTEMPLIM_UPPER_Pos);
418 }
419
420 /* API to determine if device temperature has gone below the stipulated limit */
XMC_SCU_LowTemperature(void)421 bool XMC_SCU_LowTemperature(void)
422 {
423 bool ret_val;
424 uint32_t dtscon;
425 uint32_t dtempalarm;
426 dtscon = SCU_GENERAL->DTSCON;
427 dtscon = dtscon & SCU_GENERAL_DTSCON_PWD_Msk;
428
429 ret_val = false;
430
431 /* Any audit makes sense only if the DTS were powered up */
432 if(dtscon)
433 {
434 /* Powered down - return false */
435 ret_val = false;
436 }
437 else
438 {
439 /* Powered up - Read the overflow bit and decide accordingly*/
440 dtempalarm = SCU_GENERAL->DTEMPALARM;
441 dtempalarm = dtempalarm & SCU_GENERAL_DTEMPALARM_UNDERFL_Msk;
442
443 if(dtempalarm)
444 {
445 ret_val = true;
446 }
447 else
448 {
449 ret_val = false;
450 }
451 }
452
453 return (ret_val);
454 }
455 #endif
456
457 /* API to write into Retention memory in hibernate domain */
XMC_SCU_WriteToRetentionMemory(uint32_t address,uint32_t data)458 void XMC_SCU_WriteToRetentionMemory(uint32_t address, uint32_t data)
459 {
460 uint32_t rmacr;
461
462 /* Get the address right */
463 rmacr = (uint32_t)((address << SCU_GENERAL_RMACR_ADDR_Pos) & (uint32_t)SCU_GENERAL_RMACR_ADDR_Msk);
464
465 /* Transfer from RMDATA to Retention memory */
466 rmacr |= (uint32_t)(SCU_GENERAL_RMACR_RDWR_Msk);
467
468 /* Write desired data into RMDATA register */
469 SCU_GENERAL->RMDATA = data;
470
471 /* Write address & direction of transfer into RMACR register */
472 SCU_GENERAL->RMACR = rmacr;
473
474 /* Wait until the update of RMX register in hibernate domain is completed */
475 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_RMX_Msk)
476 {
477 }
478 }
479
480 /* API to read from Retention memory in hibernate domain */
XMC_SCU_ReadFromRetentionMemory(uint32_t address)481 uint32_t XMC_SCU_ReadFromRetentionMemory(uint32_t address)
482 {
483 uint32_t rmacr;
484
485 /* Get the address right */
486 rmacr = ((uint32_t)(address << SCU_GENERAL_RMACR_ADDR_Pos) & (uint32_t)SCU_GENERAL_RMACR_ADDR_Msk);
487
488 /* Transfer from RMDATA to Retention memory */
489 rmacr &= ~((uint32_t)(SCU_GENERAL_RMACR_RDWR_Msk));
490
491 /* Writing an adress & direction of transfer into RMACR register */
492 SCU_GENERAL->RMACR = rmacr;
493
494 /* Wait until the update of RMX register in hibernate domain is completed */
495 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_RMX_Msk)
496 {
497 }
498
499 return (SCU_GENERAL->RMDATA);
500 }
501
502 /* API to initialize the clock tree */
XMC_SCU_CLOCK_Init(const XMC_SCU_CLOCK_CONFIG_t * const config)503 void XMC_SCU_CLOCK_Init(const XMC_SCU_CLOCK_CONFIG_t *const config)
504 {
505 XMC_ASSERT("", config->fsys_clkdiv != 0);
506 XMC_ASSERT("", config->fcpu_clkdiv != 0);
507 XMC_ASSERT("", config->fccu_clkdiv != 0);
508 XMC_ASSERT("", config->fperipheral_clkdiv != 0);
509 XMC_ASSERT("", ((config->syspll_config.p_div != 0) &&
510 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL)) ||
511 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_PRESCALAR));
512 XMC_ASSERT("", ((config->syspll_config.n_div != 0) &&
513 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL)) ||
514 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_PRESCALAR));
515 XMC_ASSERT("", (config->syspll_config.k_div != 0) &&
516 ((config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL) ||
517 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_PRESCALAR)));
518 XMC_ASSERT("", ((config->fsys_clksrc == XMC_SCU_CLOCK_SYSCLKSRC_PLL) ||
519 (config->fsys_clksrc == XMC_SCU_CLOCK_SYSCLKSRC_OFI)) &&
520 ((config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL) ||
521 (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_PRESCALAR)));
522 XMC_ASSERT("", ((config->fstdby_clksrc == XMC_SCU_HIB_STDBYCLKSRC_OSCULP) && (config->enable_osculp == true)) ||
523 (config->fstdby_clksrc != XMC_SCU_HIB_STDBYCLKSRC_OSCULP));
524 XMC_ASSERT("", ((config->syspll_config.clksrc == XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP) &&
525 (config->enable_oschp == true)) || (config->syspll_config.clksrc != XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP));
526
527 XMC_SCU_CLOCK_SetSystemClockSource(XMC_SCU_CLOCK_SYSCLKSRC_OFI);
528
529 XMC_SCU_HIB_EnableHibernateDomain();
530
531 if (config->enable_osculp == true)
532 {
533 XMC_SCU_CLOCK_EnableLowPowerOscillator();
534 while (XMC_SCU_CLOCK_IsLowPowerOscillatorStable() == false);
535 }
536
537 XMC_SCU_HIB_SetStandbyClockSource(config->fstdby_clksrc);
538 while (XMC_SCU_GetMirrorStatus() != 0)
539 {
540 /* Wait until update of the stanby clock source is done in the HIB domain */
541 }
542
543 XMC_SCU_CLOCK_SetBackupClockCalibrationMode(config->calibration_mode);
544
545 XMC_SCU_CLOCK_SetSystemClockDivider((uint32_t)config->fsys_clkdiv);
546 XMC_SCU_CLOCK_SetCpuClockDivider((uint32_t)config->fcpu_clkdiv);
547 XMC_SCU_CLOCK_SetCcuClockDivider((uint32_t)config->fccu_clkdiv);
548 XMC_SCU_CLOCK_SetPeripheralClockDivider((uint32_t)config->fperipheral_clkdiv);
549
550 if (config->enable_oschp == true)
551 {
552 XMC_SCU_CLOCK_EnableHighPerformanceOscillator();
553 while(XMC_SCU_CLOCK_IsHighPerformanceOscillatorStable() == false);
554 }
555
556 if (config->syspll_config.mode == XMC_SCU_CLOCK_SYSPLL_MODE_DISABLED)
557 {
558 XMC_SCU_CLOCK_DisableSystemPll();
559 }
560 else
561 {
562
563 XMC_SCU_CLOCK_EnableSystemPll();
564 XMC_SCU_CLOCK_StartSystemPll(config->syspll_config.clksrc,
565 config->syspll_config.mode,
566 (uint32_t)config->syspll_config.p_div,
567 (uint32_t)config->syspll_config.n_div,
568 (uint32_t)config->syspll_config.k_div);
569 }
570
571 /* use SYSPLL? */
572 if (config->fsys_clksrc == XMC_SCU_CLOCK_SYSCLKSRC_PLL)
573 {
574 XMC_SCU_CLOCK_SetSystemClockSource(XMC_SCU_CLOCK_SYSCLKSRC_PLL);
575 }
576 SystemCoreClockUpdate();
577 }
578
579 /* API to enable a trap source */
XMC_SCU_TRAP_Enable(const uint32_t trap)580 void XMC_SCU_TRAP_Enable(const uint32_t trap)
581 {
582 SCU_TRAP->TRAPDIS &= (uint32_t)~trap;
583 }
584
585 /* API to disable a trap source */
XMC_SCU_TRAP_Disable(const uint32_t trap)586 void XMC_SCU_TRAP_Disable(const uint32_t trap)
587 {
588 SCU_TRAP->TRAPDIS |= (uint32_t)trap;
589 }
590
591 /* API to determine if a trap source has generated event */
XMC_SCU_TRAP_GetStatus(void)592 uint32_t XMC_SCU_TRAP_GetStatus(void)
593 {
594 return (SCU_TRAP->TRAPRAW);
595 }
596
597 /* API to manually trigger a trap event */
XMC_SCU_TRAP_Trigger(const uint32_t trap)598 void XMC_SCU_TRAP_Trigger(const uint32_t trap)
599 {
600 SCU_TRAP->TRAPSET = (uint32_t)trap;
601 }
602
603 /* API to clear a trap event */
XMC_SCU_TRAP_ClearStatus(const uint32_t trap)604 void XMC_SCU_TRAP_ClearStatus(const uint32_t trap)
605 {
606 SCU_TRAP->TRAPCLR = (uint32_t)trap;
607 }
608
609 /* API to clear parity error event */
XMC_SCU_PARITY_ClearStatus(const uint32_t memory)610 void XMC_SCU_PARITY_ClearStatus(const uint32_t memory)
611 {
612 SCU_PARITY->PEFLAG |= (uint32_t)memory;
613 }
614
615 /* API to determine if the specified parity error has occured or not */
XMC_SCU_PARITY_GetStatus(void)616 uint32_t XMC_SCU_PARITY_GetStatus(void)
617 {
618 return (SCU_PARITY->PEFLAG);
619 }
620
621 /* API to enable parity error checking for the selected on-chip RAM type */
XMC_SCU_PARITY_Enable(const uint32_t memory)622 void XMC_SCU_PARITY_Enable(const uint32_t memory)
623 {
624 SCU_PARITY->PEEN |= (uint32_t)memory;
625 }
626
627 /* API to disable parity error checking for the selected on-chip RAM type */
XMC_SCU_PARITY_Disable(const uint32_t memory)628 void XMC_SCU_PARITY_Disable(const uint32_t memory)
629 {
630 SCU_PARITY->PEEN &= (uint32_t)~memory;
631 }
632
633 /* API to enable trap assertion for the parity error source */
XMC_SCU_PARITY_EnableTrapGeneration(const uint32_t memory)634 void XMC_SCU_PARITY_EnableTrapGeneration(const uint32_t memory)
635 {
636 SCU_PARITY->PETE |= (uint32_t)memory;
637 }
638
639 /* API to disable the assertion of trap for the parity error source */
XMC_SCU_PARITY_DisableTrapGeneration(const uint32_t memory)640 void XMC_SCU_PARITY_DisableTrapGeneration(const uint32_t memory)
641 {
642 SCU_PARITY->PETE &= (uint32_t)~memory;
643 }
644
645 /* Enables a NMI source */
XMC_SCU_INTERRUPT_EnableNmiRequest(const uint32_t request)646 void XMC_SCU_INTERRUPT_EnableNmiRequest(const uint32_t request)
647 {
648 SCU_INTERRUPT->NMIREQEN |= (uint32_t)request;
649 }
650
651 /* Disables a NMI source */
XMC_SCU_INTERRUPT_DisableNmiRequest(const uint32_t request)652 void XMC_SCU_INTERRUPT_DisableNmiRequest(const uint32_t request)
653 {
654 SCU_INTERRUPT->NMIREQEN &= (uint32_t)~request;
655 }
656
657 /* API to manually assert a reset request */
XMC_SCU_RESET_AssertPeripheralReset(const XMC_SCU_PERIPHERAL_RESET_t peripheral)658 void XMC_SCU_RESET_AssertPeripheralReset(const XMC_SCU_PERIPHERAL_RESET_t peripheral)
659 {
660 uint32_t index = (uint32_t)((((uint32_t)peripheral) & 0xf0000000UL) >> 28UL);
661 uint32_t mask = (((uint32_t)peripheral) & ((uint32_t)~0xf0000000UL));
662
663 *(uint32_t *)(&(SCU_RESET->PRSET0) + (index * 3U)) = (uint32_t)mask;
664 }
665
666 /* API to manually de-assert a reset request */
XMC_SCU_RESET_DeassertPeripheralReset(const XMC_SCU_PERIPHERAL_RESET_t peripheral)667 void XMC_SCU_RESET_DeassertPeripheralReset(const XMC_SCU_PERIPHERAL_RESET_t peripheral)
668 {
669 uint32_t index = (uint32_t)((((uint32_t)peripheral) & 0xf0000000UL) >> 28UL);
670 uint32_t mask = (((uint32_t)peripheral) & ((uint32_t)~0xf0000000UL));
671
672 *(uint32_t *)(&(SCU_RESET->PRCLR0) + (index * 3U)) = (uint32_t)mask;
673 }
674
675 /* Find out if the peripheral reset is asserted */
XMC_SCU_RESET_IsPeripheralResetAsserted(const XMC_SCU_PERIPHERAL_RESET_t peripheral)676 bool XMC_SCU_RESET_IsPeripheralResetAsserted(const XMC_SCU_PERIPHERAL_RESET_t peripheral)
677 {
678 uint32_t index = (uint32_t)((((uint32_t)peripheral) & 0xf0000000UL) >> 28UL);
679 uint32_t mask = (((uint32_t)peripheral) & ((uint32_t)~0xf0000000UL));
680
681 return ((*(uint32_t *)(&(SCU_RESET->PRSTAT0) + (index * 3U)) & mask) != 0U);
682 }
683
684 /*
685 * API to retrieve frequency of System PLL output clock
686 */
XMC_SCU_CLOCK_GetSystemPllClockFrequency(void)687 uint32_t XMC_SCU_CLOCK_GetSystemPllClockFrequency(void)
688 {
689 uint32_t clock_frequency;
690 uint32_t p_div;
691 uint32_t n_div;
692 uint32_t k2_div;
693
694 clock_frequency = XMC_SCU_CLOCK_GetSystemPllClockSourceFrequency();
695 if(SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk)
696 {
697 /* Prescalar mode - fOSC is the parent*/
698 clock_frequency = (uint32_t)(clock_frequency /
699 ((((SCU_PLL->PLLCON1) & SCU_PLL_PLLCON1_K1DIV_Msk) >> SCU_PLL_PLLCON1_K1DIV_Pos) + 1UL));
700 }
701 else
702 {
703 p_div = (uint32_t)((((SCU_PLL->PLLCON1) & SCU_PLL_PLLCON1_PDIV_Msk) >> SCU_PLL_PLLCON1_PDIV_Pos) + 1UL);
704 n_div = (uint32_t)((((SCU_PLL->PLLCON1) & SCU_PLL_PLLCON1_NDIV_Msk) >> SCU_PLL_PLLCON1_NDIV_Pos) + 1UL);
705 k2_div = (uint32_t)((((SCU_PLL->PLLCON1) & SCU_PLL_PLLCON1_K2DIV_Msk) >> SCU_PLL_PLLCON1_K2DIV_Pos) + 1UL);
706
707 clock_frequency = (clock_frequency * n_div) / (p_div * k2_div);
708 }
709
710 return (clock_frequency);
711 }
712
713 /**
714 * API to retrieve frequency of System PLL VCO input clock
715 */
XMC_SCU_CLOCK_GetSystemPllClockSourceFrequency(void)716 uint32_t XMC_SCU_CLOCK_GetSystemPllClockSourceFrequency(void)
717 {
718 uint32_t clock_frequency;
719
720 /* Prescalar mode - fOSC is the parent*/
721 if((SCU_PLL->PLLCON2 & SCU_PLL_PLLCON2_PINSEL_Msk) == (uint32_t)XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP)
722 {
723 clock_frequency = OSCHP_GetFrequency();
724 }
725 else
726 {
727 clock_frequency = OFI_FREQUENCY;
728 }
729
730 return (clock_frequency);
731 }
732
733 /*
734 * API to retrieve frequency of USB PLL output clock
735 */
XMC_SCU_CLOCK_GetUsbPllClockFrequency(void)736 uint32_t XMC_SCU_CLOCK_GetUsbPllClockFrequency(void)
737 {
738 uint32_t clock_frequency;
739 uint32_t n_div;
740 uint32_t p_div;
741
742 clock_frequency = OSCHP_GetFrequency();
743 if((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOBYST_Msk) == 0U)
744 {
745 /* Normal mode - fVCO is the parent*/
746 n_div = (uint32_t)((((SCU_PLL->USBPLLCON) & SCU_PLL_USBPLLCON_NDIV_Msk) >> SCU_PLL_USBPLLCON_NDIV_Pos) + 1UL);
747 p_div = (uint32_t)((((SCU_PLL->USBPLLCON) & SCU_PLL_USBPLLCON_PDIV_Msk) >> SCU_PLL_USBPLLCON_PDIV_Pos) + 1UL);
748 clock_frequency = (uint32_t)((clock_frequency * n_div)/ (uint32_t)(p_div * 2UL));
749 }
750 return (clock_frequency);
751 }
752
753 /*
754 * API to retrieve frequency of CCU clock frequency
755 */
XMC_SCU_CLOCK_GetCcuClockFrequency(void)756 uint32_t XMC_SCU_CLOCK_GetCcuClockFrequency(void)
757 {
758 uint32_t frequency = 0UL;
759 frequency = XMC_SCU_CLOCK_GetSystemClockFrequency();
760
761 return (uint32_t)(frequency >> ((uint32_t)((SCU_CLK->CCUCLKCR & SCU_CLK_CCUCLKCR_CCUDIV_Msk) >>
762 SCU_CLK_CCUCLKCR_CCUDIV_Pos)));
763 }
764
765 /*
766 * API to retrieve USB and SDMMC clock frequency
767 */
XMC_SCU_CLOCK_GetUsbClockFrequency(void)768 uint32_t XMC_SCU_CLOCK_GetUsbClockFrequency(void)
769 {
770 uint32_t frequency = 0UL;
771 XMC_SCU_CLOCK_USBCLKSRC_t clksrc;
772
773 clksrc = XMC_SCU_CLOCK_GetUsbClockSource();
774
775 if (clksrc == XMC_SCU_CLOCK_USBCLKSRC_SYSPLL)
776 {
777 frequency = XMC_SCU_CLOCK_GetSystemPllClockFrequency();
778 }
779 else if (clksrc == XMC_SCU_CLOCK_USBCLKSRC_USBPLL)
780 {
781 frequency = XMC_SCU_CLOCK_GetUsbPllClockFrequency();
782 }
783 else
784 {
785 }
786
787 return (uint32_t)(frequency / (((SCU_CLK->USBCLKCR & SCU_CLK_USBCLKCR_USBDIV_Msk) >>
788 SCU_CLK_USBCLKCR_USBDIV_Pos) + 1UL));
789 }
790
791 #if defined(EBU)
792 /*
793 * API to retrieve EBU clock frequency
794 */
XMC_SCU_CLOCK_GetEbuClockFrequency(void)795 uint32_t XMC_SCU_CLOCK_GetEbuClockFrequency(void)
796 {
797 uint32_t frequency = XMC_SCU_CLOCK_GetSystemPllClockFrequency();
798
799 return (uint32_t)((frequency /(((SCU_CLK->EBUCLKCR & SCU_CLK_EBUCLKCR_EBUDIV_Msk) >>
800 SCU_CLK_EBUCLKCR_EBUDIV_Pos) + 1UL)));
801 }
802 #endif
803
804 #if defined(ECAT0)
805 /*
806 * API to retrieve ECAT clock frequency
807 */
XMC_SCU_CLOCK_GetECATClockFrequency(void)808 uint32_t XMC_SCU_CLOCK_GetECATClockFrequency(void)
809 {
810 uint32_t frequency;
811
812 if ((SCU_CLK->ECATCLKCR & SCU_CLK_ECATCLKCR_ECATSEL_Msk) != 0U)
813 {
814 frequency = XMC_SCU_CLOCK_GetSystemPllClockFrequency();
815 }
816 else
817 {
818 frequency = XMC_SCU_CLOCK_GetUsbPllClockFrequency();
819 }
820
821 return (uint32_t)((frequency / (XMC_SCU_CLOCK_GetECATClockDivider() + 1UL)));
822 }
823 #endif
824
825 /*
826 * API to retrieve WDT clock frequency
827 */
XMC_SCU_CLOCK_GetWdtClockFrequency(void)828 uint32_t XMC_SCU_CLOCK_GetWdtClockFrequency(void)
829 {
830 uint32_t frequency = 0UL;
831 XMC_SCU_CLOCK_WDTCLKSRC_t clksrc;
832
833 clksrc = XMC_SCU_CLOCK_GetWdtClockSource();
834
835 if (clksrc == XMC_SCU_CLOCK_WDTCLKSRC_PLL)
836 {
837 frequency = XMC_SCU_CLOCK_GetSystemPllClockFrequency();
838 }
839 else if (clksrc == XMC_SCU_CLOCK_WDTCLKSRC_OFI)
840 {
841 frequency = OFI_FREQUENCY;
842 }
843 else if (clksrc == XMC_SCU_CLOCK_WDTCLKSRC_STDBY)
844 {
845 frequency = OSI_FREQUENCY;
846 }
847 else
848 {
849
850 }
851
852 return (uint32_t)((frequency / (((SCU_CLK->WDTCLKCR & SCU_CLK_WDTCLKCR_WDTDIV_Msk) >>
853 SCU_CLK_WDTCLKCR_WDTDIV_Pos) + 1UL)));
854 }
855
856 /**
857 * @brief API to retrieve EXTERNAL-OUT clock frequency
858 * @retval Clock frequency
859 */
XMC_SCU_CLOCK_GetExternalOutputClockFrequency(void)860 uint32_t XMC_SCU_CLOCK_GetExternalOutputClockFrequency(void)
861 {
862 uint32_t frequency = 0UL;
863 XMC_SCU_CLOCK_EXTOUTCLKSRC_t clksrc;
864
865 clksrc = XMC_SCU_CLOCK_GetExternalOutputClockSource();
866
867 if (clksrc == XMC_SCU_CLOCK_EXTOUTCLKSRC_PLL)
868 {
869 frequency = XMC_SCU_CLOCK_GetSystemPllClockFrequency();
870
871 frequency = (uint32_t)((frequency / ((((SCU_CLK->EXTCLKCR) & SCU_CLK_EXTCLKCR_ECKDIV_Msk) >>
872 SCU_CLK_EXTCLKCR_ECKDIV_Pos)+ 1UL)));
873 }
874 else if (clksrc == XMC_SCU_CLOCK_EXTOUTCLKSRC_SYS)
875 {
876 frequency = XMC_SCU_CLOCK_GetSystemClockFrequency();
877 }
878 else if (clksrc == XMC_SCU_CLOCK_EXTOUTCLKSRC_USB)
879 {
880 frequency = XMC_SCU_CLOCK_GetUsbPllClockFrequency();
881
882 frequency = (uint32_t)((frequency / ((((SCU_CLK->EXTCLKCR) & SCU_CLK_EXTCLKCR_ECKDIV_Msk) >>
883 SCU_CLK_EXTCLKCR_ECKDIV_Pos)+ 1UL)));
884 }
885 else
886 {
887
888 }
889
890 return (frequency);
891 }
892
893 /*
894 * API to retrieve clock frequency of peripherals on the peripheral bus using a shared functional clock
895 */
XMC_SCU_CLOCK_GetPeripheralClockFrequency(void)896 uint32_t XMC_SCU_CLOCK_GetPeripheralClockFrequency(void)
897 {
898 return (uint32_t)(XMC_SCU_CLOCK_GetCpuClockFrequency() >>
899 ((SCU_CLK->PBCLKCR & SCU_CLK_PBCLKCR_PBDIV_Msk) >> SCU_CLK_PBCLKCR_PBDIV_Pos));
900 }
901
902 /* API to select fSYS */
XMC_SCU_CLOCK_SetSystemClockSource(const XMC_SCU_CLOCK_SYSCLKSRC_t source)903 void XMC_SCU_CLOCK_SetSystemClockSource(const XMC_SCU_CLOCK_SYSCLKSRC_t source)
904 {
905 SCU_CLK->SYSCLKCR = (SCU_CLK->SYSCLKCR & ((uint32_t)~SCU_CLK_SYSCLKCR_SYSSEL_Msk)) |
906 ((uint32_t)source);
907 }
908
909 /* API to select fUSB */
XMC_SCU_CLOCK_SetUsbClockSource(const XMC_SCU_CLOCK_USBCLKSRC_t source)910 void XMC_SCU_CLOCK_SetUsbClockSource(const XMC_SCU_CLOCK_USBCLKSRC_t source)
911 {
912 SCU_CLK->USBCLKCR = (SCU_CLK->USBCLKCR & ((uint32_t)~SCU_CLK_USBCLKCR_USBSEL_Msk)) |
913 ((uint32_t)source);
914 }
915
916 /* API to select fWDT */
XMC_SCU_CLOCK_SetWdtClockSource(const XMC_SCU_CLOCK_WDTCLKSRC_t source)917 void XMC_SCU_CLOCK_SetWdtClockSource(const XMC_SCU_CLOCK_WDTCLKSRC_t source)
918 {
919 SCU_CLK->WDTCLKCR = (SCU_CLK->WDTCLKCR & ((uint32_t)~SCU_CLK_WDTCLKCR_WDTSEL_Msk)) |
920 ((uint32_t)source);
921 }
922
923 /* API to select fEXT */
XMC_SCU_CLOCK_SetExternalOutputClockSource(const XMC_SCU_CLOCK_EXTOUTCLKSRC_t source)924 void XMC_SCU_CLOCK_SetExternalOutputClockSource(const XMC_SCU_CLOCK_EXTOUTCLKSRC_t source)
925 {
926 SCU_CLK->EXTCLKCR = (SCU_CLK->EXTCLKCR & ((uint32_t)~SCU_CLK_EXTCLKCR_ECKSEL_Msk)) |
927 ((uint32_t)source);
928 }
929
930 /* API to select fPLL */
XMC_SCU_CLOCK_SetSystemPllClockSource(const XMC_SCU_CLOCK_SYSPLLCLKSRC_t source)931 void XMC_SCU_CLOCK_SetSystemPllClockSource(const XMC_SCU_CLOCK_SYSPLLCLKSRC_t source)
932 {
933 /* Check input clock */
934 if (source == XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP) /* Select PLLClockSource */
935 {
936 SCU_PLL->PLLCON2 &= (uint32_t)~(SCU_PLL_PLLCON2_PINSEL_Msk | SCU_PLL_PLLCON2_K1INSEL_Msk);
937 }
938 else
939 {
940 SCU_PLL->PLLCON2 |= (uint32_t)(SCU_PLL_PLLCON2_PINSEL_Msk | SCU_PLL_PLLCON2_K1INSEL_Msk);
941 }
942 }
943
944 /* API to select fRTC */
XMC_SCU_HIB_SetRtcClockSource(const XMC_SCU_HIB_RTCCLKSRC_t source)945 void XMC_SCU_HIB_SetRtcClockSource(const XMC_SCU_HIB_RTCCLKSRC_t source)
946 {
947 /* Wait until the update of HDCR register in hibernate domain is completed */
948 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
949 {
950 }
951
952 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & ((uint32_t)~SCU_HIBERNATE_HDCR_RCS_Msk)) |
953 ((uint32_t)source);
954 }
955
956 /* API to select fSTDBY */
XMC_SCU_HIB_SetStandbyClockSource(const XMC_SCU_HIB_STDBYCLKSRC_t source)957 void XMC_SCU_HIB_SetStandbyClockSource(const XMC_SCU_HIB_STDBYCLKSRC_t source)
958 {
959 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
960 {
961 /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
962 }
963 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & ((uint32_t)~SCU_HIBERNATE_HDCR_STDBYSEL_Msk)) |
964 ((uint32_t)source);
965 }
966
967 /* API to program the divider placed between fsys and its parent */
XMC_SCU_CLOCK_SetSystemClockDivider(const uint32_t divider)968 void XMC_SCU_CLOCK_SetSystemClockDivider(const uint32_t divider)
969 {
970 XMC_ASSERT("XMC_SCU_CLOCK_SetSystemClockDivider:Wrong clock divider value",
971 (divider <= (SCU_CLK_SYSCLKCR_SYSDIV_Msk + 1UL)) );
972
973 SCU_CLK->SYSCLKCR = (SCU_CLK->SYSCLKCR & ((uint32_t)~SCU_CLK_SYSCLKCR_SYSDIV_Msk)) |
974 ((uint32_t)(((uint32_t)(divider - 1UL)) << SCU_CLK_SYSCLKCR_SYSDIV_Pos));
975 }
976
977 /* API to program the divider placed between fccu and its parent */
XMC_SCU_CLOCK_SetCcuClockDivider(const uint32_t divider)978 void XMC_SCU_CLOCK_SetCcuClockDivider(const uint32_t divider)
979 {
980 XMC_ASSERT("XMC_SCU_CLOCK_SetCapcomClockDivider:Wrong clock divider value", (divider <= 2UL) );
981
982 SCU_CLK->CCUCLKCR = (SCU_CLK->CCUCLKCR & ((uint32_t)~SCU_CLK_CCUCLKCR_CCUDIV_Msk)) |
983 (uint32_t)((uint32_t)(divider - 1UL) << SCU_CLK_CCUCLKCR_CCUDIV_Pos);
984 }
985
986 /* API to program the divider placed between fcpu and its parent */
XMC_SCU_CLOCK_SetCpuClockDivider(const uint32_t divider)987 void XMC_SCU_CLOCK_SetCpuClockDivider(const uint32_t divider)
988 {
989 XMC_ASSERT("XMC_SCU_CLOCK_SetCpuClockDivider:Wrong clock divider value", (divider <= 2UL) );
990
991 SCU_CLK->CPUCLKCR = (SCU_CLK->CPUCLKCR & ((uint32_t)~SCU_CLK_CPUCLKCR_CPUDIV_Msk)) |
992 (uint32_t)((uint32_t)(divider - 1UL) << SCU_CLK_CPUCLKCR_CPUDIV_Pos);
993 }
994
995 /* API to program the divider placed between fperiph and its parent */
XMC_SCU_CLOCK_SetPeripheralClockDivider(const uint32_t divider)996 void XMC_SCU_CLOCK_SetPeripheralClockDivider(const uint32_t divider)
997 {
998 XMC_ASSERT("XMC_SCU_CLOCK_SetPeripheralClockDivider:Wrong clock divider value", (divider <= 2UL) );
999
1000 SCU_CLK->PBCLKCR = (SCU_CLK->PBCLKCR & ((uint32_t)~SCU_CLK_PBCLKCR_PBDIV_Msk)) |
1001 ((uint32_t)((uint32_t)(divider - 1UL) << SCU_CLK_PBCLKCR_PBDIV_Pos));
1002 }
1003
1004 /* API to program the divider placed between fsdmmc and its parent */
XMC_SCU_CLOCK_SetUsbClockDivider(const uint32_t divider)1005 void XMC_SCU_CLOCK_SetUsbClockDivider(const uint32_t divider)
1006 {
1007 XMC_ASSERT("XMC_SCU_CLOCK_SetSdmmcClockDivider:Wrong clock divider value",
1008 (divider <= (SCU_CLK_USBCLKCR_USBDIV_Msk + 1UL)) );
1009
1010 SCU_CLK->USBCLKCR = (SCU_CLK->USBCLKCR & ((uint32_t)~SCU_CLK_USBCLKCR_USBDIV_Msk)) |
1011 (uint32_t)((uint32_t)(divider - 1UL) << SCU_CLK_USBCLKCR_USBDIV_Pos);
1012 }
1013
1014 #if defined(EBU)
1015 /* API to program the divider placed between febu and its parent */
XMC_SCU_CLOCK_SetEbuClockDivider(const uint32_t divider)1016 void XMC_SCU_CLOCK_SetEbuClockDivider(const uint32_t divider)
1017 {
1018 XMC_ASSERT("XMC_SCU_CLOCK_SetEbuClockDivider:Wrong clock divider value",
1019 (divider <= (SCU_CLK_EBUCLKCR_EBUDIV_Msk + 1UL) ) );
1020
1021 SCU_CLK->EBUCLKCR = (SCU_CLK->EBUCLKCR & ((uint32_t)~SCU_CLK_EBUCLKCR_EBUDIV_Msk)) |
1022 (uint32_t)(((uint32_t)(divider - 1UL)) << SCU_CLK_EBUCLKCR_EBUDIV_Pos);
1023 }
1024 #endif
1025
1026 /* API to program the divider placed between fwdt and its parent */
XMC_SCU_CLOCK_SetWdtClockDivider(const uint32_t divider)1027 void XMC_SCU_CLOCK_SetWdtClockDivider(const uint32_t divider)
1028 {
1029 XMC_ASSERT("XMC_SCU_CLOCK_SetWdtClockDivider:Wrong clock divider value",
1030 (divider <= (SCU_CLK_WDTCLKCR_WDTDIV_Msk + 1UL) ) );
1031
1032 SCU_CLK->WDTCLKCR = (SCU_CLK->WDTCLKCR & ((uint32_t)~SCU_CLK_WDTCLKCR_WDTDIV_Msk)) |
1033 (uint32_t)(((uint32_t)(divider - 1UL)) << SCU_CLK_WDTCLKCR_WDTDIV_Pos);
1034 }
1035
1036 /* API to program the divider placed between fext and its parent */
XMC_SCU_CLOCK_SetExternalOutputClockDivider(const uint32_t divider)1037 void XMC_SCU_CLOCK_SetExternalOutputClockDivider(const uint32_t divider)
1038 {
1039 XMC_ASSERT("XMC_SCU_CLOCK_SetExternalOutputClockDivider:Wrong clock divider value",
1040 (divider <= (SCU_CLK_EXTCLKCR_ECKDIV_Msk + 1UL) ) );
1041
1042 SCU_CLK->EXTCLKCR = (SCU_CLK->EXTCLKCR & ((uint32_t)~SCU_CLK_EXTCLKCR_ECKDIV_Msk)) |
1043 (uint32_t)(((uint32_t)(divider - 1UL)) << SCU_CLK_EXTCLKCR_ECKDIV_Pos);
1044 }
1045
1046 #if defined(ECAT0)
1047 /* API to configure the ECAT clock by setting the clock divider for the ECAT clock source */
XMC_SCU_CLOCK_SetECATClockDivider(const uint32_t divider)1048 void XMC_SCU_CLOCK_SetECATClockDivider(const uint32_t divider)
1049 {
1050 SCU_CLK->ECATCLKCR = (SCU_CLK->ECATCLKCR & ~SCU_CLK_ECATCLKCR_ECADIV_Msk) |
1051 (uint32_t)(((uint32_t)(divider - 1UL)) << SCU_CLK_ECATCLKCR_ECADIV_Pos);
1052 }
1053 #endif
1054
1055 /* API to enable a given module clock */
XMC_SCU_CLOCK_EnableClock(const XMC_SCU_CLOCK_t clock)1056 void XMC_SCU_CLOCK_EnableClock(const XMC_SCU_CLOCK_t clock)
1057 {
1058 SCU_CLK->CLKSET = ((uint32_t)clock);
1059 }
1060
1061 /* API to disable a given module clock */
XMC_SCU_CLOCK_DisableClock(const XMC_SCU_CLOCK_t clock)1062 void XMC_SCU_CLOCK_DisableClock(const XMC_SCU_CLOCK_t clock)
1063 {
1064 SCU_CLK->CLKCLR = ((uint32_t)clock);
1065 }
1066
1067 /* API to determine if module clock of the given peripheral is enabled */
XMC_SCU_CLOCK_IsClockEnabled(const XMC_SCU_CLOCK_t clock)1068 bool XMC_SCU_CLOCK_IsClockEnabled(const XMC_SCU_CLOCK_t clock)
1069 {
1070 return (bool)(SCU_CLK->CLKSTAT & ((uint32_t)clock));
1071 }
1072
1073 #if defined(CLOCK_GATING_SUPPORTED)
1074 /* API to gate a given module clock */
XMC_SCU_CLOCK_GatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)1075 void XMC_SCU_CLOCK_GatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
1076 {
1077 uint32_t index = (peripheral & 0xf0000000UL) >> 28UL;
1078 uint32_t mask = (peripheral & (uint32_t)~0xf0000000UL);
1079
1080 *(uint32_t *)((&(SCU_CLK->CGATSET0)) + (index * 3U)) = (uint32_t)mask;
1081 }
1082
1083 /* API to ungate a given module clock */
XMC_SCU_CLOCK_UngatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)1084 void XMC_SCU_CLOCK_UngatePeripheralClock(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
1085 {
1086 uint32_t index = (uint32_t)((peripheral & 0xf0000000UL) >> 28UL);
1087 uint32_t mask = (peripheral & (uint32_t)~0xf0000000UL);
1088
1089 *(uint32_t *)(&(SCU_CLK->CGATCLR0) + (index * 3U)) = (uint32_t)mask;
1090 }
1091
1092 /* API to ungate a given module clock */
XMC_SCU_CLOCK_IsPeripheralClockGated(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)1093 bool XMC_SCU_CLOCK_IsPeripheralClockGated(const XMC_SCU_PERIPHERAL_CLOCK_t peripheral)
1094 {
1095 uint32_t index = ((peripheral & 0xf0000000UL) >> 28UL);
1096 uint32_t mask = (peripheral & (uint32_t)~0xf0000000UL);
1097
1098 return ((*(uint32_t *)(&(SCU_CLK->CGATSTAT0) + (index * 3U)) & mask) != 0U);
1099 }
1100 #endif
1101
XMC_SCU_POWER_GetEVR13Voltage(void)1102 float XMC_SCU_POWER_GetEVR13Voltage(void)
1103 {
1104 return (SCU_POWER->EVRVADCSTAT & SCU_POWER_EVRVADCSTAT_VADC13V_Msk) * XMC_SCU_POWER_LSB13V;
1105 }
1106
XMC_SCU_POWER_GetEVR33Voltage(void)1107 float XMC_SCU_POWER_GetEVR33Voltage(void)
1108 {
1109 return ((SCU_POWER->EVRVADCSTAT & SCU_POWER_EVRVADCSTAT_VADC33V_Msk) >> SCU_POWER_EVRVADCSTAT_VADC33V_Pos) * XMC_SCU_POWER_LSB33V;
1110 }
1111
1112 /* API to enable USB PLL for USB clock */
XMC_SCU_CLOCK_EnableUsbPll(void)1113 void XMC_SCU_CLOCK_EnableUsbPll(void)
1114 {
1115 SCU_PLL->USBPLLCON &= (uint32_t)~(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk);
1116 }
1117
1118 /* API to disable USB PLL for USB clock */
XMC_SCU_CLOCK_DisableUsbPll(void)1119 void XMC_SCU_CLOCK_DisableUsbPll(void)
1120 {
1121 SCU_PLL->USBPLLCON |= (uint32_t)(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk);
1122 }
1123
1124 /* API to configure USB PLL */
XMC_SCU_CLOCK_StartUsbPll(uint32_t pdiv,uint32_t ndiv)1125 void XMC_SCU_CLOCK_StartUsbPll(uint32_t pdiv, uint32_t ndiv)
1126 {
1127 /* Go to bypass the USB PLL */
1128 SCU_PLL->USBPLLCON |= (uint32_t)SCU_PLL_USBPLLCON_VCOBYP_Msk;
1129
1130 /* disconnect Oscillator from USB PLL */
1131 SCU_PLL->USBPLLCON |= (uint32_t)SCU_PLL_USBPLLCON_FINDIS_Msk;
1132
1133 /* Setup Divider settings for USB PLL */
1134 SCU_PLL->USBPLLCON = (uint32_t)((uint32_t)((ndiv -1U) << SCU_PLL_USBPLLCON_NDIV_Pos) |
1135 (uint32_t)((pdiv - 1U) << SCU_PLL_USBPLLCON_PDIV_Pos));
1136
1137 /* Set OSCDISCDIS */
1138 SCU_PLL->USBPLLCON |= (uint32_t)SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
1139
1140 /* connect Oscillator to USB PLL */
1141 SCU_PLL->USBPLLCON &= (uint32_t)~SCU_PLL_USBPLLCON_FINDIS_Msk;
1142
1143 /* restart PLL Lock detection */
1144 SCU_PLL->USBPLLCON |= (uint32_t)SCU_PLL_USBPLLCON_RESLD_Msk;
1145
1146 while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk) == 0U)
1147 {
1148 /* wait for PLL Lock */
1149 }
1150
1151 }
1152
1153 /* API to disable USB PLL operation */
XMC_SCU_CLOCK_StopUsbPll(void)1154 void XMC_SCU_CLOCK_StopUsbPll(void)
1155 {
1156 SCU_PLL->USBPLLCON = (uint32_t)(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk |
1157 SCU_PLL_USBPLLCON_VCOBYP_Msk);
1158 }
1159
1160 /* API to onfigure the calibration mode for internal oscillator */
XMC_SCU_CLOCK_SetBackupClockCalibrationMode(XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_t mode)1161 void XMC_SCU_CLOCK_SetBackupClockCalibrationMode(XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_t mode)
1162 {
1163 /* Enable factory calibration based trimming */
1164 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_FOTR_Msk;
1165
1166 if (mode == XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_AUTOMATIC)
1167 {
1168 /* Disable factory calibration based trimming */
1169 SCU_PLL->PLLCON0 &= (uint32_t)~SCU_PLL_PLLCON0_FOTR_Msk;
1170 XMC_SCU_lDelay(100UL);
1171
1172 /* Enable automatic calibration */
1173 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_AOTREN_Msk;
1174 }
1175
1176 XMC_SCU_lDelay(100UL);
1177 }
1178
1179
1180
1181 /* API to enable USB Phy and comparator */
XMC_SCU_POWER_EnableUsb(void)1182 void XMC_SCU_POWER_EnableUsb(void)
1183 {
1184 #if defined(USB_OTG_SUPPORTED)
1185 SCU_POWER->PWRSET = (uint32_t)(SCU_POWER_PWRSET_USBOTGEN_Msk | SCU_POWER_PWRSET_USBPHYPDQ_Msk);
1186 #else
1187 SCU_POWER->PWRSET = (uint32_t)SCU_POWER_PWRSET_USBPHYPDQ_Msk;
1188 #endif
1189 }
1190
1191 /* API to power down USB Phy and comparator */
XMC_SCU_POWER_DisableUsb(void)1192 void XMC_SCU_POWER_DisableUsb(void)
1193 {
1194 #if defined(USB_OTG_SUPPORTED)
1195 SCU_POWER->PWRCLR = (uint32_t)(SCU_POWER_PWRCLR_USBOTGEN_Msk | SCU_POWER_PWRSET_USBPHYPDQ_Msk);
1196 #else
1197 SCU_POWER->PWRCLR = (uint32_t)SCU_POWER_PWRCLR_USBPHYPDQ_Msk;
1198 #endif
1199 }
1200
1201 /* API to check USB PLL is locked or not */
XMC_SCU_CLOCK_IsUsbPllLocked(void)1202 bool XMC_SCU_CLOCK_IsUsbPllLocked(void)
1203 {
1204 return (bool)((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk) != 0UL);
1205 }
1206
1207 /* API to power up the hibernation domain */
XMC_SCU_HIB_EnableHibernateDomain(void)1208 void XMC_SCU_HIB_EnableHibernateDomain(void)
1209 {
1210 /* Power up HIB domain if and only if it is currently powered down */
1211 if((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0UL)
1212 {
1213 SCU_POWER->PWRSET = (uint32_t)SCU_POWER_PWRSET_HIB_Msk;
1214
1215 while((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0UL)
1216 {
1217 /* wait until HIB domain is enabled */
1218 }
1219 }
1220
1221 /* Remove the reset only if HIB domain were in a state of reset */
1222 if((SCU_RESET->RSTSTAT) & SCU_RESET_RSTSTAT_HIBRS_Msk)
1223 {
1224 SCU_RESET->RSTCLR = (uint32_t)SCU_RESET_RSTCLR_HIBRS_Msk;
1225 while((SCU_RESET->RSTSTAT & SCU_RESET_RSTSTAT_HIBRS_Msk) != 0UL)
1226 {
1227 /* wait until HIB domain is enabled */
1228 }
1229 }
1230 }
1231
1232 /* API to power down the hibernation domain */
XMC_SCU_HIB_DisableHibernateDomain(void)1233 void XMC_SCU_HIB_DisableHibernateDomain(void)
1234 {
1235 /* Disable hibernate domain */
1236 SCU_POWER->PWRCLR = (uint32_t)SCU_POWER_PWRCLR_HIB_Msk;
1237 /* Reset of hibernate domain reset */
1238 SCU_RESET->RSTSET = (uint32_t)SCU_RESET_RSTSET_HIBRS_Msk;
1239 }
1240
1241 /* API to check the hibernation domain is enabled or not */
XMC_SCU_HIB_IsHibernateDomainEnabled(void)1242 bool XMC_SCU_HIB_IsHibernateDomainEnabled(void)
1243 {
1244 return ((bool)(SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) &&
1245 !(bool)(SCU_RESET->RSTSTAT & SCU_RESET_RSTSTAT_HIBRS_Msk));
1246 }
1247
1248 /* API to enable internal slow clock - fOSI (32.768kHz) in hibernate domain */
XMC_SCU_HIB_EnableInternalSlowClock(void)1249 void XMC_SCU_HIB_EnableInternalSlowClock(void)
1250 {
1251 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_OSCSICTRL_Msk)
1252 {
1253 /* Wait until OSCSICTRL register in hibernate domain is ready to accept a write */
1254 }
1255 SCU_HIBERNATE->OSCSICTRL &= (uint32_t)~(SCU_HIBERNATE_OSCSICTRL_PWD_Msk);
1256 }
1257
1258 /* API to disable internal slow clock - fOSI (32.768kHz) in hibernate domain */
XMC_SCU_HIB_DisableInternalSlowClock(void)1259 void XMC_SCU_HIB_DisableInternalSlowClock(void)
1260 {
1261 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_OSCSICTRL_Msk)
1262 {
1263 /* Wait until OSCSICTRL register in hibernate domain is ready to accept a write */
1264 }
1265 SCU_HIBERNATE->OSCSICTRL |= (uint32_t)SCU_HIBERNATE_OSCSICTRL_PWD_Msk;
1266 }
1267
XMC_SCU_HIB_ClearEventStatus(int32_t event)1268 void XMC_SCU_HIB_ClearEventStatus(int32_t event)
1269 {
1270 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCLR_Msk)
1271 {
1272 /* Wait until HDCLR register in hibernate domain is ready to accept a write */
1273 }
1274 SCU_HIBERNATE->HDCLR = event;
1275 }
1276
XMC_SCU_HIB_TriggerEvent(int32_t event)1277 void XMC_SCU_HIB_TriggerEvent(int32_t event)
1278 {
1279 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDSET_Msk)
1280 {
1281 /* Wait until HDSET register in hibernate domain is ready to accept a write */
1282 }
1283 SCU_HIBERNATE->HDSET = event;
1284 }
1285
XMC_SCU_HIB_EnableEvent(int32_t event)1286 void XMC_SCU_HIB_EnableEvent(int32_t event)
1287 {
1288 #if (defined(DOXYGEN) || (UC_SERIES == XMC44) || (UC_SERIES == XMC42) || (UC_SERIES == XMC41))
1289 event = ((event & XMC_SCU_HIB_EVENT_LPAC_VBAT_POSEDGE) << (SCU_HIBERNATE_HDCR_VBATHI_Pos - SCU_HIBERNATE_HDSTAT_VBATPEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_VBAT_POSEDGE);
1290 event = ((event & XMC_SCU_HIB_EVENT_LPAC_VBAT_NEGEDGE) << (SCU_HIBERNATE_HDCR_VBATLO_Pos - SCU_HIBERNATE_HDSTAT_VBATNEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_VBAT_NEGEDGE);
1291 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_POSEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO0HI_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO0PEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_POSEDGE);
1292 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_NEGEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO0LO_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO0NEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_NEGEDGE);
1293 #if (defined(DOXYGEN) || ((UC_SERIES == XMC44) && (UC_PACKAGE == LQFP100)))
1294 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_POSEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO1HI_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO1PEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_POSEDGE);
1295 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_NEGEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO1LO_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO1NEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_NEGEDGE);
1296 #endif
1297 #endif
1298
1299 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1300 {
1301 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1302 }
1303 SCU_HIBERNATE->HDCR |= event;
1304 }
1305
XMC_SCU_HIB_DisableEvent(int32_t event)1306 void XMC_SCU_HIB_DisableEvent(int32_t event)
1307 {
1308 #if (defined(DOXYGEN) || (UC_SERIES == XMC44) || (UC_SERIES == XMC42) || (UC_SERIES == XMC41))
1309 event = ((event & XMC_SCU_HIB_EVENT_LPAC_VBAT_POSEDGE) << (SCU_HIBERNATE_HDCR_VBATHI_Pos - SCU_HIBERNATE_HDSTAT_VBATPEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_VBAT_POSEDGE);
1310 event = ((event & XMC_SCU_HIB_EVENT_LPAC_VBAT_NEGEDGE) << (SCU_HIBERNATE_HDCR_VBATLO_Pos - SCU_HIBERNATE_HDSTAT_VBATNEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_VBAT_NEGEDGE);
1311 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_POSEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO0HI_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO0PEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_POSEDGE);
1312 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_NEGEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO0LO_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO0NEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_0_NEGEDGE);
1313 #if (defined(DOXYGEN) || ((UC_SERIES == XMC44) && (UC_PACKAGE == LQFP100)))
1314 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_POSEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO1HI_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO1PEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_POSEDGE);
1315 event = ((event & XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_NEGEDGE) << (SCU_HIBERNATE_HDCR_AHIBIO1LO_Pos - SCU_HIBERNATE_HDSTAT_AHIBIO1NEV_Pos)) | (event & (uint32_t)~XMC_SCU_HIB_EVENT_LPAC_HIB_IO_1_NEGEDGE);
1316 #endif
1317 #endif
1318
1319 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1320 {
1321 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1322 }
1323 SCU_HIBERNATE->HDCR &= ~event;
1324 }
1325
XMC_SCU_HIB_EnterHibernateState(void)1326 void XMC_SCU_HIB_EnterHibernateState(void)
1327 {
1328 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1329 {
1330 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1331 }
1332 SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_HIB_Msk;
1333 }
1334
XMC_SCU_HIB_EnterHibernateStateEx(XMC_SCU_HIB_HIBERNATE_MODE_t mode)1335 void XMC_SCU_HIB_EnterHibernateStateEx(XMC_SCU_HIB_HIBERNATE_MODE_t mode)
1336 {
1337 if (mode == XMC_SCU_HIB_HIBERNATE_MODE_EXTERNAL)
1338 {
1339 XMC_SCU_HIB_EnterHibernateState();
1340 }
1341 #if ((UC_SERIES == XMC44) || (UC_SERIES == XMC42) || (UC_SERIES == XMC41))
1342 if (mode == XMC_SCU_HIB_HIBERNATE_MODE_INTERNAL)
1343 {
1344 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HINTSET_Msk)
1345 {
1346 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1347 }
1348 SCU_HIBERNATE->HINTSET = SCU_HIBERNATE_HINTSET_HIBNINT_Msk;
1349 }
1350 #endif
1351 }
1352
XMC_SCU_HIB_SetWakeupTriggerInput(XMC_SCU_HIB_IO_t pin)1353 void XMC_SCU_HIB_SetWakeupTriggerInput(XMC_SCU_HIB_IO_t pin)
1354 {
1355 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1356 {
1357 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1358 }
1359
1360 if (pin == XMC_SCU_HIB_IO_0)
1361 {
1362 SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_WKUPSEL_Msk;
1363 }
1364 else
1365 {
1366 SCU_HIBERNATE->HDCR &= ~SCU_HIBERNATE_HDCR_WKUPSEL_Msk;
1367 }
1368 }
1369
XMC_SCU_HIB_SetPinMode(XMC_SCU_HIB_IO_t pin,XMC_SCU_HIB_PIN_MODE_t mode)1370 void XMC_SCU_HIB_SetPinMode(XMC_SCU_HIB_IO_t pin, XMC_SCU_HIB_PIN_MODE_t mode)
1371 {
1372 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1373 {
1374 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1375 }
1376 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & ~(SCU_HIBERNATE_HDCR_HIBIO0SEL_Msk << (SCU_HIBERNATE_HDCR_HIBIOSEL_Size * pin))) |
1377 (mode << (SCU_HIBERNATE_HDCR_HIBIOSEL_Size * pin));
1378 }
1379
XMC_SCU_HIB_SetPinOutputLevel(XMC_SCU_HIB_IO_t pin,XMC_SCU_HIB_IO_OUTPUT_LEVEL_t level)1380 void XMC_SCU_HIB_SetPinOutputLevel(XMC_SCU_HIB_IO_t pin, XMC_SCU_HIB_IO_OUTPUT_LEVEL_t level)
1381 {
1382 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1383 {
1384 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1385 }
1386 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & ~(SCU_HIBERNATE_HDCR_HIBIO0POL_Msk << pin)) |
1387 (level << pin);
1388 }
1389
XMC_SCU_HIB_SetInput0(XMC_SCU_HIB_IO_t pin)1390 void XMC_SCU_HIB_SetInput0(XMC_SCU_HIB_IO_t pin)
1391 {
1392 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1393 {
1394 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1395 }
1396
1397 if (pin == XMC_SCU_HIB_IO_0)
1398 {
1399 SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_GPI0SEL_Msk;
1400 }
1401 else
1402 {
1403 SCU_HIBERNATE->HDCR &= ~SCU_HIBERNATE_HDCR_GPI0SEL_Msk;
1404 }
1405 }
1406
XMC_SCU_HIB_SetSR0Input(XMC_SCU_HIB_SR0_INPUT_t input)1407 void XMC_SCU_HIB_SetSR0Input(XMC_SCU_HIB_SR0_INPUT_t input)
1408 {
1409 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1410 {
1411 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1412 }
1413 #if ((UC_SERIES == XMC44) || (UC_SERIES == XMC42) || (UC_SERIES == XMC41))
1414 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & (uint32_t)~(SCU_HIBERNATE_HDCR_GPI0SEL_Msk | SCU_HIBERNATE_HDCR_ADIG0SEL_Msk)) |
1415 #else
1416 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & (uint32_t)~(SCU_HIBERNATE_HDCR_GPI0SEL_Msk)) |
1417 #endif
1418 input;
1419 }
1420
1421 #if ((UC_SERIES == XMC44) || (UC_SERIES == XMC42) || (UC_SERIES == XMC41))
1422
1423 #if ((UC_SERIES == XMC44) && (UC_PACKAGE == LQFP100))
XMC_SCU_HIB_SetSR1Input(XMC_SCU_HIB_SR1_INPUT_t input)1424 void XMC_SCU_HIB_SetSR1Input(XMC_SCU_HIB_SR1_INPUT_t input)
1425 {
1426 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_HDCR_Msk)
1427 {
1428 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1429 }
1430 SCU_HIBERNATE->HDCR = (SCU_HIBERNATE->HDCR & (uint32_t)~(SCU_HIBERNATE_HDCR_GPI1SEL_Msk | SCU_HIBERNATE_HDCR_ADIG1SEL_Msk | SCU_HIBERNATE_HDCR_XTALGPI1SEL_Msk)) |
1431 input;
1432 }
1433 #endif
1434
XMC_SCU_HIB_LPAC_SetInput(XMC_SCU_HIB_LPAC_INPUT_t input)1435 void XMC_SCU_HIB_LPAC_SetInput(XMC_SCU_HIB_LPAC_INPUT_t input)
1436 {
1437 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACCONF_Msk)
1438 {
1439 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1440 }
1441 SCU_HIBERNATE->LPACCONF = (SCU_HIBERNATE->LPACCONF & (uint32_t)~SCU_HIBERNATE_LPACCONF_CMPEN_Msk) |
1442 input;
1443 }
1444
XMC_SCU_HIB_LPAC_SetTrigger(XMC_SCU_HIB_LPAC_TRIGGER_t trigger)1445 void XMC_SCU_HIB_LPAC_SetTrigger(XMC_SCU_HIB_LPAC_TRIGGER_t trigger)
1446 {
1447 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACCONF_Msk)
1448 {
1449 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1450 }
1451 SCU_HIBERNATE->LPACCONF = (SCU_HIBERNATE->LPACCONF & (uint32_t)~SCU_HIBERNATE_LPACCONF_TRIGSEL_Msk) |
1452 trigger;
1453 }
1454
XMC_SCU_HIB_LPAC_SetTiming(bool enable_delay,uint16_t interval_count,uint8_t settle_count)1455 void XMC_SCU_HIB_LPAC_SetTiming(bool enable_delay, uint16_t interval_count, uint8_t settle_count)
1456 {
1457 uint32_t config = 0;
1458
1459 if (enable_delay)
1460 {
1461 config = SCU_HIBERNATE_LPACCONF_CONVDEL_Msk;
1462 }
1463
1464 config |= interval_count << SCU_HIBERNATE_LPACCONF_INTERVCNT_Pos;
1465 config |= settle_count << SCU_HIBERNATE_LPACCONF_SETTLECNT_Pos;
1466
1467 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACCONF_Msk)
1468 {
1469 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1470 }
1471
1472 SCU_HIBERNATE->LPACCONF = (SCU_HIBERNATE->LPACCONF & (uint32_t)~(SCU_HIBERNATE_LPACCONF_CONVDEL_Msk |
1473 SCU_HIBERNATE_LPACCONF_INTERVCNT_Msk |
1474 SCU_HIBERNATE_LPACCONF_SETTLECNT_Msk)) |
1475 config;
1476
1477 }
1478
XMC_SCU_HIB_LPAC_SetVBATThresholds(uint8_t lower,uint8_t upper)1479 void XMC_SCU_HIB_LPAC_SetVBATThresholds(uint8_t lower, uint8_t upper)
1480 {
1481
1482 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACTH0_Msk)
1483 {
1484 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1485 }
1486
1487 SCU_HIBERNATE->LPACTH0 = (lower << SCU_HIBERNATE_LPACTH0_VBATLO_Pos) | (upper << SCU_HIBERNATE_LPACTH0_VBATHI_Pos);
1488
1489
1490
1491 }
1492
XMC_SCU_HIB_LPAC_SetHIBIO0Thresholds(uint8_t lower,uint8_t upper)1493 void XMC_SCU_HIB_LPAC_SetHIBIO0Thresholds(uint8_t lower, uint8_t upper)
1494 {
1495
1496 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACTH1_Msk)
1497 {
1498 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1499 }
1500
1501 SCU_HIBERNATE->LPACTH1 = (SCU_HIBERNATE->LPACTH1 & (uint32_t)~(SCU_HIBERNATE_LPACTH1_AHIBIO0LO_Msk | SCU_HIBERNATE_LPACTH1_AHIBIO0HI_Msk)) |
1502 (lower << SCU_HIBERNATE_LPACTH1_AHIBIO0LO_Pos) |
1503 (upper << SCU_HIBERNATE_LPACTH1_AHIBIO0HI_Pos);
1504
1505 }
1506 #if ((UC_SERIES == XMC44) && (UC_PACKAGE == LQFP100))
XMC_SCU_HIB_LPAC_SetHIBIO1Thresholds(uint8_t lower,uint8_t upper)1507 void XMC_SCU_HIB_LPAC_SetHIBIO1Thresholds(uint8_t lower, uint8_t upper)
1508 {
1509
1510 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACTH1_Msk)
1511 {
1512 /* Wait until HDCR register in hibernate domain is ready to accept a write */
1513 }
1514
1515 SCU_HIBERNATE->LPACTH1 = (SCU_HIBERNATE->LPACTH1 & (uint32_t)~(SCU_HIBERNATE_LPACTH1_AHIBIO1LO_Msk | SCU_HIBERNATE_LPACTH1_AHIBIO1HI_Msk)) |
1516 (lower << SCU_HIBERNATE_LPACTH1_AHIBIO1LO_Pos) |
1517 (upper << SCU_HIBERNATE_LPACTH1_AHIBIO1HI_Pos);
1518
1519 }
1520 #endif
XMC_SCU_HIB_LPAC_GetStatus(void)1521 int32_t XMC_SCU_HIB_LPAC_GetStatus(void)
1522 {
1523 return SCU_HIBERNATE->LPACST;
1524 }
1525
XMC_SCU_HIB_LPAC_ClearStatus(int32_t status)1526 void XMC_SCU_HIB_LPAC_ClearStatus(int32_t status)
1527 {
1528 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACCLR_Msk)
1529 {
1530 /* Wait until LPACCLR register in hibernate domain is ready to accept a write */
1531 }
1532 SCU_HIBERNATE->LPACCLR = status;;
1533 }
1534
XMC_SCU_HIB_LPAC_TriggerCompare(XMC_SCU_HIB_LPAC_INPUT_t input)1535 void XMC_SCU_HIB_LPAC_TriggerCompare(XMC_SCU_HIB_LPAC_INPUT_t input)
1536 {
1537 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_LPACSET_Msk)
1538 {
1539 /* Wait until LPACSET register in hibernate domain is ready to accept a write */
1540 }
1541
1542 SCU_HIBERNATE->LPACSET = input;
1543 }
1544
1545 #endif
1546
XMC_SCU_CLOCK_IsLowPowerOscillatorStable(void)1547 bool XMC_SCU_CLOCK_IsLowPowerOscillatorStable(void)
1548 {
1549 return ((SCU_HIBERNATE->HDSTAT & SCU_HIBERNATE_HDSTAT_ULPWDG_Msk) == 0UL);
1550 }
1551
1552 /* API to configure the 32khz Ultra Low Power oscillator */
XMC_SCU_CLOCK_EnableLowPowerOscillator(void)1553 void XMC_SCU_CLOCK_EnableLowPowerOscillator(void)
1554 {
1555 /* Enable OSC_ULP */
1556 XMC_SCU_INTERRUPT_ClearEventStatus(XMC_SCU_INTERRUPT_EVENT_OSCULCTRL_UPDATED);
1557 SCU_HIBERNATE->OSCULCTRL &= ~SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
1558 while ((XMC_SCU_INTERUPT_GetEventStatus() & XMC_SCU_INTERRUPT_EVENT_OSCULCTRL_UPDATED) == 0);
1559
1560 /* Clear ULP WDG status */
1561 XMC_SCU_INTERRUPT_ClearEventStatus(XMC_SCU_INTERRUPT_EVENT_HDCLR_UPDATED);
1562 SCU_HIBERNATE->HDCLR = (uint32_t)SCU_HIBERNATE_HDCLR_ULPWDG_Msk;
1563 while ((XMC_SCU_INTERUPT_GetEventStatus() & XMC_SCU_INTERRUPT_EVENT_HDCLR_UPDATED) == 0);
1564
1565 /* Enable ULP WDG */
1566 XMC_SCU_INTERRUPT_ClearEventStatus(XMC_SCU_INTERRUPT_EVENT_HDCR_UPDATED);
1567 SCU_HIBERNATE->HDCR |= (uint32_t)SCU_HIBERNATE_HDCR_ULPWDGEN_Msk;
1568 while ((XMC_SCU_INTERUPT_GetEventStatus() & XMC_SCU_INTERRUPT_EVENT_HDCR_UPDATED) == 0);
1569 }
1570
1571 /* API to configure the 32khz Ultra Low Power oscillator */
XMC_SCU_CLOCK_DisableLowPowerOscillator(void)1572 void XMC_SCU_CLOCK_DisableLowPowerOscillator(void)
1573 {
1574 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
1575 {
1576 /* Wait until OSCULCTRL register in hibernate domain is ready to accept a write */
1577 }
1578 SCU_HIBERNATE->OSCULCTRL |= (uint32_t)SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
1579 }
1580
XMC_SCU_CLOCK_EnableLowPowerOscillatorGeneralPurposeInput(void)1581 void XMC_SCU_CLOCK_EnableLowPowerOscillatorGeneralPurposeInput(void)
1582 {
1583 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
1584 {
1585 /* Wait until OSCULCTRL register in hibernate domain is ready to accept a write */
1586 }
1587 SCU_HIBERNATE->OSCULCTRL |= SCU_HIBERNATE_OSCULCTRL_X1DEN_Msk | SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
1588 }
1589
XMC_SCU_CLOCK_DisableLowPowerOscillatorGeneralPurposeInput(void)1590 void XMC_SCU_CLOCK_DisableLowPowerOscillatorGeneralPurposeInput(void)
1591 {
1592 while((SCU_GENERAL->MIRRSTS) & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
1593 {
1594 /* Wait until OSCULCTRL register in hibernate domain is ready to accept a write */
1595 }
1596 SCU_HIBERNATE->OSCULCTRL = (SCU_HIBERNATE->OSCULCTRL & ~(uint32_t)(SCU_HIBERNATE_OSCULCTRL_X1DEN_Msk | SCU_HIBERNATE_OSCULCTRL_MODE_Msk)) |
1597 (SCU_HIBERNATE_OSCULCTRL_MODE_OSC_POWER_DOWN << SCU_HIBERNATE_OSCULCTRL_MODE_Pos);
1598 }
1599
XMC_SCU_CLOCK_GetLowPowerOscillatorGeneralPurposeInputStatus(void)1600 uint32_t XMC_SCU_CLOCK_GetLowPowerOscillatorGeneralPurposeInputStatus(void)
1601 {
1602 return (SCU_HIBERNATE->OSCULSTAT & SCU_HIBERNATE_OSCULSTAT_X1D_Msk);
1603 }
1604
1605 /* API to enable High Precision High Speed oscillator */
XMC_SCU_CLOCK_EnableHighPerformanceOscillator(void)1606 void XMC_SCU_CLOCK_EnableHighPerformanceOscillator(void)
1607 {
1608 SCU_PLL->PLLCON0 &= (uint32_t)~SCU_PLL_PLLCON0_PLLPWD_Msk;
1609
1610 SCU_OSC->OSCHPCTRL = (uint32_t)((SCU_OSC->OSCHPCTRL & ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk)) |
1611 (((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos));
1612
1613 /* restart OSC Watchdog */
1614 SCU_PLL->PLLCON0 &= (uint32_t)~SCU_PLL_PLLCON0_OSCRES_Msk;
1615 }
1616
XMC_SCU_CLOCK_IsHighPerformanceOscillatorStable(void)1617 bool XMC_SCU_CLOCK_IsHighPerformanceOscillatorStable(void)
1618 {
1619 return ((SCU_PLL->PLLSTAT & XMC_SCU_PLL_PLLSTAT_OSC_USABLE) == XMC_SCU_PLL_PLLSTAT_OSC_USABLE);
1620 }
1621
1622 /* API to disable High Precision High Speed oscillator */
XMC_SCU_CLOCK_DisableHighPerformanceOscillator(void)1623 void XMC_SCU_CLOCK_DisableHighPerformanceOscillator(void)
1624 {
1625 SCU_OSC->OSCHPCTRL |= (uint32_t)SCU_OSC_OSCHPCTRL_MODE_Msk;
1626 }
1627
XMC_SCU_CLOCK_EnableHighPerformanceOscillatorGeneralPurposeInput(void)1628 void XMC_SCU_CLOCK_EnableHighPerformanceOscillatorGeneralPurposeInput(void)
1629 {
1630 SCU_OSC->OSCHPCTRL |= SCU_OSC_OSCHPCTRL_X1DEN_Msk;
1631 }
1632
XMC_SCU_CLOCK_DisableHighPerformanceOscillatorGeneralPurposeInput(void)1633 void XMC_SCU_CLOCK_DisableHighPerformanceOscillatorGeneralPurposeInput(void)
1634 {
1635 SCU_OSC->OSCHPCTRL &= ~SCU_OSC_OSCHPCTRL_X1DEN_Msk;
1636 }
1637
XMC_SCU_CLOCK_GetHighPerformanceOscillatorGeneralPurposeInputStatus(void)1638 uint32_t XMC_SCU_CLOCK_GetHighPerformanceOscillatorGeneralPurposeInputStatus(void)
1639 {
1640 return (SCU_OSC->OSCHPSTAT & SCU_OSC_OSCHPSTAT_X1D_Msk);
1641 }
1642
1643 /* API to enable main PLL */
XMC_SCU_CLOCK_EnableSystemPll(void)1644 void XMC_SCU_CLOCK_EnableSystemPll(void)
1645 {
1646 SCU_PLL->PLLCON0 &= (uint32_t)~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
1647 }
1648
1649 /* API to disable main PLL */
XMC_SCU_CLOCK_DisableSystemPll(void)1650 void XMC_SCU_CLOCK_DisableSystemPll(void)
1651 {
1652 SCU_PLL->PLLCON0 |= (uint32_t)(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
1653 }
1654
1655 /* API to configure main PLL */
XMC_SCU_CLOCK_StartSystemPll(XMC_SCU_CLOCK_SYSPLLCLKSRC_t source,XMC_SCU_CLOCK_SYSPLL_MODE_t mode,uint32_t pdiv,uint32_t ndiv,uint32_t kdiv)1656 void XMC_SCU_CLOCK_StartSystemPll(XMC_SCU_CLOCK_SYSPLLCLKSRC_t source,
1657 XMC_SCU_CLOCK_SYSPLL_MODE_t mode,
1658 uint32_t pdiv,
1659 uint32_t ndiv,
1660 uint32_t kdiv)
1661 {
1662
1663 uint32_t vco_frequency; /* Q10.22, max VCO frequency = 520MHz */
1664 uint32_t kdiv_temp;
1665
1666 XMC_SCU_CLOCK_SetSystemPllClockSource(source);
1667
1668 if (mode == XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL)
1669 {
1670 /* Calculate initial step to be close to fOFI */
1671 if (source == XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP)
1672 {
1673 vco_frequency = (OSCHP_GetFrequency() / 1000000U) << 22;
1674 }
1675 else
1676 {
1677 vco_frequency = (OFI_FREQUENCY / 1000000U) << 22;
1678 }
1679 vco_frequency = ((vco_frequency * ndiv) / pdiv);
1680 kdiv_temp = (vco_frequency / (OFI_FREQUENCY / 1000000U)) >> 22;
1681
1682 /* Switch to prescaler mode */
1683 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_VCOBYP_Msk;
1684
1685 /* disconnect Oscillator from PLL */
1686 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_FINDIS_Msk;
1687
1688 /* Setup divider settings for main PLL */
1689 SCU_PLL->PLLCON1 = (uint32_t)((SCU_PLL->PLLCON1 & ~(SCU_PLL_PLLCON1_NDIV_Msk | SCU_PLL_PLLCON1_K2DIV_Msk |
1690 SCU_PLL_PLLCON1_PDIV_Msk)) | ((ndiv - 1UL) << SCU_PLL_PLLCON1_NDIV_Pos) |
1691 ((kdiv_temp - 1UL) << SCU_PLL_PLLCON1_K2DIV_Pos) |
1692 ((pdiv - 1UL)<< SCU_PLL_PLLCON1_PDIV_Pos));
1693
1694 /* Set OSCDISCDIS, OSC clock remains connected to the VCO in case of loss of lock */
1695 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
1696
1697 /* connect Oscillator to PLL */
1698 SCU_PLL->PLLCON0 &= (uint32_t)~SCU_PLL_PLLCON0_FINDIS_Msk;
1699
1700 /* restart PLL Lock detection */
1701 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_RESLD_Msk;
1702 while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
1703 {
1704 /* wait for PLL Lock */
1705 }
1706
1707 /* Switch to normal mode */
1708 SCU_PLL->PLLCON0 &= (uint32_t)~SCU_PLL_PLLCON0_VCOBYP_Msk;
1709 while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) != 0U)
1710 {
1711 /* wait for normal mode */
1712 }
1713
1714 /* Ramp up PLL frequency in steps */
1715 kdiv_temp = (vco_frequency / 60UL) >> 22;
1716 if (kdiv < kdiv_temp)
1717 {
1718 XMC_SCU_CLOCK_StepSystemPllFrequency(kdiv_temp);
1719 }
1720
1721 kdiv_temp = (vco_frequency / 90UL) >> 22;
1722 if (kdiv < kdiv_temp)
1723 {
1724 XMC_SCU_CLOCK_StepSystemPllFrequency(kdiv_temp);
1725 }
1726
1727 XMC_SCU_CLOCK_StepSystemPllFrequency(kdiv);
1728 }
1729 else
1730 {
1731 SCU_PLL->PLLCON1 = (uint32_t)((SCU_PLL->PLLCON1 & ~SCU_PLL_PLLCON1_K1DIV_Msk) |
1732 ((kdiv -1UL) << SCU_PLL_PLLCON1_K1DIV_Pos));
1733
1734 /* Switch to prescaler mode */
1735 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_VCOBYP_Msk;
1736
1737 while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) == 0U)
1738 {
1739 /* wait for prescaler mode */
1740 }
1741 }
1742 }
1743
1744 /* API to stop main PLL operation */
XMC_SCU_CLOCK_StopSystemPll(void)1745 void XMC_SCU_CLOCK_StopSystemPll(void)
1746 {
1747 SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_PLLPWD_Msk;
1748 }
1749
1750 /* API to step up/down the main PLL frequency */
XMC_SCU_CLOCK_StepSystemPllFrequency(uint32_t kdiv)1751 void XMC_SCU_CLOCK_StepSystemPllFrequency(uint32_t kdiv)
1752 {
1753 SCU_PLL->PLLCON1 = (uint32_t)((SCU_PLL->PLLCON1 & ~SCU_PLL_PLLCON1_K2DIV_Msk) |
1754 ((kdiv - 1UL) << SCU_PLL_PLLCON1_K2DIV_Pos));
1755
1756 XMC_SCU_lDelay(50U);
1757 }
1758
1759 /* API to check main PLL is locked or not */
XMC_SCU_CLOCK_IsSystemPllLocked(void)1760 bool XMC_SCU_CLOCK_IsSystemPllLocked(void)
1761 {
1762 return (bool)((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) != 0UL);
1763 }
1764
1765 /*
1766 * API to assign the event handler function to be executed on occurrence of the selected event.
1767 */
XMC_SCU_INTERRUPT_SetEventHandler(const XMC_SCU_INTERRUPT_EVENT_t event,const XMC_SCU_INTERRUPT_EVENT_HANDLER_t handler)1768 XMC_SCU_STATUS_t XMC_SCU_INTERRUPT_SetEventHandler(const XMC_SCU_INTERRUPT_EVENT_t event,
1769 const XMC_SCU_INTERRUPT_EVENT_HANDLER_t handler)
1770 {
1771 uint32_t index;
1772 XMC_SCU_STATUS_t status;
1773
1774 index = 0U;
1775 while (((event & ((XMC_SCU_INTERRUPT_EVENT_t)1 << index)) == 0U) && (index < XMC_SCU_INTERRUPT_EVENT_MAX))
1776 {
1777 index++;
1778 }
1779
1780 if (index == XMC_SCU_INTERRUPT_EVENT_MAX)
1781 {
1782 status = XMC_SCU_STATUS_ERROR;
1783 }
1784 else
1785 {
1786 event_handler_list[index] = handler;
1787 status = XMC_SCU_STATUS_OK;
1788 }
1789
1790 return (status);
1791 }
1792
1793 /*
1794 * API to execute callback functions for multiple events.
1795 */
XMC_SCU_IRQHandler(uint32_t sr_num)1796 void XMC_SCU_IRQHandler(uint32_t sr_num)
1797 {
1798 uint32_t index;
1799 XMC_SCU_INTERRUPT_EVENT_t event;
1800 XMC_SCU_INTERRUPT_EVENT_HANDLER_t event_handler;
1801
1802 XMC_UNUSED_ARG(sr_num);
1803
1804 index = 0U;
1805 event = XMC_SCU_INTERUPT_GetEventStatus();
1806 while (index < XMC_SCU_INTERRUPT_EVENT_MAX)
1807 {
1808 if ((event & ((XMC_SCU_INTERRUPT_EVENT_t)1 << index)) != 0U)
1809 {
1810 event_handler = event_handler_list[index];
1811 if (event_handler != NULL)
1812 {
1813 (event_handler)();
1814 }
1815
1816 XMC_SCU_INTERRUPT_ClearEventStatus((uint32_t)(1UL << index));
1817
1818 break;
1819 }
1820 index++;
1821 }
1822 }
1823
1824 #endif /* UC_FAMILY == XMC4 */
1825