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