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