1 /*
2 ** ###################################################################
3 **     Processors:          LPC55S14JBD100
4 **                          LPC55S14JBD64
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:    LPC55S1x/LPC551x User manual Rev.0.6  15 November 2019
12 **     Version:             rev. 1.1, 2019-12-03
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 (2018-08-22)
31 **         Initial version based on v0.2UM
32 **     - rev. 1.1 (2019-12-03)
33 **         Initial version based on v0.6UM
34 **
35 ** ###################################################################
36 */
37 
38 /*!
39  * @file LPC55S14
40  * @version 1.1
41  * @date 2019-12-03
42  * @brief Device specific configuration file for LPC55S14 (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 #endif
266     /* Following code is to reset PUF to remove over consumption */
267     /* Enable PUF register clock to access register */
268     SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
269     /* Release PUF reset */
270     SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_PUF_RST_MASK;
271     /* Enable PUF SRAM */
272     PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK;
273     /* Disable PUF register clock. */
274     // Delaying the line of code below until the PUF State Machine execution is completed:
275     // Shutting down the clock to early will prevent the state machine from reaching the end.
276     // => Wait for status bit in PUF Controller Registers before stop PUF clock.
277     while ((PUF_SRAM_CTRL->INT_STATUS & PUF_SRAM_CTRL_INT_STATUS_READY_MASK) == 0UL)
278     {
279     }
280     SYSCON->AHBCLKCTRLCLR[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
281   SystemInitHook();
282 }
283 
284 /* ----------------------------------------------------------------------------
285    -- SystemCoreClockUpdate()
286    ---------------------------------------------------------------------------- */
287 
SystemCoreClockUpdate(void)288 void SystemCoreClockUpdate (void) {
289     uint32_t clkRate = 0;
290     uint32_t prediv, postdiv;
291     uint64_t workRate;
292     uint64_t workRate1;
293 
294     switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK)
295     {
296         case 0x00: /* MAINCLKSELA clock (main_clk_a)*/
297             switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK)
298             {
299                 case 0x00: /* FRO 12 MHz (fro_12m) */
300                     clkRate = GetFro12MFreq();
301                     break;
302                 case 0x01: /* CLKIN (clk_in) */
303                     clkRate = GetExtClkFreq();
304                     break;
305                 case 0x02: /* Fro 1MHz (fro_1m) */
306                     clkRate = GetFro1MFreq();
307                     break;
308                 default: /* = 0x03 = FRO 96 MHz (fro_hf) */
309                     clkRate = GetFroHfFreq();
310                     break;
311             }
312             break;
313         case 0x01: /* PLL0 clock (pll0_clk)*/
314             switch (SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK)
315             {
316                 case 0x00: /* FRO 12 MHz (fro_12m) */
317                     clkRate = GetFro12MFreq();
318                     break;
319                 case 0x01: /* CLKIN (clk_in) */
320                     clkRate = GetExtClkFreq();
321                     break;
322                 case 0x02: /* Fro 1MHz (fro_1m) */
323                     clkRate = GetFro1MFreq();
324                     break;
325                 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
326                     clkRate = GetOsc32KFreq();
327                     break;
328                 default:
329                     clkRate = 0UL;
330                     break;
331             }
332             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))
333             {
334                 prediv = findPll0PreDiv();
335                 postdiv = findPll0PostDiv();
336                 /* Adjust input clock */
337                 clkRate = clkRate / prediv;
338                 /* MDEC used for rate */
339                 workRate = (uint64_t)clkRate * (uint64_t)findPll0MMult();
340                 clkRate = (uint32_t)(workRate / ((uint64_t)postdiv));
341             }
342             break;
343         case 0x02: /* PLL1 clock (pll1_clk)*/
344             switch (SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK)
345             {
346                 case 0x00: /* FRO 12 MHz (fro_12m) */
347                     clkRate = GetFro12MFreq();
348                     break;
349                 case 0x01: /* CLKIN (clk_in) */
350                     clkRate = GetExtClkFreq();
351                     break;
352                 case 0x02: /* Fro 1MHz (fro_1m) */
353                     clkRate = GetFro1MFreq();
354                     break;
355                 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
356                     clkRate = GetOsc32KFreq();
357                     break;
358                 default:
359                     clkRate = 0UL;
360                     break;
361             }
362             if (((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) && ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
363             {
364                 /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */
365                 prediv = findPll1PreDiv();
366                 postdiv = findPll1PostDiv();
367                 /* Adjust input clock */
368                 clkRate = clkRate / prediv;
369 
370                 /* MDEC used for rate */
371                 workRate1 = (uint64_t)clkRate * (uint64_t)findPll1MMult();
372                 clkRate = (uint32_t)(workRate1 / ((uint64_t)postdiv));
373             }
374             break;
375         case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
376             clkRate = GetOsc32KFreq();
377             break;
378         default:
379             clkRate = 0UL;
380             break;
381     }
382     SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFFUL) + 1UL);
383 }
384 
385 /* ----------------------------------------------------------------------------
386    -- SystemInitHook()
387    ---------------------------------------------------------------------------- */
388 
SystemInitHook(void)389 __attribute__ ((weak)) void SystemInitHook (void) {
390   /* Void implementation of the weak function. */
391 }
392