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