1 /*********************************************************************************************************************
2  * @file     system_XMC4800.c
3  * @brief    CMSIS Cortex-M4 Device Peripheral Access Layer Header File for the Infineon XMC4800 Device Series
4  * @version  V1.0.8
5  * @date     27. Aug 2020
6  *
7  * @cond
8  *********************************************************************************************************************
9  * Copyright (c) 2015-2020, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Boost Software License - Version 1.0 - August 17th, 2003
13  *
14  * Permission is hereby granted, free of charge, to any person or organization
15  * obtaining a copy of the software and accompanying documentation covered by
16  * this license (the "Software") to use, reproduce, display, distribute,
17  * execute, and transmit the Software, and to prepare derivative works of the
18  * Software, and to permit third-parties to whom the Software is furnished to
19  * do so, all subject to the following:
20  *
21  * The copyright notices in the Software and this entire statement, including
22  * the above license grant, this restriction and the following disclaimer,
23  * must be included in all copies of the Software, in whole or in part, and
24  * all derivative works of the Software, unless such copies or derivative
25  * works are solely in the form of machine-executable object code generated by
26  * a source language processor.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
31  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
32  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
33  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34  * DEALINGS IN THE SOFTWARE.
35  *
36  * To improve the quality of the software, users are encouraged to share
37  * modifications, enhancements or bug fixes with Infineon Technologies AG
38  * at XMCSupport@infineon.com.
39  *********************************************************************************************************************
40  *
41  ********************** Version History ***************************************
42  * V1.0.0, 22. May 2015, Initial version
43  * V1.0.1, 26. Jan 2016, Disable trap generation from clock unit
44  * V1.0.2, 01. Jun 2016, Fix masking of OSCHPCTRL value
45  * V1.0.3, 09. Feb 2017, Fix activation of USBPLL when SDMMC clock is enabled
46  * V1.0.4, 19. Jun 2017, Rely on cmsis_compiler.h instead of defining __WEAK
47  * V1.0.5, 26. Sep 2017, Disable FPU if FPU_USED is zero
48  * V1.0.6, 29. Oct 2018, Fix variable location of SystemCoreClock and g_chipid for ARMCC compiler
49  * V1.0.7, 02. Dec 2019, Fix including device header file following the convention: angle brackets are used for standard includes and double quotes for everything else.
50  *                       Fix external clock monitoring pin settings
51  * V1.0.8, 27. Aug 2020. Fix K1 divider input clock for PLL in prescaler mode
52  *                       Added compiler checks for input VCO and VCO frequencies
53  *                       Added wait for K2 divider ready after updating the K2 divider in the PLL ramp up
54  ******************************************************************************
55 * @endcond
56 */
57 
58 /*******************************************************************************
59  * Default clock initialization
60  * fPLL = 288MHz => fSYS = 144MHz => fCPU = 144MHz
61  *                                => fPB  = 144MHz
62  *                                => fCCU = 144MHz
63  *                                => fETH = 72MHz
64  *               => fUSB = 48MHz
65  *               => fEBU = 72MHz
66  *
67  * fUSBPLL = 200MHz => fECAT = 100MHz
68  *
69  * fOFI = 24MHz => fWDT = 24MHz
70  *******************************************************************************/
71 
72 /*******************************************************************************
73  * HEADER FILES
74  *******************************************************************************/
75 #include <string.h>
76 
77 #include "XMC4800.h"
78 #include "system_XMC4800.h"
79 
80 /*******************************************************************************
81  * MACROS
82  *******************************************************************************/
83 #define CHIPID_LOC ((uint8_t *)0x20000000UL)
84 
85 #define PMU_FLASH_WS          (0x4U)
86 
87 #define FOSCREF               (2500000U)
88 
89 #define DELAY_CNT_50US_50MHZ  (2500UL)
90 #define DELAY_CNT_150US_50MHZ (7500UL)
91 #define DELAY_CNT_50US_48MHZ  (2400UL)
92 #define DELAY_CNT_50US_72MHZ  (3600UL)
93 #define DELAY_CNT_50US_96MHZ  (4800UL)
94 #define DELAY_CNT_50US_120MHZ (6000UL)
95 #define DELAY_CNT_50US_144MHZ (7200UL)
96 
97 #define VCO_INPUT_MIN         (4000000UL)
98 #define VCO_INPUT_MAX         (16000000UL)
99 #define VCO_MIN               (260000000UL)
100 #define VCO_MAX               (520000000UL)
101 
102 #define SCU_PLL_PLLSTAT_OSC_USABLE  (SCU_PLL_PLLSTAT_PLLHV_Msk | \
103                                      SCU_PLL_PLLSTAT_PLLLV_Msk | \
104                                      SCU_PLL_PLLSTAT_PLLSP_Msk)
105 
106 /*
107 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
108 */
109 
110 /*
111 // <h> Clock configuration
112 */
113 
114 /*
115 //    <o> External crystal frequency [Hz]
116 //       <8000000=> 8MHz
117 //       <12000000=> 12MHz
118 //       <16000000=> 16MHz
119 //    <i> Defines external crystal frequency
120 //    <i> Default: 8MHz
121 */
122 #define OSCHP_FREQUENCY (12000000U)
123 
124 /* USB PLL settings, fUSBPLL = 200MHz */
125 /* Note: Implicit divider of 2, fUSBPLLVCO = 400MHz */
126 #if OSCHP_FREQUENCY == 8000000U
127 #define USB_PDIV (1U)
128 #define USB_NDIV (99U)
129 
130 #elif OSCHP_FREQUENCY == 12000000U
131 #define USB_PDIV (2U)
132 #define USB_NDIV (99U)
133 
134 #elif OSCHP_FREQUENCY == 16000000U
135 #define USB_PDIV (3U)
136 #define USB_NDIV (99U)
137 
138 #else
139 #error "External crystal frequency not supported"
140 
141 #endif
142 
143 #define USB_VCO ((OSCHP_FREQUENCY / (USB_PDIV + 1UL)) * (USB_NDIV + 1UL))
144 #define USB_VCO_INPUT (OSCHP_FREQUENCY / (USB_PDIV + 1UL))
145 
146 /*
147 //    <o> Backup clock calibration mode
148 //       <0=> Factory calibration
149 //       <1=> Automatic calibration
150 //    <i> Default: Automatic calibration
151 */
152 #define FOFI_CALIBRATION_MODE 1
153 #define FOFI_CALIBRATION_MODE_FACTORY 0
154 #define FOFI_CALIBRATION_MODE_AUTOMATIC 1
155 
156 /*
157 //    <o> Standby clock (fSTDBY) source selection
158 //       <0=> Internal slow oscillator (32768Hz)
159 //       <1=> External crystal (32768Hz)
160 //    <i> Default: Internal slow oscillator (32768Hz)
161 */
162 #define STDBY_CLOCK_SRC 0
163 #define STDBY_CLOCK_SRC_OSI 0
164 #define STDBY_CLOCK_SRC_OSCULP 1
165 
166 /*
167 //    <o> PLL clock source selection
168 //       <0=> External crystal
169 //       <1=> Internal fast oscillator
170 //    <i> Default: External crystal
171 */
172 #define PLL_CLOCK_SRC 0
173 #define PLL_CLOCK_SRC_EXT_XTAL 0
174 #define PLL_CLOCK_SRC_OFI 1
175 
176 /* PLL settings, fPLL = 288MHz */
177 #if PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL
178 #if OSCHP_FREQUENCY == 8000000U
179 #define PLL_PDIV (1U)
180 #define PLL_NDIV (71U)
181 #define PLL_K2DIV (0U)
182 
183 #elif OSCHP_FREQUENCY == 12000000U
184 #define PLL_PDIV (1U)
185 #define PLL_NDIV (47U)
186 #define PLL_K2DIV (0U)
187 
188 #elif OSCHP_FREQUENCY == 16000000U
189 #define PLL_PDIV (1U)
190 #define PLL_NDIV (35U)
191 #define PLL_K2DIV (0U)
192 
193 #else
194 #error "External crystal frequency not supported"
195 
196 #endif
197 
198 #define VCO ((OSCHP_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
199 #define VCO_INPUT (OSCHP_FREQUENCY / (PLL_PDIV + 1UL))
200 
201 #else /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL */
202 #define PLL_PDIV (1U)
203 #define PLL_NDIV (23U)
204 #define PLL_K2DIV (0U)
205 
206 #define VCO ((OFI_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
207 #define VCO_INPUT (OFI_FREQUENCY / (PLL_PDIV + 1UL))
208 
209 #endif /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_OFI */
210 
211 #if (VCO_INPUT < VCO_INPUT_MIN) || (VCO_INPUT > VCO_INPUT_MAX)
212 #error VCO_INPUT frequency out of range.
213 #endif
214 
215 #if (VCO < VCO_MIN) || (VCO > VCO_MAX)
216 #error VCO frequency out of range.
217 #endif
218 
219 #if (USB_VCO_INPUT < VCO_INPUT_MIN) || (USB_VCO_INPUT > VCO_INPUT_MAX)
220 #error USB_VCO_INPUT frequency out of range.
221 #endif
222 
223 #if (USB_VCO < VCO_MIN) || (USB_VCO > VCO_MAX)
224 #error USB_VCO frequency out of range.
225 #endif
226 
227 #define PLL_K2DIV_24MHZ  ((VCO / OFI_FREQUENCY) - 1UL)
228 #define PLL_K2DIV_48MHZ  ((VCO / 48000000U) - 1UL)
229 #define PLL_K2DIV_72MHZ  ((VCO / 72000000U) - 1UL)
230 #define PLL_K2DIV_96MHZ  ((VCO / 96000000U) - 1UL)
231 #define PLL_K2DIV_120MHZ ((VCO / 120000000U) - 1UL)
232 
233 #define SCU_CLK_CLKCLR_ENABLE_USBCLK SCU_CLK_CLKCLR_USBCDI_Msk
234 #define SCU_CLK_CLKCLR_ENABLE_MMCCLK SCU_CLK_CLKCLR_MMCCDI_Msk
235 #define SCU_CLK_CLKCLR_ENABLE_ETHCLK SCU_CLK_CLKCLR_ETH0CDI_Msk
236 #define SCU_CLK_CLKCLR_ENABLE_EBUCLK SCU_CLK_CLKCLR_EBUCDI_Msk
237 #define SCU_CLK_CLKCLR_ENABLE_CCUCLK SCU_CLK_CLKCLR_CCUCDI_Msk
238 
239 #define SCU_CLK_SYSCLKCR_SYSSEL_OFI      (0U << SCU_CLK_SYSCLKCR_SYSSEL_Pos)
240 #define SCU_CLK_SYSCLKCR_SYSSEL_PLL      (1U << SCU_CLK_SYSCLKCR_SYSSEL_Pos)
241 
242 #define SCU_CLK_USBCLKCR_USBSEL_USBPLL   (0U << SCU_CLK_USBCLKCR_USBSEL_Pos)
243 #define SCU_CLK_USBCLKCR_USBSEL_PLL      (1U << SCU_CLK_USBCLKCR_USBSEL_Pos)
244 
245 #define SCU_CLK_ECATCLKCR_ECATSEL_USBPLL (0U << SCU_CLK_ECATCLKCR_ECATSEL_Pos)
246 #define SCU_CLK_ECATCLKCR_ECATSEL_PLL    (1U << SCU_CLK_ECATCLKCR_ECATSEL_Pos)
247 
248 #define SCU_CLK_WDTCLKCR_WDTSEL_OFI      (0U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
249 #define SCU_CLK_WDTCLKCR_WDTSEL_STANDBY  (1U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
250 #define SCU_CLK_WDTCLKCR_WDTSEL_PLL      (2U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
251 
252 #define SCU_CLK_EXTCLKCR_ECKSEL_SYS      (0U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
253 #define SCU_CLK_EXTCLKCR_ECKSEL_USBPLL   (2U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
254 #define SCU_CLK_EXTCLKCR_ECKSEL_PLL      (3U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
255 
256 #define EXTCLK_PIN_P0_8  (1)
257 #define EXTCLK_PIN_P1_15 (2)
258 
259 /*
260 //    <h> Clock tree
261 //        <o1.16> System clock source selection
262 //                      <0=> fOFI
263 //                      <1=> fPLL
264 //                      <i> Default: fPLL
265 //        <o1.0..7> System clock divider <1-256><#-1>
266 //                      <i> Default: 2
267 //        <o2.0> CPU clock divider
268 //                      <0=> fCPU = fSYS
269 //                      <1=> fCPU = fSYS / 2
270 //                      <i> Default: fCPU = fSYS
271 //        <o3.0>  Peripheral clock divider
272 //                      <0=> fPB = fCPU
273 //                      <1=> fPB = fCPU / 2
274 //                      <i> Default: fPB = fCPU
275 //        <o4.0>  CCU clock divider
276 //                      <0=> fCCU = fCPU
277 //                      <1=> fCCU = fCPU / 2
278 //                      <i> Default: fCCU = fCPU
279 //        <e.5> Enable WDT clock
280 //             <o5.16..17> WDT clock source <0=> fOFI
281 //                                          <1=> fSTDBY
282 //                                          <2=> fPLL
283 //                      <i> Default: fOFI
284 //             <o5.0..7> WDT clock divider <1-256><#-1>
285 //                      <i> Default: 1
286 //        </e>
287 //        <e.3> Enable EBU clock
288 //             <o6.0..5>  EBU clock divider  <1-64><#-1>
289 //             <i> Default: 4
290 //        </e>
291 //        <e.2> Enable ETH clock
292 //        </e>
293 //        <e.1> Enable MMC clock
294 //        </e>
295 //        <e.0> Enable USB clock
296 //             <o7.16> USB clock source <0=> fUSBPLL
297 //                                      <1=> fPLL
298 //             <i> Default: fPLL
299 //             <o7.0..2> USB clock source divider <1-8><#-1>
300 //             <i> Default: 6
301 //        </e>
302 //        <h> EtherCAT Clock Control
303 //        	   <o8.16..17> ECAT clock source <0=> fUSBPLL
304 //                                           <1=> fPLL
305 //                                           <i> Default: fUSBPLL
306 //             <o8.0..1> ECAT clock divider  <1-4><#-1>
307 //                                           <i> Default: 2
308 //        </h>
309 //        <h> External Clock Control
310 //             <o9.0..1> External Clock Source Selection
311 //                  <0=> fSYS
312 //                  <2=> fUSB
313 //                  <3=> fPLL
314 //                  <i> Default: fPLL
315 //             <o9.16..24> External Clock divider <1-512><#-1>
316 //                  <i> Default: 288
317 //                  <i> Only valid for USB PLL and PLL clocks
318 //             <o10.0> External Clock Pin Selection
319 //                  <0=> Disabled
320 //                  <1=> P0.8
321 //                  <2=> P1.15
322 //                  <i> Default: Disabled
323 //        </h>
324 //    </h>
325 */
326 #define __CLKSET    (0x00000000UL)
327 #define __SYSCLKCR  (0x00010001UL)
328 #define __CPUCLKCR  (0x00000000UL)
329 #define __PBCLKCR   (0x00000000UL)
330 #define __CCUCLKCR  (0x00000000UL)
331 #define __WDTCLKCR  (0x00000000UL)
332 #define __EBUCLKCR  (0x00000003UL)
333 #define __USBCLKCR  (0x00010005UL)
334 #define __ECATCLKCR (0x00000001UL)
335 #define __EXTCLKCR  (0x01200003UL)
336 #define __EXTCLKPIN (0U)
337 
338 /*
339 // </h>
340 */
341 
342 /*
343 //-------- <<< end of configuration section >>> ------------------
344 */
345 
346 #define ENABLE_PLL \
347     (((__SYSCLKCR & SCU_CLK_SYSCLKCR_SYSSEL_Msk) == SCU_CLK_SYSCLKCR_SYSSEL_PLL) || \
348      ((__ECATCLKCR & SCU_CLK_ECATCLKCR_ECATSEL_Msk) == SCU_CLK_ECATCLKCR_ECATSEL_PLL) || \
349      ((__CLKSET & SCU_CLK_CLKSET_EBUCEN_Msk) != 0) || \
350      (((__CLKSET & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_PLL)) || \
351      (((__CLKSET & SCU_CLK_CLKSET_WDTCEN_Msk) != 0) && ((__WDTCLKCR & SCU_CLK_WDTCLKCR_WDTSEL_Msk) == SCU_CLK_WDTCLKCR_WDTSEL_PLL)))
352 
353 #define ENABLE_USBPLL \
354     (((__ECATCLKCR & SCU_CLK_ECATCLKCR_ECATSEL_Msk) == SCU_CLK_ECATCLKCR_ECATSEL_USBPLL) || \
355      (((__CLKSET & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)) || \
356      (((__CLKSET & SCU_CLK_CLKSET_MMCCEN_Msk) != 0) && ((__USBCLKCR & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)))
357 
358 /*******************************************************************************
359  * GLOBAL VARIABLES
360  *******************************************************************************/
361 #if defined ( __CC_ARM )
362 #if defined(XMC4800_E196x2048) || defined(XMC4800_F144x2048) || defined(XMC4800_F100x2048)
363 uint32_t SystemCoreClock __attribute__((at(0x2003FFC0)));
364 uint8_t g_chipid[16] __attribute__((at(0x2003FFC4)));
365 #elif defined(XMC4800_E196x1536) || defined(XMC4800_F144x1536) || defined(XMC4800_F100x1536)
366 uint32_t SystemCoreClock __attribute__((at(0x2002CFC0)));
367 uint8_t g_chipid[16] __attribute__((at(0x2002CFC4)));
368 #elif defined(XMC4800_E196x1024) || defined(XMC4800_F144x1024) || defined(XMC4800_F100x1024)
369 uint32_t SystemCoreClock __attribute__((at(0x2001FFC0)));
370 uint8_t g_chipid[16] __attribute__((at(0x2001FFC4)));
371 #else
372 #error "system_XMC4800.c: device not supported"
373 #endif
374 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
375 #if defined(XMC4800_E196x2048) || defined(XMC4800_F144x2048) || defined(XMC4800_F100x2048)
376 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2003FFC0")));
377 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2003FFC0")));
378 #elif defined(XMC4800_E196x1536) || defined(XMC4800_F144x1536) || defined(XMC4800_F100x1536)
379 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2002CFC0")));
380 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2002CFC4")));
381 #elif defined(XMC4800_E196x1024) || defined(XMC4800_F144x1024) || defined(XMC4800_F100x1024)
382 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2001FFC0")));
383 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2001FFC4")));
384 #else
385 #error "system_XMC4800.c: device not supported"
386 #endif
387 #elif defined ( __ICCARM__ )
388 #if defined(XMC4800_E196x2048) || defined(XMC4800_F144x2048) || defined(XMC4800_F100x2048) || \
389     defined(XMC4800_E196x1536) || defined(XMC4800_F144x1536) || defined(XMC4800_F100x1536) || \
390     defined(XMC4800_E196x1024) || defined(XMC4800_F144x1024) || defined(XMC4800_F100x1024)
391 __no_init uint32_t SystemCoreClock;
392 __no_init uint8_t g_chipid[16];
393 #else
394 #error "system_XMC4800.c: device not supported"
395 #endif
396 #elif defined ( __GNUC__ )
397 #if defined(XMC4800_E196x2048) || defined(XMC4800_F144x2048) || defined(XMC4800_F100x2048) || \
398     defined(XMC4800_E196x1536) || defined(XMC4800_F144x1536) || defined(XMC4800_F100x1536) || \
399     defined(XMC4800_E196x1024) || defined(XMC4800_F144x1024) || defined(XMC4800_F100x1024)
400 uint32_t SystemCoreClock __attribute__((section(".no_init")));
401 uint8_t g_chipid[16] __attribute__((section(".no_init")));
402 #else
403 #error "system_XMC4800.c: device not supported"
404 #endif
405 #elif defined ( __TASKING__ )
406 #if defined(XMC4800_E196x2048) || defined(XMC4800_F144x2048) || defined(XMC4800_F100x2048)
407 uint32_t SystemCoreClock __at( 0x2003FFC0 );
408 uint8_t g_chipid[16] __at( 0x2003FFC4 );
409 #elif defined(XMC4800_E196x1536) || defined(XMC4800_F144x1536) || defined(XMC4800_F100x1536)
410 uint32_t SystemCoreClock __at( 0x2002CFC0 );
411 uint8_t g_chipid[16] __at( 0x2002CFC4 );
412 #elif defined(XMC4800_E196x1024) || defined(XMC4800_F144x1024) || defined(XMC4800_F100x1024)
413 uint32_t SystemCoreClock __at( 0x2001FFC0 );
414 uint8_t g_chipid[16] __at( 0x2001FFC4 );
415 #else
416 #error "system_XMC4800.c: device not supported"
417 #endif
418 #else
419 #error "system_XMC4800.c: compiler not supported"
420 #endif
421 
422 extern uint32_t __Vectors;
423 
424 /*******************************************************************************
425  * LOCAL FUNCTIONS
426  *******************************************************************************/
delay(uint32_t cycles)427 static void delay(uint32_t cycles)
428 {
429   volatile uint32_t i;
430 
431   for(i = 0UL; i < cycles ;++i)
432   {
433     __NOP();
434   }
435 }
436 
437 /*******************************************************************************
438  * API IMPLEMENTATION
439  *******************************************************************************/
440 
SystemInit(void)441 __WEAK void SystemInit(void)
442 {
443   memcpy(g_chipid, CHIPID_LOC, 16);
444 
445   SystemCoreSetup();
446   SystemCoreClockSetup();
447 }
448 
SystemCoreSetup(void)449 __WEAK void SystemCoreSetup(void)
450 {
451   uint32_t temp;
452 
453   /* relocate vector table */
454   __disable_irq();
455   SCB->VTOR = (uint32_t)(&__Vectors);
456   __DSB();
457   __enable_irq();
458 
459   /* __FPU_PRESENT = 1 defined in device header file */
460   /* __FPU_USED value depends on compiler/linker options. */
461   /* __FPU_USED = 0 if -mfloat-abi=soft is selected */
462   /* __FPU_USED = 1 if -mfloat-abi=softfp or –mfloat-abi=hard */
463 
464 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
465   SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
466                  (3UL << 11*2)  );               /* set CP11 Full Access */
467 #else
468   SCB->CPACR = 0;
469 #endif
470 
471   /* Enable unaligned memory access - SCB_CCR.UNALIGN_TRP = 0 */
472   SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk);
473 
474   temp = FLASH0->FCON;
475   temp &= ~FLASH_FCON_WSPFLASH_Msk;
476   temp |= PMU_FLASH_WS;
477   FLASH0->FCON = temp;
478 }
479 
SystemCoreClockSetup(void)480 __WEAK void SystemCoreClockSetup(void)
481 {
482 #if FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_FACTORY
483   /* Enable factory calibration */
484   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FOTR_Msk;
485 #else
486   /* Automatic calibration uses the fSTDBY */
487 
488   /* Enable HIB domain */
489   /* Power up HIB domain if and only if it is currently powered down */
490   if((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
491   {
492     SCU_POWER->PWRSET |= SCU_POWER_PWRSET_HIB_Msk;
493 
494     while((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
495     {
496       /* wait until HIB domain is enabled */
497     }
498   }
499 
500   /* Remove the reset only if HIB domain were in a state of reset */
501   if((SCU_RESET->RSTSTAT) & SCU_RESET_RSTSTAT_HIBRS_Msk)
502   {
503     SCU_RESET->RSTCLR |= SCU_RESET_RSTCLR_HIBRS_Msk;
504     delay(DELAY_CNT_150US_50MHZ);
505   }
506 
507 #if STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP
508   /* Enable OSC_ULP */
509   if ((SCU_HIBERNATE->OSCULCTRL & SCU_HIBERNATE_OSCULCTRL_MODE_Msk) != 0UL)
510   {
511     /*enable OSC_ULP*/
512     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
513     {
514       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
515     }
516     SCU_HIBERNATE->OSCULCTRL &= ~SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
517 
518     /* Check if the clock is OK using OSCULP Oscillator Watchdog*/
519     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
520     {
521       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
522     }
523     SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_ULPWDGEN_Msk;
524 
525     /* wait till clock is stable */
526     do
527     {
528       while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCLR_Msk)
529       {
530         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
531       }
532       SCU_HIBERNATE->HDCLR |= SCU_HIBERNATE_HDCLR_ULPWDG_Msk;
533 
534       delay(DELAY_CNT_50US_50MHZ);
535 
536     } while ((SCU_HIBERNATE->HDSTAT & SCU_HIBERNATE_HDSTAT_ULPWDG_Msk) != 0UL);
537 
538   }
539 
540   /* now OSC_ULP is running and can be used*/
541   /* Select OSC_ULP as the clock source for RTC and STDBY*/
542   while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
543   {
544     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
545   }
546   SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_RCS_Msk | SCU_HIBERNATE_HDCR_STDBYSEL_Msk;
547 #endif /* STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP */
548 
549   /* Enable automatic calibration of internal fast oscillator */
550   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_AOTREN_Msk;
551 #endif /* FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_AUTOMATIC */
552 
553   delay(DELAY_CNT_50US_50MHZ);
554 
555 #if ENABLE_PLL
556 
557   /* enable PLL */
558   SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
559 
560 #if PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI
561   /* enable OSC_HP */
562   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
563   {
564     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
565     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
566 
567     /* select OSC_HP clock as PLL input */
568     SCU_PLL->PLLCON2 = 0;
569 
570     /* restart OSC Watchdog */
571     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
572 
573     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
574     {
575       /* wait till OSC_HP output frequency is usable */
576     }
577   }
578 #else /* PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI */
579 
580   /* select backup clock as PLL input */
581   SCU_PLL->PLLCON2 = SCU_PLL_PLLCON2_PINSEL_Msk | SCU_PLL_PLLCON2_K1INSEL_Msk;
582 #endif
583 
584   /* Go to bypass the Main PLL */
585   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_VCOBYP_Msk;
586   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) == 0U)
587   {
588     /* wait for prescaler mode */
589   }
590 
591   /* disconnect Oscillator from PLL */
592   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FINDIS_Msk;
593 
594   /* Setup divider settings for main PLL */
595   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
596                       (PLL_K2DIV_24MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
597                       (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
598 
599   /* Set OSCDISCDIS */
600   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
601 
602   /* connect Oscillator to PLL */
603   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_FINDIS_Msk;
604 
605   /* restart PLL Lock detection */
606   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_RESLD_Msk;
607 
608   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
609   {
610     /* wait for PLL Lock at 24MHz*/
611   }
612 
613   /* Disable bypass- put PLL clock back */
614   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_VCOBYP_Msk;
615   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) != 0U)
616   {
617     /* wait for normal mode */
618   }
619 
620 #endif /* ENABLE_PLL */
621 
622   /* Before scaling to final frequency we need to setup the clock dividers */
623   SCU_CLK->SYSCLKCR = __SYSCLKCR;
624   SCU_CLK->PBCLKCR = __PBCLKCR;
625   SCU_CLK->CPUCLKCR = __CPUCLKCR;
626   SCU_CLK->CCUCLKCR = __CCUCLKCR;
627   SCU_CLK->WDTCLKCR = __WDTCLKCR;
628   SCU_CLK->EBUCLKCR = __EBUCLKCR;
629   SCU_CLK->USBCLKCR = __USBCLKCR;
630   SCU_CLK->ECATCLKCR = __ECATCLKCR;
631   SCU_CLK->EXTCLKCR = __EXTCLKCR;
632 
633 #if ENABLE_PLL
634   /* PLL frequency stepping...*/
635   /* Reset OSCDISCDIS */
636   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
637 
638   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
639 	                  (PLL_K2DIV_48MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
640 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
641 
642   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_K2RDY_Msk) == 0U)
643   {
644     /* wait until K2-divider operates on the configured value  */
645   }
646 
647   delay(DELAY_CNT_50US_48MHZ);
648 
649   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
650 	                  (PLL_K2DIV_72MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
651 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
652 
653   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_K2RDY_Msk) == 0U)
654   {
655     /* wait until K2-divider operates on the configured value  */
656   }
657 
658   delay(DELAY_CNT_50US_72MHZ);
659 
660   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
661 	                  (PLL_K2DIV_96MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
662 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
663 
664   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_K2RDY_Msk) == 0U)
665   {
666     /* wait until K2-divider operates on the configured value  */
667   }
668 
669   delay(DELAY_CNT_50US_96MHZ);
670 
671   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
672 	                  (PLL_K2DIV_120MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
673 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
674 
675   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_K2RDY_Msk) == 0U)
676   {
677     /* wait until K2-divider operates on the configured value  */
678   }
679 
680   delay(DELAY_CNT_50US_120MHZ);
681 
682   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
683 	                  (PLL_K2DIV << SCU_PLL_PLLCON1_K2DIV_Pos) |
684 	                  (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
685 
686   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_K2RDY_Msk) == 0U)
687   {
688     /* wait until K2-divider operates on the configured value  */
689   }
690 
691   delay(DELAY_CNT_50US_144MHZ);
692 
693   SCU_TRAP->TRAPCLR = SCU_TRAP_TRAPCLR_SOSCWDGT_Msk | SCU_TRAP_TRAPCLR_SVCOLCKT_Msk;
694 #endif /* ENABLE_PLL */
695 
696 #if ENABLE_USBPLL
697   /* enable USB PLL first */
698   SCU_PLL->USBPLLCON &= ~(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk);
699 
700   /* USB PLL uses as clock input the OSC_HP */
701   /* check and if not already running enable OSC_HP */
702   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
703   {
704     /* check if Main PLL is switched on for OSC WDG*/
705     if ((SCU_PLL->PLLCON0 &(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk)) != 0UL)
706     {
707       /* enable PLL first */
708       SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
709     }
710 
711     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
712     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
713 
714     /* restart OSC Watchdog */
715     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
716 
717     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
718     {
719       /* wait till OSC_HP output frequency is usable */
720     }
721   }
722 
723   /* Setup USB PLL */
724   /* Go to bypass the USB PLL */
725   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_VCOBYP_Msk;
726   while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOBYST_Msk) == 0U)
727   {
728     /* wait for prescaler mode */
729   }
730 
731   /* disconnect Oscillator from USB PLL */
732   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_FINDIS_Msk;
733 
734   /* Setup Divider settings for USB PLL */
735   SCU_PLL->USBPLLCON = ((USB_NDIV << SCU_PLL_USBPLLCON_NDIV_Pos) |
736                         (USB_PDIV << SCU_PLL_USBPLLCON_PDIV_Pos));
737 
738   /* Set OSCDISCDIS */
739   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
740 
741   /* connect Oscillator to USB PLL */
742   SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_FINDIS_Msk;
743 
744   /* restart PLL Lock detection */
745   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_RESLD_Msk;
746 
747   while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk) == 0U)
748   {
749     /* wait for PLL Lock */
750   }
751 
752   /* Disable bypass- put PLL clock back */
753   SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_VCOBYP_Msk;
754   while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOBYST_Msk) != 0U)
755   {
756     /* wait for normal mode */
757   }
758 
759   /* Reset OSCDISCDIS */
760   SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
761 
762   SCU_TRAP->TRAPCLR = SCU_TRAP_TRAPCLR_UVCOLCKT_Msk;
763 #endif
764 
765   /* Enable selected clocks */
766   SCU_CLK->CLKSET = __CLKSET;
767 
768 #if __EXTCLKPIN != 0
769 #if __EXTCLKPIN == EXTCLK_PIN_P1_15
770   /* P1.15 */
771   PORT1->PDR1 &= ~PORT1_PDR1_PD15_Msk;
772   PORT1->IOCR12 = (PORT1->IOCR12 & ~PORT0_IOCR12_PC15_Msk) | (0x11U << PORT0_IOCR12_PC15_Pos);
773 #else
774   /* P0.8 */
775   PORT0->HWSEL &= ~PORT0_HWSEL_HW8_Msk;
776   PORT0->PDR1 &= ~PORT0_PDR1_PD8_Msk;
777   PORT0->IOCR8 = (PORT0->IOCR8 & ~PORT0_IOCR8_PC8_Msk) | (0x11U << PORT0_IOCR8_PC8_Pos);
778 #endif
779 #endif  /* ENABLE_EXTCLK == 1  */
780 
781   SystemCoreClockUpdate();
782 }
783 
SystemCoreClockUpdate(void)784 __WEAK void SystemCoreClockUpdate(void)
785 {
786   uint32_t pdiv;
787   uint32_t ndiv;
788   uint32_t kdiv;
789   uint32_t temp;
790 
791   if (SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSSEL_Msk)
792   {
793     /* fPLL is clock source for fSYS */
794     if(SCU_PLL->PLLCON2 & SCU_PLL_PLLCON2_PINSEL_Msk)
795     {
796       /* PLL input clock is the backup clock (fOFI) */
797       temp = OFI_FREQUENCY;
798     }
799     else
800     {
801       /* PLL input clock is the high performance osicllator (fOSCHP) */
802       temp = OSCHP_GetFrequency();
803     }
804 
805     /* check if PLL is locked */
806     if (SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk)
807     {
808       /* PLL normal mode */
809       /* read back divider settings */
810       pdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_PDIV_Msk) >> SCU_PLL_PLLCON1_PDIV_Pos) + 1;
811       ndiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_NDIV_Msk) >> SCU_PLL_PLLCON1_NDIV_Pos) + 1;
812       kdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K2DIV_Msk) >> SCU_PLL_PLLCON1_K2DIV_Pos) + 1;
813 
814       temp = (temp / (pdiv * kdiv)) * ndiv;
815     }
816     else
817     {
818       /* PLL prescalar mode */
819       /* read back divider settings */
820       kdiv  = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K1DIV_Msk) >> SCU_PLL_PLLCON1_K1DIV_Pos) + 1;
821 
822       temp = (temp / kdiv);
823     }
824   }
825   else
826   {
827     /* fOFI is clock source for fSYS */
828     temp = OFI_FREQUENCY;
829   }
830 
831   temp = temp / ((SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSDIV_Msk) + 1);
832   temp = temp / ((SCU_CLK->CPUCLKCR & SCU_CLK_CPUCLKCR_CPUDIV_Msk) + 1);
833 
834   SystemCoreClock = temp;
835 }
836 
OSCHP_GetFrequency(void)837 __WEAK uint32_t OSCHP_GetFrequency(void)
838 {
839   return OSCHP_FREQUENCY;
840 }
841