1 /*********************************************************************************************************************
2  * @file     system_XMC4700.c
3  * @brief    CMSIS Cortex-M4 Device Peripheral Access Layer Header File for the Infineon XMC4700 Device Series
4  * @version  V1.0.6
5  * @date     29. Oct 2018
6  *
7  * @cond
8  *********************************************************************************************************************
9  * Copyright (c) 2015-2018, 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  ********************** Version History ***************************************
37  * V1.0.0, 03. Sep 2015, Initial version
38  * V1.0.1, 26. Jan 2016, Disable trap generation from clock unit
39  * V1.0.2, 01. Jun 2016, Fix masking of OSCHPCTRL value
40  * V1.0.3, 09. Feb 2017, Fix activation of USBPLL when SDMMC clock is enabled
41  * V1.0.4, 19. Jun 2017, Rely on cmsis_compiler.h instead of defining __WEAK
42  *                       Added support for ARM Compiler 6 (armclang)
43  * V1.0.5, 26. Sep 2017, Disable FPU if FPU_USED is zero
44  * V1.0.6, 29. Oct 2018, Fix variable location of SystemCoreClock and g_chipid for ARMCC compiler
45  ******************************************************************************
46  * @endcond
47  */
48 
49 /*******************************************************************************
50  * Default clock initialization
51  * fPLL = 288MHz => fSYS = 144MHz => fCPU = 144MHz
52  *                                => fPB  = 144MHz
53  *                                => fCCU = 144MHz
54  *                                => fETH = 72MHz
55  *               => fUSB = 48MHz
56  *               => fEBU = 72MHz
57  *
58  * fUSBPLL Disabled, only enabled if SCU_CLK_USBCLKCR_USBSEL_USBPLL is selected
59  *
60  * fOFI = 24MHz => fWDT = 24MHz
61  *******************************************************************************/
62 
63 /*******************************************************************************
64  * HEADER FILES
65  *******************************************************************************/
66 #include <string.h>
67 
68 #include <XMC4700.h>
69 #include "system_XMC4700.h"
70 
71 /*******************************************************************************
72  * MACROS
73  *******************************************************************************/
74 #define CHIPID_LOC ((uint8_t *)0x20000000UL)
75 
76 #define PMU_FLASH_WS          (0x4U)
77 
78 #define FOSCREF               (2500000U)
79 
80 #define DELAY_CNT_50US_50MHZ  (2500UL)
81 #define DELAY_CNT_150US_50MHZ (7500UL)
82 #define DELAY_CNT_50US_48MHZ  (2400UL)
83 #define DELAY_CNT_50US_72MHZ  (3600UL)
84 #define DELAY_CNT_50US_96MHZ  (4800UL)
85 #define DELAY_CNT_50US_120MHZ (6000UL)
86 #define DELAY_CNT_50US_144MHZ (7200UL)
87 
88 #define SCU_PLL_PLLSTAT_OSC_USABLE  (SCU_PLL_PLLSTAT_PLLHV_Msk | \
89                                      SCU_PLL_PLLSTAT_PLLLV_Msk | \
90                                      SCU_PLL_PLLSTAT_PLLSP_Msk)
91 
92 /*
93 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
94 */
95 
96 /*
97 // <h> Clock configuration
98 */
99 
100 /*
101 //    <o> External crystal frequency [Hz]
102 //       <8000000=> 8MHz
103 //       <12000000=> 12MHz
104 //       <16000000=> 16MHz
105 //    <i> Defines external crystal frequency
106 //    <i> Default: 8MHz
107 */
108 #define OSCHP_FREQUENCY (12000000U)
109 
110 /* USB PLL settings, fUSBPLL = 48MHz and fUSBPLLVCO = 384 MHz */
111 /* Note: Implicit divider of 2 and fUSBPLLVCO >= 260 MHz and fUSBPLLVCO <= 520 MHz*/
112 #if OSCHP_FREQUENCY == 8000000U
113 #define USB_PDIV (1U)
114 #define USB_NDIV (95U)
115 
116 #elif OSCHP_FREQUENCY == 12000000U
117 #define USB_PDIV (1U)
118 #define USB_NDIV (63U)
119 
120 #elif OSCHP_FREQUENCY == 16000000U
121 #define USB_PDIV (1U)
122 #define USB_NDIV (47U)
123 
124 #else
125 #error "External crystal frequency not supported"
126 
127 #endif
128 
129 /*
130 //    <o> Backup clock calibration mode
131 //       <0=> Factory calibration
132 //       <1=> Automatic calibration
133 //    <i> Default: Automatic calibration
134 */
135 #define FOFI_CALIBRATION_MODE 1
136 #define FOFI_CALIBRATION_MODE_FACTORY 0
137 #define FOFI_CALIBRATION_MODE_AUTOMATIC 1
138 
139 /*
140 //    <o> Standby clock (fSTDBY) source selection
141 //       <0=> Internal slow oscillator (32768Hz)
142 //       <1=> External crystal (32768Hz)
143 //    <i> Default: Internal slow oscillator (32768Hz)
144 */
145 #define STDBY_CLOCK_SRC 0
146 #define STDBY_CLOCK_SRC_OSI 0
147 #define STDBY_CLOCK_SRC_OSCULP 1
148 
149 /*
150 //    <o> PLL clock source selection
151 //       <0=> External crystal
152 //       <1=> Internal fast oscillator
153 //    <i> Default: External crystal
154 */
155 #define PLL_CLOCK_SRC 0
156 #define PLL_CLOCK_SRC_EXT_XTAL 0
157 #define PLL_CLOCK_SRC_OFI 1
158 
159 /* PLL settings, fPLL = 288MHz */
160 #if PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL
161 #if OSCHP_FREQUENCY == 8000000U
162 #define PLL_PDIV (1U)
163 #define PLL_NDIV (71U)
164 #define PLL_K2DIV (0U)
165 
166 #elif OSCHP_FREQUENCY == 12000000U
167 #define PLL_PDIV (1U)
168 #define PLL_NDIV (47U)
169 #define PLL_K2DIV (0U)
170 
171 #elif OSCHP_FREQUENCY == 16000000U
172 #define PLL_PDIV (1U)
173 #define PLL_NDIV (35U)
174 #define PLL_K2DIV (0U)
175 
176 #else
177 #error "External crystal frequency not supported"
178 
179 #endif
180 
181 #define VCO ((OSCHP_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
182 
183 #else /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL */
184 #define PLL_PDIV (1U)
185 #define PLL_NDIV (23U)
186 #define PLL_K2DIV (0U)
187 
188 #define VCO ((OFI_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
189 
190 #endif /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_OFI */
191 
192 #define PLL_K2DIV_24MHZ  ((VCO / OFI_FREQUENCY) - 1UL)
193 #define PLL_K2DIV_48MHZ  ((VCO / 48000000U) - 1UL)
194 #define PLL_K2DIV_72MHZ  ((VCO / 72000000U) - 1UL)
195 #define PLL_K2DIV_96MHZ  ((VCO / 96000000U) - 1UL)
196 #define PLL_K2DIV_120MHZ ((VCO / 120000000U) - 1UL)
197 
198 #define SCU_CLK_CLKCLR_ENABLE_USBCLK SCU_CLK_CLKCLR_USBCDI_Msk
199 #define SCU_CLK_CLKCLR_ENABLE_MMCCLK SCU_CLK_CLKCLR_MMCCDI_Msk
200 #define SCU_CLK_CLKCLR_ENABLE_ETHCLK SCU_CLK_CLKCLR_ETH0CDI_Msk
201 #define SCU_CLK_CLKCLR_ENABLE_EBUCLK SCU_CLK_CLKCLR_EBUCDI_Msk
202 #define SCU_CLK_CLKCLR_ENABLE_CCUCLK SCU_CLK_CLKCLR_CCUCDI_Msk
203 #define SCU_CLK_CLKCLR_ENABLE_WDTCLK SCU_CLK_CLKCLR_WDTCDI_Msk
204 
205 #define SCU_CLK_SYSCLKCR_SYSSEL_OFI      (0U << SCU_CLK_SYSCLKCR_SYSSEL_Pos)
206 #define SCU_CLK_SYSCLKCR_SYSSEL_PLL      (1U << SCU_CLK_SYSCLKCR_SYSSEL_Pos)
207 
208 #define SCU_CLK_USBCLKCR_USBSEL_USBPLL   (0U << SCU_CLK_USBCLKCR_USBSEL_Pos)
209 #define SCU_CLK_USBCLKCR_USBSEL_PLL      (1U << SCU_CLK_USBCLKCR_USBSEL_Pos)
210 
211 #define SCU_CLK_WDTCLKCR_WDTSEL_OFI      (0U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
212 #define SCU_CLK_WDTCLKCR_WDTSEL_STANDBY  (1U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
213 #define SCU_CLK_WDTCLKCR_WDTSEL_PLL      (2U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
214 
215 #define SCU_CLK_EXTCLKCR_ECKSEL_SYS      (0U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
216 #define SCU_CLK_EXTCLKCR_ECKSEL_USBPLL   (2U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
217 #define SCU_CLK_EXTCLKCR_ECKSEL_PLL      (3U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
218 
219 #define EXTCLK_PIN_P0_8  (1)
220 #define EXTCLK_PIN_P1_15 (2)
221 
222 /*
223 //    <h> Clock tree
224 //        <o1.16> System clock source selection
225 //                      <0=> fOFI
226 //                      <1=> fPLL
227 //                      <i> Default: fPLL
228 //        <o1.0..7> System clock divider <1-256><#-1>
229 //                      <i> Default: 2
230 //        <o2.0> CPU clock divider
231 //                      <0=> fCPU = fSYS
232 //                      <1=> fCPU = fSYS / 2
233 //                      <i> Default: fCPU = fSYS
234 //        <o3.0>  Peripheral clock divider
235 //                      <0=> fPB = fCPU
236 //                      <1=> fPB = fCPU / 2
237 //                      <i> Default: fPB = fCPU
238 //        <o4.0>  CCU clock divider
239 //                      <0=> fCCU = fCPU
240 //                      <1=> fCCU = fCPU / 2
241 //                      <i> Default: fCCU = fCPU
242 //        <e.5> Enable WDT clock
243 //             <o5.16..17> WDT clock source <0=> fOFI
244 //                                          <1=> fSTDBY
245 //                                          <2=> fPLL
246 //                      <i> Default: fOFI
247 //             <o5.0..7> WDT clock divider <1-256><#-1>
248 //                      <i> Default: 1
249 //        </e>
250 //        <e.3> Enable EBU clock
251 //             <o6.0..5>  EBU clock divider  <1-64><#-1>
252 //             <i> Default: 4
253 //        </e>
254 //        <e.2> Enable ETH clock
255 //        </e>
256 //        <e.1> Enable MMC clock
257 //        </e>
258 //        <e.0> Enable USB clock
259 //             <o7.16> USB clock source <0=> fUSBPLL
260 //                                      <1=> fPLL
261 //             <i> Default: fPLL
262 //        </e>
263 //        <e8> Enable external clock
264 //             <o8.0..1> External Clock Source Selection
265 //                  <0=> fSYS
266 //                  <2=> fUSB
267 //                  <3=> fPLL
268 //                  <i> Default: fPLL
269 //             <o8.16..24> External Clock divider <1-512><#-1>
270 //                  <i> Default: 288
271 //                  <i> Only valid for USB PLL and PLL clocks
272 //             <o9.0> External Clock Pin Selection
273 //                  <0=> Disabled
274 //                  <1=> P0.8
275 //                  <2=> P1.15
276 //                  <i> Default: Disabled
277 //        </e>
278 //    </h>
279 */
280 #define __CLKSET    (0x00000000UL)
281 #define __SYSCLKCR  (0x00010001UL)
282 #define __CPUCLKCR  (0x00000000UL)
283 #define __PBCLKCR   (0x00000000UL)
284 #define __CCUCLKCR  (0x00000000UL)
285 #define __WDTCLKCR  (0x00000000UL)
286 #define __EBUCLKCR  (0x00000003UL)
287 #define __USBCLKCR  (0x00010000UL)
288 
289 #define __EXTCLKCR (0x01200003UL)
290 #define __EXTCLKPIN (0U)
291 
292 /*
293 // </h>
294 */
295 
296 /*
297 //-------- <<< end of configuration section >>> ------------------
298 */
299 
300 #define ENABLE_PLL \
301     (((__SYSCLKCR & SCU_CLK_SYSCLKCR_SYSSEL_Msk) == SCU_CLK_SYSCLKCR_SYSSEL_PLL) || \
302      ((__CLKSET & SCU_CLK_CLKSET_EBUCEN_Msk) != 0) || \
303      (((__CLKSET & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_PLL)) || \
304      (((__CLKSET & SCU_CLK_CLKSET_WDTCEN_Msk) != 0) && ((__WDTCLKCR & SCU_CLK_WDTCLKCR_WDTSEL_Msk) == SCU_CLK_WDTCLKCR_WDTSEL_PLL)))
305 
306 #define ENABLE_USBPLL \
307      ((((__CLKSET & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)) || \
308       (((__CLKSET & SCU_CLK_CLKSET_MMCCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)))
309 
310 #if ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)
311 #define USB_DIV (3U)
312 #else
313 #define USB_DIV (5U)
314 #endif
315 
316 /*******************************************************************************
317  * GLOBAL VARIABLES
318  *******************************************************************************/
319 #if defined ( __CC_ARM )
320 #if defined(XMC4700_E196x2048) || defined(XMC4700_F144x2048) || defined(XMC4700_F100x2048)
321 uint32_t SystemCoreClock __attribute__((at(0x2003FFC0)));
322 uint8_t g_chipid[16] __attribute__((at(0x2003FFC4)));
323 #elif defined(XMC4700_E196x1536) || defined(XMC4700_F144x1536) || defined(XMC4700_F100x1536)
324 uint32_t SystemCoreClock __attribute__((at(0x2002CFC0)));
325 uint8_t g_chipid[16] __attribute__((at(0x2002CFC4)));
326 #else
327 #error "system_XMC4700.c: device not supported"
328 #endif
329 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
330 #if defined(XMC4700_E196x2048) || defined(XMC4700_F144x2048) || defined(XMC4700_F100x2048)
331 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2003FFC0")));
332 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2003FFC4")));
333 #elif defined(XMC4700_E196x1536) || defined(XMC4700_F144x1536) || defined(XMC4700_F100x1536)
334 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2002CFC0")));
335 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2002CFC4")));
336 #else
337 #error "system_XMC4700.c: device not supported"
338 #endif
339 #elif defined ( __ICCARM__ )
340 #if defined(XMC4700_E196x2048) || defined(XMC4700_F144x2048) || defined(XMC4700_F100x2048) || \
341     defined(XMC4700_E196x1536) || defined(XMC4700_F144x1536) || defined(XMC4700_F100x1536)
342 __no_init uint32_t SystemCoreClock;
343 __no_init uint8_t g_chipid[16];
344 #else
345 #error "system_XMC4700.c: device not supported"
346 #endif
347 #elif defined ( __GNUC__ )
348 #if defined(XMC4700_E196x2048) || defined(XMC4700_F144x2048) || defined(XMC4700_F100x2048) || \
349     defined(XMC4700_E196x1536) || defined(XMC4700_F144x1536) || defined(XMC4700_F100x1536)
350 uint32_t SystemCoreClock __attribute__((section(".noinit")));
351 uint8_t g_chipid[16] __attribute__((section(".noinit")));
352 #else
353 #error "system_XMC4700.c: device not supported"
354 #endif
355 #elif defined ( __TASKING__ )
356 #if defined(XMC4700_E196x2048) || defined(XMC4700_F144x2048) || defined(XMC4700_F100x2048)
357 uint32_t SystemCoreClock __at( 0x2003FFC0 );
358 uint8_t g_chipid[16] __at( 0x2003FFC4 );
359 #elif defined(XMC4700_E196x1536) || defined(XMC4700_F144x1536) || defined(XMC4700_F100x1536)
360 uint32_t SystemCoreClock __at( 0x2002CFC0 );
361 uint8_t g_chipid[16] __at( 0x2002CFC4 );
362 #else
363 #error "system_XMC4700.c: device not supported"
364 #endif
365 #else
366 #error "system_XMC4700.c: compiler not supported"
367 #endif
368 
369 extern uint32_t __Vectors;
370 
371 /*******************************************************************************
372  * LOCAL FUNCTIONS
373  *******************************************************************************/
delay(uint32_t cycles)374 static void delay(uint32_t cycles)
375 {
376   volatile uint32_t i;
377 
378   for(i = 0UL; i < cycles ;++i)
379   {
380     __NOP();
381   }
382 }
383 
384 /*******************************************************************************
385  * API IMPLEMENTATION
386  *******************************************************************************/
387 
SystemInit(void)388 __WEAK void SystemInit(void)
389 {
390   memcpy(g_chipid, CHIPID_LOC, 16);
391 
392   SystemCoreSetup();
393   SystemCoreClockSetup();
394 }
395 
SystemCoreSetup(void)396 __WEAK void SystemCoreSetup(void)
397 {
398   uint32_t temp;
399 
400   /* relocate vector table */
401   __disable_irq();
402   SCB->VTOR = (uint32_t)(&__Vectors);
403   __DSB();
404   __enable_irq();
405 
406   /* __FPU_PRESENT = 1 defined in device header file */
407   /* __FPU_USED value depends on compiler/linker options. */
408   /* __FPU_USED = 0 if -mfloat-abi=soft is selected */
409   /* __FPU_USED = 1 if -mfloat-abi=softfp or –mfloat-abi=hard */
410 
411 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
412   SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
413                  (3UL << 11*2)  );               /* set CP11 Full Access */
414 #else
415   SCB->CPACR = 0;
416 #endif
417 
418   /* Enable unaligned memory access - SCB_CCR.UNALIGN_TRP = 0 */
419   SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk);
420 
421   temp = FLASH0->FCON;
422   temp &= ~FLASH_FCON_WSPFLASH_Msk;
423   temp |= PMU_FLASH_WS;
424   FLASH0->FCON = temp;
425 }
426 
SystemCoreClockSetup(void)427 __WEAK void SystemCoreClockSetup(void)
428 {
429 #if FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_FACTORY
430   /* Enable factory calibration */
431   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FOTR_Msk;
432 #else
433   /* Automatic calibration uses the fSTDBY */
434 
435   /* Enable HIB domain */
436   /* Power up HIB domain if and only if it is currently powered down */
437   if((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
438   {
439     SCU_POWER->PWRSET |= SCU_POWER_PWRSET_HIB_Msk;
440 
441     while((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
442     {
443       /* wait until HIB domain is enabled */
444     }
445   }
446 
447   /* Remove the reset only if HIB domain were in a state of reset */
448   if((SCU_RESET->RSTSTAT) & SCU_RESET_RSTSTAT_HIBRS_Msk)
449   {
450     SCU_RESET->RSTCLR |= SCU_RESET_RSTCLR_HIBRS_Msk;
451     delay(DELAY_CNT_150US_50MHZ);
452   }
453 
454 #if STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP
455   /* Enable OSC_ULP */
456   if ((SCU_HIBERNATE->OSCULCTRL & SCU_HIBERNATE_OSCULCTRL_MODE_Msk) != 0UL)
457   {
458     /*enable OSC_ULP*/
459     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
460     {
461       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
462     }
463     SCU_HIBERNATE->OSCULCTRL &= ~SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
464 
465     /* Check if the clock is OK using OSCULP Oscillator Watchdog*/
466     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
467     {
468       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
469     }
470     SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_ULPWDGEN_Msk;
471 
472     /* wait till clock is stable */
473     do
474     {
475       while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCLR_Msk)
476       {
477         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
478       }
479       SCU_HIBERNATE->HDCLR |= SCU_HIBERNATE_HDCLR_ULPWDG_Msk;
480 
481       delay(DELAY_CNT_50US_50MHZ);
482 
483     } while ((SCU_HIBERNATE->HDSTAT & SCU_HIBERNATE_HDSTAT_ULPWDG_Msk) != 0UL);
484 
485   }
486 
487   /* now OSC_ULP is running and can be used*/
488   /* Select OSC_ULP as the clock source for RTC and STDBY*/
489   while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
490   {
491     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
492   }
493   SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_RCS_Msk | SCU_HIBERNATE_HDCR_STDBYSEL_Msk;
494 #endif /* STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP */
495 
496   /* Enable automatic calibration of internal fast oscillator */
497   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_AOTREN_Msk;
498 #endif /* FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_AUTOMATIC */
499 
500   delay(DELAY_CNT_50US_50MHZ);
501 
502 #if ENABLE_PLL
503 
504   /* enable PLL */
505   SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
506 
507 #if PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI
508   /* enable OSC_HP */
509   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
510   {
511     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
512     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
513 
514     /* select OSC_HP clock as PLL input */
515     SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk;
516 
517     /* restart OSC Watchdog */
518     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
519 
520     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
521     {
522       /* wait till OSC_HP output frequency is usable */
523     }
524   }
525 #else /* PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI */
526 
527   /* select backup clock as PLL input */
528   SCU_PLL->PLLCON2 |= SCU_PLL_PLLCON2_PINSEL_Msk;
529 #endif
530 
531   /* Go to bypass the Main PLL */
532   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_VCOBYP_Msk;
533 
534   /* disconnect Oscillator from PLL */
535   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FINDIS_Msk;
536 
537   /* Setup divider settings for main PLL */
538   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
539                       (PLL_K2DIV_24MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
540                       (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
541 
542   /* Set OSCDISCDIS */
543   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
544 
545   /* connect Oscillator to PLL */
546   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_FINDIS_Msk;
547 
548   /* restart PLL Lock detection */
549   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_RESLD_Msk;
550 
551   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
552   {
553     /* wait for PLL Lock at 24MHz*/
554   }
555 
556   /* Disable bypass- put PLL clock back */
557   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_VCOBYP_Msk;
558   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) != 0U)
559   {
560     /* wait for normal mode */
561   }
562 #endif /* ENABLE_PLL */
563 
564   /* Before scaling to final frequency we need to setup the clock dividers */
565   SCU_CLK->SYSCLKCR = __SYSCLKCR;
566   SCU_CLK->PBCLKCR = __PBCLKCR;
567   SCU_CLK->CPUCLKCR = __CPUCLKCR;
568   SCU_CLK->CCUCLKCR = __CCUCLKCR;
569   SCU_CLK->WDTCLKCR = __WDTCLKCR;
570   SCU_CLK->EBUCLKCR = __EBUCLKCR;
571   SCU_CLK->USBCLKCR = __USBCLKCR | USB_DIV;
572   SCU_CLK->EXTCLKCR = __EXTCLKCR;
573 
574 #if ENABLE_PLL
575   /* PLL frequency stepping...*/
576   /* Reset OSCDISCDIS */
577   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
578 
579   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
580 	                  (PLL_K2DIV_48MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
581 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
582 
583   delay(DELAY_CNT_50US_48MHZ);
584 
585   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
586 	                  (PLL_K2DIV_72MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
587 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
588 
589   delay(DELAY_CNT_50US_72MHZ);
590 
591   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
592 	                  (PLL_K2DIV_96MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
593 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
594 
595   delay(DELAY_CNT_50US_96MHZ);
596 
597   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
598 	                  (PLL_K2DIV_120MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
599 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
600 
601   delay(DELAY_CNT_50US_120MHZ);
602 
603   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
604 	                  (PLL_K2DIV << SCU_PLL_PLLCON1_K2DIV_Pos) |
605 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
606 
607   delay(DELAY_CNT_50US_144MHZ);
608 
609 #endif /* ENABLE_PLL */
610 
611 #if ENABLE_USBPLL
612   /* enable USB PLL first */
613   SCU_PLL->USBPLLCON &= ~(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk);
614 
615   /* USB PLL uses as clock input the OSC_HP */
616   /* check and if not already running enable OSC_HP */
617   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
618   {
619     /* check if Main PLL is switched on for OSC WDG*/
620     if ((SCU_PLL->PLLCON0 &(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk)) != 0UL)
621     {
622       /* enable PLL first */
623       SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
624     }
625 
626     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
627     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
628 
629     /* restart OSC Watchdog */
630     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
631 
632     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
633     {
634       /* wait till OSC_HP output frequency is usable */
635     }
636   }
637 
638 
639   /* Setup USB PLL */
640   /* Go to bypass the USB PLL */
641   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_VCOBYP_Msk;
642 
643   /* disconnect Oscillator from USB PLL */
644   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_FINDIS_Msk;
645 
646   /* Setup Divider settings for USB PLL */
647   SCU_PLL->USBPLLCON = ((USB_NDIV << SCU_PLL_USBPLLCON_NDIV_Pos) |
648                         (USB_PDIV << SCU_PLL_USBPLLCON_PDIV_Pos));
649 
650   /* Set OSCDISCDIS */
651   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
652 
653   /* connect Oscillator to USB PLL */
654   SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_FINDIS_Msk;
655 
656   /* restart PLL Lock detection */
657   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_RESLD_Msk;
658 
659   while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk) == 0U)
660   {
661     /* wait for PLL Lock */
662   }
663 #endif
664 
665 
666   /* Enable selected clocks */
667   SCU_CLK->CLKSET = __CLKSET;
668 
669 #if __EXTCLKPIN != 0
670 #if __EXTCLKPIN == EXTCLK_PIN_P1_15
671   /* P1.15 */
672   PORT1->PDR1 &= ~PORT1_PDR1_PD15_Msk;
673   PORT1->IOCR12 = (PORT1->IOCR12 & ~PORT0_IOCR12_PC15_Msk) | (0x11U << PORT0_IOCR12_PC15_Pos);
674 #else
675   /* P0.8 */
676   PORT0->HWSEL &= ~PORT0_HWSEL_HW8_Msk;
677   PORT0->PDR1 &= ~PORT0_PDR1_PD8_Msk;
678   PORT0->IOCR8 = (PORT0->IOCR8 & ~PORT0_IOCR8_PC8_Msk) | (0x11U << PORT0_IOCR8_PC8_Pos);
679 #endif
680 #endif  /* ENABLE_EXTCLK == 1  */
681 
682   SystemCoreClockUpdate();
683 }
684 
SystemCoreClockUpdate(void)685 __WEAK void SystemCoreClockUpdate(void)
686 {
687   uint32_t pdiv;
688   uint32_t ndiv;
689   uint32_t kdiv;
690   uint32_t temp;
691 
692   if (SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSSEL_Msk)
693   {
694     /* fPLL is clock source for fSYS */
695     if(SCU_PLL->PLLCON2 & SCU_PLL_PLLCON2_PINSEL_Msk)
696     {
697       /* PLL input clock is the backup clock (fOFI) */
698       temp = OFI_FREQUENCY;
699     }
700     else
701     {
702       /* PLL input clock is the high performance osicllator (fOSCHP) */
703       temp = OSCHP_GetFrequency();
704     }
705 
706     /* check if PLL is locked */
707     if (SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk)
708     {
709       /* PLL normal mode */
710       /* read back divider settings */
711       pdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_PDIV_Msk) >> SCU_PLL_PLLCON1_PDIV_Pos) + 1;
712       ndiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_NDIV_Msk) >> SCU_PLL_PLLCON1_NDIV_Pos) + 1;
713       kdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K2DIV_Msk) >> SCU_PLL_PLLCON1_K2DIV_Pos) + 1;
714 
715       temp = (temp / (pdiv * kdiv)) * ndiv;
716     }
717     else
718     {
719       /* PLL prescalar mode */
720       /* read back divider settings */
721       kdiv  = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K1DIV_Msk) >> SCU_PLL_PLLCON1_K1DIV_Pos) + 1;
722 
723       temp = (temp / kdiv);
724     }
725   }
726   else
727   {
728     /* fOFI is clock source for fSYS */
729     temp = OFI_FREQUENCY;
730   }
731 
732   temp = temp / ((SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSDIV_Msk) + 1);
733   temp = temp / ((SCU_CLK->CPUCLKCR & SCU_CLK_CPUCLKCR_CPUDIV_Msk) + 1);
734 
735   SystemCoreClock = temp;
736 }
737 
OSCHP_GetFrequency(void)738 __WEAK uint32_t OSCHP_GetFrequency(void)
739 {
740   return OSCHP_FREQUENCY;
741 }
742