1 /*
2 ** ###################################################################
3 **     Processors:          LPC55S16JBD100
4 **                          LPC55S16JBD64
5 **                          LPC55S16JEV98
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 LPC55S16
41  * @version 1.1
42  * @date 2019-12-03
43  * @brief Device specific configuration file for LPC55S16 (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     PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK;
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 & PUF_SRAM_CTRL_INT_STATUS_READY_MASK) == 0UL)
279     {
280     }
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