diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S16/system_LPC55S16.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S16/system_LPC55S16.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S16/system_LPC55S16.c b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S16/system_LPC55S16.c new file mode 100644 index 000000000..6e00b0883 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/LPC55S16/system_LPC55S16.c | |||
@@ -0,0 +1,401 @@ | |||
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: b201015 | ||
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-2020 NXP | ||
23 | ** All rights reserved. | ||
24 | ** | ||
25 | ** SPDX-License-Identifier: BSD-3-Clause | ||
26 | ** | ||
27 | ** http: www.nxp.com | ||
28 | ** mail: [email protected] | ||
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 */ | ||
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 */ | ||
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 */ | ||
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 = | ||
109 | (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT); | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | mMult_int = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U); | ||
114 | mMult_int = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL_SSCG_MD_INT_P); | ||
115 | mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL_SSCG_MD_FRACT_M) / | ||
116 | (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P)); | ||
117 | mMult = (float)mMult_int + mMult_fract; | ||
118 | } | ||
119 | if (mMult == 0.0F) | ||
120 | { | ||
121 | mMult = 1.0F; | ||
122 | } | ||
123 | return mMult; | ||
124 | } | ||
125 | |||
126 | /* Get predivider (N) from PLL1 NDEC setting */ | ||
127 | static uint32_t findPll1PreDiv(void) | ||
128 | { | ||
129 | uint32_t preDiv = 1UL; | ||
130 | |||
131 | /* Direct input is not used? */ | ||
132 | if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL) | ||
133 | { | ||
134 | preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK; | ||
135 | if (preDiv == 0UL) | ||
136 | { | ||
137 | preDiv = 1UL; | ||
138 | } | ||
139 | } | ||
140 | return preDiv; | ||
141 | } | ||
142 | |||
143 | /* Get postdivider (P) from PLL1 PDEC setting */ | ||
144 | static uint32_t findPll1PostDiv(void) | ||
145 | { | ||
146 | uint32_t postDiv = 1UL; | ||
147 | |||
148 | if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL) | ||
149 | { | ||
150 | if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL) | ||
151 | { | ||
152 | postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK; | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK); | ||
157 | } | ||
158 | if (postDiv == 0UL) | ||
159 | { | ||
160 | postDiv = 2UL; | ||
161 | } | ||
162 | } | ||
163 | return postDiv; | ||
164 | } | ||
165 | |||
166 | /* Get multiplier (M) from PLL1 MDEC settings */ | ||
167 | static uint32_t findPll1MMult(void) | ||
168 | { | ||
169 | uint32_t mMult = 1UL; | ||
170 | |||
171 | mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK; | ||
172 | |||
173 | if (mMult == 0UL) | ||
174 | { | ||
175 | mMult = 1UL; | ||
176 | } | ||
177 | return mMult; | ||
178 | } | ||
179 | |||
180 | /* Get FRO 12M Clk */ | ||
181 | /*! brief Return Frequency of FRO 12MHz | ||
182 | * return Frequency of FRO 12MHz | ||
183 | */ | ||
184 | static uint32_t GetFro12MFreq(void) | ||
185 | { | ||
186 | return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U; | ||
187 | } | ||
188 | |||
189 | /* Get FRO 1M Clk */ | ||
190 | /*! brief Return Frequency of FRO 1MHz | ||
191 | * return Frequency of FRO 1MHz | ||
192 | */ | ||
193 | static uint32_t GetFro1MFreq(void) | ||
194 | { | ||
195 | return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U; | ||
196 | } | ||
197 | |||
198 | /* Get EXT OSC Clk */ | ||
199 | /*! brief Return Frequency of External Clock | ||
200 | * return Frequency of External Clock. If no external clock is used returns 0. | ||
201 | */ | ||
202 | static uint32_t GetExtClkFreq(void) | ||
203 | { | ||
204 | return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? CLK_CLK_IN : 0U; | ||
205 | } | ||
206 | |||
207 | /* Get HF FRO Clk */ | ||
208 | /*! brief Return Frequency of High-Freq output of FRO | ||
209 | * return Frequency of High-Freq output of FRO | ||
210 | */ | ||
211 | static uint32_t GetFroHfFreq(void) | ||
212 | { | ||
213 | return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U; | ||
214 | } | ||
215 | |||
216 | /* Get RTC OSC Clk */ | ||
217 | /*! brief Return Frequency of 32kHz osc | ||
218 | * return Frequency of 32kHz osc | ||
219 | */ | ||
220 | static uint32_t GetOsc32KFreq(void) | ||
221 | { | ||
222 | return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) && | ||
223 | (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ? | ||
224 | CLK_RTC_32K_CLK : | ||
225 | ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) && | ||
226 | ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ? | ||
227 | CLK_RTC_32K_CLK : | ||
228 | 0U; | ||
229 | } | ||
230 | |||
231 | /* ---------------------------------------------------------------------------- | ||
232 | -- Core clock | ||
233 | ---------------------------------------------------------------------------- */ | ||
234 | |||
235 | uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK; | ||
236 | |||
237 | /* ---------------------------------------------------------------------------- | ||
238 | -- SystemInit() | ||
239 | ---------------------------------------------------------------------------- */ | ||
240 | |||
241 | __attribute__((weak)) void SystemInit(void) | ||
242 | { | ||
243 | #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) | ||
244 | SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access in Secure mode */ | ||
245 | #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) | ||
246 | SCB_NS->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access in Non-secure mode */ | ||
247 | #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ | ||
248 | #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */ | ||
249 | |||
250 | SCB->CPACR |= ((3UL << 0 * 2) | (3UL << 1 * 2)); /* set CP0, CP1 Full Access in Secure mode (enable PowerQuad) */ | ||
251 | #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) | ||
252 | SCB_NS->CPACR |= ((3UL << 0 * 2) | (3UL << 1 * 2)); /* set CP0, CP1 Full Access in Normal mode (enable PowerQuad) */ | ||
253 | #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ | ||
254 | |||
255 | SCB->NSACR |= ((3UL << 0) | (3UL << 10)); /* enable CP0, CP1, CP10, CP11 Non-secure Access */ | ||
256 | |||
257 | #if defined(__MCUXPRESSO) | ||
258 | extern void (*const g_pfnVectors[])(void); | ||
259 | SCB->VTOR = (uint32_t)&g_pfnVectors; | ||
260 | #else | ||
261 | extern void *__Vectors; | ||
262 | SCB->VTOR = (uint32_t)&__Vectors; | ||
263 | #endif | ||
264 | SYSCON->TRACECLKDIV = 0; | ||
265 | /* Optionally enable RAM banks that may be off by default at reset */ | ||
266 | #if !defined(DONT_ENABLE_DISABLED_RAMBANKS) | ||
267 | SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL0_SRAM_CTRL1_MASK | SYSCON_AHBCLKCTRL0_SRAM_CTRL2_MASK; | ||
268 | #endif | ||
269 | /* Following code is to reset PUF to remove over consumption */ | ||
270 | /* Enable PUF register clock to access register */ | ||
271 | SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_PUF_MASK; | ||
272 | /* Release PUF reset */ | ||
273 | SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_PUF_RST_MASK; | ||
274 | /* Enable PUF SRAM */ | ||
275 | PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK; | ||
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 & PUF_SRAM_CTRL_INT_STATUS_READY_MASK) == 0UL) | ||
281 | { | ||
282 | } | ||
283 | SYSCON->AHBCLKCTRLCLR[2] = SYSCON_AHBCLKCTRL2_PUF_MASK; | ||
284 | SystemInitHook(); | ||
285 | } | ||
286 | |||
287 | /* ---------------------------------------------------------------------------- | ||
288 | -- SystemCoreClockUpdate() | ||
289 | ---------------------------------------------------------------------------- */ | ||
290 | |||
291 | void SystemCoreClockUpdate(void) | ||
292 | { | ||
293 | uint32_t clkRate = 0; | ||
294 | uint32_t prediv, postdiv; | ||
295 | uint64_t workRate; | ||
296 | uint64_t workRate1; | ||
297 | |||
298 | switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK) | ||
299 | { | ||
300 | case 0x00: /* MAINCLKSELA clock (main_clk_a)*/ | ||
301 | switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK) | ||
302 | { | ||
303 | case 0x00: /* FRO 12 MHz (fro_12m) */ | ||
304 | clkRate = GetFro12MFreq(); | ||
305 | break; | ||
306 | case 0x01: /* CLKIN (clk_in) */ | ||
307 | clkRate = GetExtClkFreq(); | ||
308 | break; | ||
309 | case 0x02: /* Fro 1MHz (fro_1m) */ | ||
310 | clkRate = GetFro1MFreq(); | ||
311 | break; | ||
312 | default: /* = 0x03 = FRO 96 MHz (fro_hf) */ | ||
313 | clkRate = GetFroHfFreq(); | ||
314 | break; | ||
315 | } | ||
316 | break; | ||
317 | case 0x01: /* PLL0 clock (pll0_clk)*/ | ||
318 | switch (SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK) | ||
319 | { | ||
320 | case 0x00: /* FRO 12 MHz (fro_12m) */ | ||
321 | clkRate = GetFro12MFreq(); | ||
322 | break; | ||
323 | case 0x01: /* CLKIN (clk_in) */ | ||
324 | clkRate = GetExtClkFreq(); | ||
325 | break; | ||
326 | case 0x02: /* Fro 1MHz (fro_1m) */ | ||
327 | clkRate = GetFro1MFreq(); | ||
328 | break; | ||
329 | case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */ | ||
330 | clkRate = GetOsc32KFreq(); | ||
331 | break; | ||
332 | default: | ||
333 | clkRate = 0UL; | ||
334 | break; | ||
335 | } | ||
336 | if (((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) && | ||
337 | ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) && | ||
338 | ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) && | ||
339 | ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL)) | ||
340 | { | ||
341 | prediv = findPll0PreDiv(); | ||
342 | postdiv = findPll0PostDiv(); | ||
343 | /* Adjust input clock */ | ||
344 | clkRate = clkRate / prediv; | ||
345 | /* MDEC used for rate */ | ||
346 | workRate = (uint64_t)clkRate * (uint64_t)findPll0MMult(); | ||
347 | clkRate = (uint32_t)(workRate / ((uint64_t)postdiv)); | ||
348 | } | ||
349 | break; | ||
350 | case 0x02: /* PLL1 clock (pll1_clk)*/ | ||
351 | switch (SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK) | ||
352 | { | ||
353 | case 0x00: /* FRO 12 MHz (fro_12m) */ | ||
354 | clkRate = GetFro12MFreq(); | ||
355 | break; | ||
356 | case 0x01: /* CLKIN (clk_in) */ | ||
357 | clkRate = GetExtClkFreq(); | ||
358 | break; | ||
359 | case 0x02: /* Fro 1MHz (fro_1m) */ | ||
360 | clkRate = GetFro1MFreq(); | ||
361 | break; | ||
362 | case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */ | ||
363 | clkRate = GetOsc32KFreq(); | ||
364 | break; | ||
365 | default: | ||
366 | clkRate = 0UL; | ||
367 | break; | ||
368 | } | ||
369 | if (((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) && | ||
370 | ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) && | ||
371 | ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL)) | ||
372 | { | ||
373 | /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */ | ||
374 | prediv = findPll1PreDiv(); | ||
375 | postdiv = findPll1PostDiv(); | ||
376 | /* Adjust input clock */ | ||
377 | clkRate = clkRate / prediv; | ||
378 | |||
379 | /* MDEC used for rate */ | ||
380 | workRate1 = (uint64_t)clkRate * (uint64_t)findPll1MMult(); | ||
381 | clkRate = (uint32_t)(workRate1 / ((uint64_t)postdiv)); | ||
382 | } | ||
383 | break; | ||
384 | case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */ | ||
385 | clkRate = GetOsc32KFreq(); | ||
386 | break; | ||
387 | default: | ||
388 | clkRate = 0UL; | ||
389 | break; | ||
390 | } | ||
391 | SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFFUL) + 1UL); | ||
392 | } | ||
393 | |||
394 | /* ---------------------------------------------------------------------------- | ||
395 | -- SystemInitHook() | ||
396 | ---------------------------------------------------------------------------- */ | ||
397 | |||
398 | __attribute__((weak)) void SystemInitHook(void) | ||
399 | { | ||
400 | /* Void implementation of the weak function. */ | ||
401 | } | ||