1 /*
2 ** ###################################################################
3 ** Processors: LPC55S28JBD100
4 ** LPC55S28JBD64
5 ** LPC55S28JEV59
6 ** LPC55S28JEV98
7 **
8 ** Compilers: GNU C Compiler
9 ** IAR ANSI C/C++ Compiler for ARM
10 ** Keil ARM C/C++ Compiler
11 ** MCUXpresso Compiler
12 **
13 ** Reference manual: LPC55S6x/LPC55S2x/LPC552x User manual(UM11126) Rev.1.3 16 May 2019
14 ** Version: rev. 1.1, 2019-05-16
15 ** Build: b231019
16 **
17 ** Abstract:
18 ** Provides a system configuration function and a global variable that
19 ** contains the system frequency. It configures the device and initializes
20 ** the oscillator (PLL) that is part of the microcontroller device.
21 **
22 ** Copyright 2016 Freescale Semiconductor, Inc.
23 ** Copyright 2016-2023 NXP
24 ** SPDX-License-Identifier: BSD-3-Clause
25 **
26 ** http: www.nxp.com
27 ** mail: support@nxp.com
28 **
29 ** Revisions:
30 ** - rev. 1.0 (2018-08-22)
31 ** Initial version based on v0.2UM
32 ** - rev. 1.1 (2019-05-16)
33 ** Initial A1 version based on v1.3UM
34 **
35 ** ###################################################################
36 */
37
38 /*!
39 * @file LPC55S28
40 * @version 1.1
41 * @date 2019-05-16
42 * @brief Device specific configuration file for LPC55S28 (implementation file)
43 *
44 * Provides a system configuration function and a global variable that contains
45 * the system frequency. It configures the device and initializes the oscillator
46 * (PLL) that is part of the microcontroller device.
47 */
48
49 #include <stdint.h>
50 #include "fsl_device_registers.h"
51
52 /* PLL0 SSCG control1 */
53 #define PLL_SSCG_MD_FRACT_P 0U
54 #define PLL_SSCG_MD_INT_P 25U
55 #define PLL_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL_SSCG_MD_FRACT_P)
56 #define PLL_SSCG_MD_INT_M ((uint64_t)0xFFUL << PLL_SSCG_MD_INT_P)
57
58 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)59 static uint32_t findPll0PreDiv(void)
60 {
61 uint32_t preDiv = 1UL;
62
63 /* Direct input is not used? */
64 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
65 {
66 preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
67 if (preDiv == 0UL)
68 {
69 preDiv = 1UL;
70 }
71 }
72 return preDiv;
73 }
74
75 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)76 static uint32_t findPll0PostDiv(void)
77 {
78 uint32_t postDiv = 1;
79
80 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
81 {
82 if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
83 {
84 postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
85 }
86 else
87 {
88 postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
89 }
90 if (postDiv == 0UL)
91 {
92 postDiv = 2UL;
93 }
94 }
95 return postDiv;
96 }
97
98 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)99 static float findPll0MMult(void)
100 {
101 float mMult = 1.0F;
102 float mMult_fract;
103 uint32_t mMult_int;
104
105 if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
106 {
107 mMult = (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
108 }
109 else
110 {
111 mMult_int = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
112 mMult_int = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL_SSCG_MD_INT_P);
113 mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL_SSCG_MD_FRACT_M) /
114 (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
115 mMult = (float)mMult_int + mMult_fract;
116 }
117 if (0ULL == ((uint64_t)mMult))
118 {
119 mMult = 1.0F;
120 }
121 return mMult;
122 }
123
124 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)125 static uint32_t findPll1PreDiv(void)
126 {
127 uint32_t preDiv = 1UL;
128
129 /* Direct input is not used? */
130 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
131 {
132 preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
133 if (preDiv == 0UL)
134 {
135 preDiv = 1UL;
136 }
137 }
138 return preDiv;
139 }
140
141 /* Get postdivider (P) from PLL1 PDEC setting */
findPll1PostDiv(void)142 static uint32_t findPll1PostDiv(void)
143 {
144 uint32_t postDiv = 1UL;
145
146 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
147 {
148 if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
149 {
150 postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
151 }
152 else
153 {
154 postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
155 }
156 if (postDiv == 0UL)
157 {
158 postDiv = 2UL;
159 }
160 }
161 return postDiv;
162 }
163
164 /* Get multiplier (M) from PLL1 MDEC settings */
findPll1MMult(void)165 static uint32_t findPll1MMult(void)
166 {
167 uint32_t mMult = 1UL;
168
169 mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
170
171 if (mMult == 0UL)
172 {
173 mMult = 1UL;
174 }
175 return mMult;
176 }
177
178 /* Get FRO 12M Clk */
179 /*! brief Return Frequency of FRO 12MHz
180 * return Frequency of FRO 12MHz
181 */
GetFro12MFreq(void)182 static uint32_t GetFro12MFreq(void)
183 {
184 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
185 }
186
187 /* Get FRO 1M Clk */
188 /*! brief Return Frequency of FRO 1MHz
189 * return Frequency of FRO 1MHz
190 */
GetFro1MFreq(void)191 static uint32_t GetFro1MFreq(void)
192 {
193 return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
194 }
195
196 /* Get EXT OSC Clk */
197 /*! brief Return Frequency of External Clock
198 * return Frequency of External Clock. If no external clock is used returns 0.
199 */
GetExtClkFreq(void)200 static uint32_t GetExtClkFreq(void)
201 {
202 return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? CLK_CLK_IN : 0U;
203 }
204
205 /* Get HF FRO Clk */
206 /*! brief Return Frequency of High-Freq output of FRO
207 * return Frequency of High-Freq output of FRO
208 */
GetFroHfFreq(void)209 static uint32_t GetFroHfFreq(void)
210 {
211 return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
212 }
213
214 /* Get RTC OSC Clk */
215 /*! brief Return Frequency of 32kHz osc
216 * return Frequency of 32kHz osc
217 */
GetOsc32KFreq(void)218 static uint32_t GetOsc32KFreq(void)
219 {
220 return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) && (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
221 CLK_RTC_32K_CLK :
222 ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) && ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
223 CLK_RTC_32K_CLK :
224 0U;
225 }
226
227
228
229 /* ----------------------------------------------------------------------------
230 -- Core clock
231 ---------------------------------------------------------------------------- */
232
233 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
234
235 /* ----------------------------------------------------------------------------
236 -- SystemInit()
237 ---------------------------------------------------------------------------- */
238
SystemInit(void)239 __attribute__ ((weak)) void SystemInit (void) {
240 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
241 SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); /* set CP10, CP11 Full Access in Secure mode */
242 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
243 SCB_NS->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); /* set CP10, CP11 Full Access in Non-secure mode */
244 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
245 #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
246
247 SCB->CPACR |= ((3UL << 0*2) | (3UL << 1*2)); /* set CP0, CP1 Full Access in Secure mode (enable PowerQuad) */
248 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
249 SCB_NS->CPACR |= ((3UL << 0*2) | (3UL << 1*2)); /* set CP0, CP1 Full Access in Normal mode (enable PowerQuad) */
250 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
251
252 SCB->NSACR |= ((3UL << 0) | (3UL << 10)); /* enable CP0, CP1, CP10, CP11 Non-secure Access */
253
254 #if defined(__MCUXPRESSO)
255 extern void(*const g_pfnVectors[]) (void);
256 SCB->VTOR = (uint32_t) &g_pfnVectors;
257 #else
258 extern void *__Vectors;
259 SCB->VTOR = (uint32_t) &__Vectors;
260 #endif
261 SYSCON->TRACECLKDIV = 0;
262 /* Optionally enable RAM banks that may be off by default at reset */
263 #if !defined(DONT_ENABLE_DISABLED_RAMBANKS)
264 SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL0_SRAM_CTRL1_MASK | SYSCON_AHBCLKCTRL0_SRAM_CTRL2_MASK
265 | SYSCON_AHBCLKCTRL0_SRAM_CTRL3_MASK | SYSCON_AHBCLKCTRL0_SRAM_CTRL4_MASK;
266 #endif
267 SystemInitHook();
268 }
269
270 /* ----------------------------------------------------------------------------
271 -- SystemCoreClockUpdate()
272 ---------------------------------------------------------------------------- */
273
SystemCoreClockUpdate(void)274 void SystemCoreClockUpdate (void) {
275 uint32_t clkRate = 0;
276 uint32_t prediv, postdiv;
277 uint64_t workRate;
278 uint64_t workRate1;
279
280 switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK)
281 {
282 case 0x00: /* MAINCLKSELA clock (main_clk_a)*/
283 switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK)
284 {
285 case 0x00: /* FRO 12 MHz (fro_12m) */
286 clkRate = GetFro12MFreq();
287 break;
288 case 0x01: /* CLKIN (clk_in) */
289 clkRate = GetExtClkFreq();
290 break;
291 case 0x02: /* Fro 1MHz (fro_1m) */
292 clkRate = GetFro1MFreq();
293 break;
294 default: /* = 0x03 = FRO 96 MHz (fro_hf) */
295 clkRate = GetFroHfFreq();
296 break;
297 }
298 break;
299 case 0x01: /* PLL0 clock (pll0_clk)*/
300 switch (SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK)
301 {
302 case 0x00: /* FRO 12 MHz (fro_12m) */
303 clkRate = GetFro12MFreq();
304 break;
305 case 0x01: /* CLKIN (clk_in) */
306 clkRate = GetExtClkFreq();
307 break;
308 case 0x02: /* Fro 1MHz (fro_1m) */
309 clkRate = GetFro1MFreq();
310 break;
311 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
312 clkRate = GetOsc32KFreq();
313 break;
314 default:
315 clkRate = 0UL;
316 break;
317 }
318 if (((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) && ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
319 {
320 prediv = findPll0PreDiv();
321 postdiv = findPll0PostDiv();
322 /* Adjust input clock */
323 clkRate = clkRate / prediv;
324 /* MDEC used for rate */
325 workRate = (uint64_t)clkRate * (uint64_t)findPll0MMult();
326 clkRate = (uint32_t)(workRate / ((uint64_t)postdiv));
327 }
328 break;
329 case 0x02: /* PLL1 clock (pll1_clk)*/
330 switch (SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK)
331 {
332 case 0x00: /* FRO 12 MHz (fro_12m) */
333 clkRate = GetFro12MFreq();
334 break;
335 case 0x01: /* CLKIN (clk_in) */
336 clkRate = GetExtClkFreq();
337 break;
338 case 0x02: /* Fro 1MHz (fro_1m) */
339 clkRate = GetFro1MFreq();
340 break;
341 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
342 clkRate = GetOsc32KFreq();
343 break;
344 default:
345 clkRate = 0UL;
346 break;
347 }
348 if (((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) && ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
349 {
350 /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */
351 prediv = findPll1PreDiv();
352 postdiv = findPll1PostDiv();
353 /* Adjust input clock */
354 clkRate = clkRate / prediv;
355
356 /* MDEC used for rate */
357 workRate1 = (uint64_t)clkRate * (uint64_t)findPll1MMult();
358 clkRate = (uint32_t)(workRate1 / ((uint64_t)postdiv));
359 }
360 break;
361 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
362 clkRate = GetOsc32KFreq();
363 break;
364 default:
365 clkRate = 0UL;
366 break;
367 }
368 SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFFUL) + 1UL);
369 }
370
371 /* ----------------------------------------------------------------------------
372 -- SystemInitHook()
373 ---------------------------------------------------------------------------- */
374
SystemInitHook(void)375 __attribute__ ((weak)) void SystemInitHook (void) {
376 /* Void implementation of the weak function. */
377 }
378