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