YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
system_msp432p401r.cpp
1
2//
3// system_ext_msp432.c
4//
5// A better system startup file for MSP432 with detailed clock selections
6//
7// Author: Andreas Terstegge April 2020
8//
10
11#include <stdint.h>
12#include "msp.h"
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
19// Configuration section //
21
22// Controls the watchdog timer
23#define WDT_DISABLE 1
24
25// Defines the DCO center frequency (3/6/12/24/48 MHz)
26// DCO_1500kHz|DCO_3MHz|DCO_6MHz|DCO_12MHz|DCO_24MHz|DCO_48MHz
27#ifndef DCO_RSEL
28#define DCO_RSEL DCO_3MHz
29#endif
30
31// Defines the DCO tuning value (-512...511)
32// Use with caution! Too high values might brick the board...
33#ifndef DCO_TUNE
34#define DCO_TUNE 0
35#endif
36
37// Selects the MCLK source: LFXT, VLO, REFO, DCO, MOD, HFXT
38#ifndef MCLK_SELECT
39#define MCLK_SELECT HFXT
40#endif
41
42// Selects the MCLK divider (1/2/4/8/16/32/64/128)
43// DIV1, DIV2, DIV4, DIV8, DIV16, DIV32, DIV64, DIV128
44#ifndef MCLK_DIV
45#define MCLK_DIV DIV1
46#endif
47
48// Selects the SMCLK source: LFXT, VLO, REFO, DCO, MOD, HFXT
49#ifndef SMCLK_SELECT
50#define SMCLK_SELECT HFXT
51#endif
52
53// Selects the SMCLK divider (1/2/4/8/16/32/64/128)
54// DIV1, DIV2, DIV4, DIV8, DIV16, DIV32, DIV64, DIV128
55#ifndef SMCLK_DIV
56#define SMCLK_DIV DIV2
57#endif
58
60// Hardware configuration //
62
63// Defines the HFXT frequency in Hz (e.g. 48000000)
64#define HFXT_HZ 48000000
65
66// Defines the LFXT frequency in Hz (e.g. 32768)
67#define LFXT_HZ 32768
68
70// Defines for configuration values //
72
73#define DCO_1500kHz 0
74#define DCO_3MHz 1
75#define DCO_6MHz 2
76#define DCO_12MHz 3
77#define DCO_24MHz 4
78#define DCO_48MHz 5
79
80#define LFXT 0
81#define VLO 1
82#define REFO 2
83#define DCO 3
84#define MOD 4
85#define HFXT 5
86
87#define DIV1 0
88#define DIV2 1
89#define DIV4 2
90#define DIV8 3
91#define DIV16 4
92#define DIV32 5
93#define DIV64 6
94#define DIV128 7
95
96// Internal clock frequencies, used for SystemCoreClockUpdate()
97#define __VLOCLK 9400
98#define __MODCLK 25000000
99#define __REFOCLK_L 32768
100#define __REFOCLK_H 128000
101#define __SYSCLK 5000000
102
103// Sanity check for HFXT and LFXT
104#if ((MCLK_SELECT == HFXT) || (SMCLK_SELECT == HFXT))
105#ifndef HFXT_HZ
106#error No HFXT frequency specified (HFXT_HZ)
107#endif
108#endif
109
110#if ((MCLK_SELECT == LFXT) || (SMCLK_SELECT == LFXT))
111#ifndef LFXT_HZ
112#error No LFXT frequency specified (LFXT_HZ)
113#endif
114#endif
115
116// Calculate HFXTFREQ bits (for CSCTL2)
117#if (HFXT_HZ > 40000000)
118#define HFXT_FREQ CS_CTL2_HFXTFREQ_6 | CS_CTL2_HFXTDRIVE
119#elif (HFXT_HZ > 32000000)
120#define HFXT_FREQ CS_CTL2_HFXTFREQ_5 | CS_CTL2_HFXTDRIVE
121#elif (HFXT_HZ > 2400000)
122#define HFXT_FREQ CS_CTL2_HFXTFREQ_4 | CS_CTL2_HFXTDRIVE
123#elif (HFXT_HZ > 16000000)
124#define HFXT_FREQ CS_CTL2_HFXTFREQ_3 | CS_CTL2_HFXTDRIVE
125#elif (HFXT_HZ > 8000000)
126#define HFXT_FREQ CS_CTL2_HFXTFREQ_2 | CS_CTL2_HFXTDRIVE
127#elif (HFXT_HZ > 4000000)
128#define HFXT_FREQ CS_CTL2_HFXTFREQ_1 | CS_CTL2_HFXTDRIVE
129#else
130#define HFXT_FREQ CS_CTL2_HFXTFREQ_0
131#endif
132
133#define MCLK_DIVIDER (1 << MCLK_DIV)
134#define SMCLK_DIVIDER (1 << SMCLK_DIV)
135
136// Evaluate the MCLK setting
137#if (MCLK_SELECT == LFXT)
138#define __MASTER_CLOCK (LFXT_HZ / MCLK_DIVIDER)
139#elif (MCLK_SELECT == VLO)
140#define __MASTER_CLOCK (__VLOCLK / MCLK_DIVIDER)
141#elif (MCLK_SELECT == REFO)
142#define __MASTER_CLOCK (__REFOCLK_L / MCLK_DIVIDER)
143#elif (MCLK_SELECT == DCO)
144#define __MASTER_CLOCK ( (1500000 << DCO_RSEL) / MCLK_DIVIDER)
145#elif (MCLK_SELECT == MOD)
146#define __MASTER_CLOCK (__MODCLK / MCLK_DIVIDER)
147#elif (MCLK_SELECT == HFXT)
148#define __MASTER_CLOCK (HFXT_HZ / MCLK_DIVIDER)
149#else
150#error No MCLK source defined (MCLK_SELECT)
151#endif
152
153// Evaluate the SMCLK setting
154#if (MCLK_SELECT == LFXT)
155#define __SUBSYS_CLOCK (LFXT_HZ / SMCLK_DIVIDER)
156#elif (MCLK_SELECT == VLO)
157#define __SUBSYS_CLOCK (__VLOCLK / SMCLK_DIVIDER)
158#elif (MCLK_SELECT == REFO)
159#define __SUBSYS_CLOCK (__REFOCLK_L / SMCLK_DIVIDER)
160#elif (MCLK_SELECT == DCO)
161#define __SUBSYS_CLOCK ((1500000 << DCO_RSEL) / SMCLK_DIVIDER)
162#elif (MCLK_SELECT == MOD)
163#define __SUBSYS_CLOCK (__MODCLK / SMCLK_DIVIDER)
164#elif (MCLK_SELECT == HFXT)
165#define __SUBSYS_CLOCK (HFXT_HZ / SMCLK_DIVIDER)
166#else
167#error No SMCLK source defined (SMCLK_SELECT)
168#endif
169
170// Global clock variables
171uint32_t SystemCoreClock = __MASTER_CLOCK; // the value of MCLK in Hz
172uint32_t SubsystemMasterClock = __SUBSYS_CLOCK; // the value of SMCLK in Hz
173
174// Global xtal frequencies. If the xtal oscillators are enabled
175// during run-time, the frequencies have to be set here so that
176// SystemCoreClockUpdate can use them.
177uint32_t HfxtFrequency = 0;
178uint32_t LfxtFrequency = 0;
179
180
181//
182// Initialize the system
183//
184// @param none
185// @return none
186//
187// @brief Setup the microcontroller system.
188//
189// Performs the following initialization steps:
190// 1. Enables the FPU
191// 2. Enables all SRAM banks
192// 3. Sets up power regulator and VCORE
193// 4. Enable Flash wait states if needed and read buffering
194// 5. Enable HFXT and/or LFXT if needed
195// 6. Configure the Clock System (CS)
196//
197void SystemInit(void)
198{
199 // Control the watchdog timer
200#if (WDT_DISABLE == 1)
201 WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
202#endif
203
204 // Enable FPU (CP10 full access, CP11 full access)
206 // Enable all SRAM banks
207 SYSCTL->SRAM_BANKEN = SYSCTL_SRAM_BANKEN_BNK7_EN;
208
209#if (__MASTER_CLOCK >= 48000000)
210 // Switches to DCDC VCORE1
211 while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
213 while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
214 // 1 flash wait states (BANK0 VCORE1 max is 16 MHz,
215 // BANK1 VCORE1 max is 32 MHz)
220#elif (__MASTER_CLOCK >= 24000000)
221 // Switches to DCDC VCORE0
222 while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
224 while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
225 // Enable read buffering and 1 flash wait state (BANK0 VCORE0 max is 12 MHz)
228#endif
229
230 // Unlock CS module
231 CS->KEY = CS_KEY_VAL;
232#ifdef HFXT_HZ
233 HfxtFrequency = HFXT_HZ;
234 // Enable the HFXT crystal oscillator.
235 // Initialize PJ for HFXT
236 PJ->SEL0 |= BIT3;
237 PJ->SEL1 &= ~BIT3;
238 CS->CTL2 |= CS_CTL2_HFXT_EN | HFXT_FREQ;
239 // Wait for the HFXT to stabilize. After a soft reset
240 // this code might run with 48MHz, so we make sure the
241 // clock is stable for some loop iterations...
242 for (int count=0; count < 200; ++count) {
243 if (CS->IFG & CS_IFG_HFXTIFG) {
244 CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG;
245 }
246 }
247#endif
248
249#ifdef LFXT_HZ
250 LfxtFrequency = LFXT_HZ;
251 // Enable the LFXT crystal oscillator. If the LFXT is not
252 // available, the system will switch automatically to
253 // REFOCLK with 32768Hz mode (less precision...).
254 // Initialize PJ for LFXT
255 PJ->SEL0 |= BIT0;
256 PJ->SEL1 &= ~BIT0;
257 // Enable LFXT
258 CS->CTL2 |= CS_CTL2_LFXT_EN; // Enable LFXT
259 // Wait for the LFXT to stabilize. After a soft reset
260 // this code might run with 48MHz, so we make sure the
261 // clock is stable for some loop iterations...
262 for (int count=0; count < 200; ++count) {
263 if (CS->IFG & CS_IFG_LFXTIFG) {
264 CS->CLRIFG |= CS_CLRIFG_CLR_LFXTIFG;
265 }
266 }
267#endif
268
269 // Set CTL0 and CTL1
270 CS->CTL0 =(DCO_RSEL << CS_CTL0_DCORSEL_OFS) |
271 (DCO_TUNE & 0x3ff);
272 CS->CTL1 = MCLK_SELECT << CS_CTL1_SELM_OFS |
273 MCLK_DIV << CS_CTL1_DIVM_OFS |
274 SMCLK_SELECT << CS_CTL1_SELS_OFS |
275 SMCLK_DIV << CS_CTL1_DIVS_OFS;
276
277 // Lock CS module
278 CS->KEY = 0;
279
280 // Update the global clock values.
281 SystemCoreClockUpdate();
282}
283
284// Start the SysTick Timer
285void __attribute__((constructor)) StartSysTick (void) {
286 SysTick_Config(SystemCoreClock / 1000);
287}
288
289//
290// Calculate the DCO clock using the DCO tune value
291//
292// @param dco_base_clock: The DCO base clock without
293// using the DCO tune value
294// @return The real DCO clock
295//
296// @brief Calcluates the DCO clock using the DCO tune value
297//
298uint32_t calculate_DCO_clock(uint32_t dco_base_clock)
299{
300 // Get DCO tune value
301 int16_t __DCOTUNE = (CS->CTL0 & CS_CTL0_DCOTUNE_MASK)
303 // Check if we have a zero tune value
304 if (!__DCOTUNE) {
305 return dco_base_clock;
306 }
307 // Convert 10 bits signed int to 16 bits signed int
308 if (__DCOTUNE & 0x0200) {
309 __DCOTUNE |= 0xFC00;
310 }
311 // Get calibration data
312 float __DCO_CONSTK;
313 uint32_t __DCO_FCAL;
314 if (CS->CTL0 & CS_CTL0_DCORES) {
315 // external resistor
316 if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
317 // DCORSEL is 5
318 __DCO_CONSTK = TLV->DCOER_CONSTK_RSEL5;
319 __DCO_FCAL = TLV->DCOER_FCAL_RSEL5;
320 } else {
321 // DCORSEL is 0..4
322 __DCO_CONSTK = TLV->DCOER_CONSTK_RSEL04;
323 __DCO_FCAL = TLV->DCOER_FCAL_RSEL04;
324 }
325 } else {
326 // internal resistor
327 if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
328 // DCORSEL is 5
329 __DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL5;
330 __DCO_FCAL = TLV->DCOIR_FCAL_RSEL5;
331 } else {
332 // DCORSEL is 0..4
333 __DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL04;
334 __DCO_FCAL = TLV->DCOIR_FCAL_RSEL04;
335 }
336 }
337 // Calculate tuned frequency
338 float denom = 1.0f / __DCO_CONSTK + 768 - (float)__DCO_FCAL;
339 return (float)dco_base_clock / (1.0f - (float)__DCOTUNE / denom);
340}
341
342
343//
344// Update SystemCoreClock and SubsystemMasterClock variables
345//
346// @param none
347// @return none
348//
349// @brief Updates the SystemCoreClock and SubsystemMasterClock
350// with current core Clock retrieved from CS registers.
351//
352void SystemCoreClockUpdate(void)
353{
354 // Check which source is selected for MCLK
355 switch (CS->CTL1 & CS_CTL1_SELM_MASK) {
359 // Check if we still have a LFXT fault
360 if (CS->IFG & CS_IFG_LFXTIFG) {
361 // According to the TRM, a LFXT fault will
362 // always switch to REFOCLK with 32768Hz
363 SystemCoreClock = __REFOCLK_L;
364 } else {
365 SystemCoreClock = LfxtFrequency;
366 }
367 break;
368 }
370 case CS_CTL1_SELM__VLOCLK: {
372 SystemCoreClock = __VLOCLK;
373 break;
374 }
376 case CS_CTL1_SELM__REFOCLK: {
378 if (CS->CLKEN & CS_CLKEN_REFOFSEL) {
379 SystemCoreClock = __REFOCLK_H;
380 } else {
381 SystemCoreClock = __REFOCLK_L;
382 }
383 break;
384 }
386 case CS_CTL1_SELM__DCOCLK: {
388 // Set the center frequency
389 SystemCoreClock = 1500000 << ((CS->CTL0 & CS_CTL0_DCORSEL_MASK)
391 SystemCoreClock = calculate_DCO_clock(SystemCoreClock);
392 break;
393 }
395 case CS_CTL1_SELM__MODOSC: {
397 SystemCoreClock = __MODCLK;
398 break;
399 }
403 // Check if we still have a HFXT fault
404 if (CS->IFG & CS_IFG_HFXTIFG) {
405 // According to the TRM, a HFXT fault will
406 // switch over to SYSOSC...
407 SystemCoreClock = __SYSCLK;
408 } else {
409 SystemCoreClock = HfxtFrequency;
410 }
411 break;
412 }
413 }
414 // Check which source is selected for SMCLK
415 switch (CS->CTL1 & CS_CTL1_SELS_MASK) {
419 // Check if we still have a LFXT fault
420 if (CS->IFG & CS_IFG_LFXTIFG_OFS) {
421 // According to the TRM, a LFXT fault will
422 // always switch to REFOCLK with 32768Hz
423 SubsystemMasterClock = __REFOCLK_L;
424 } else {
425 SubsystemMasterClock = LfxtFrequency;
426 }
427 break;
428 }
430 case CS_CTL1_SELS__VLOCLK: {
432 SubsystemMasterClock = __VLOCLK;
433 break;
434 }
436 case CS_CTL1_SELS__REFOCLK: {
438 if (CS->CLKEN & CS_CLKEN_REFOFSEL) {
439 SubsystemMasterClock = __REFOCLK_H;
440 } else {
441 SubsystemMasterClock = __REFOCLK_L;
442 }
443 break;
444 }
446 case CS_CTL1_SELS__DCOCLK: {
448 // Set the center frequency
449 SubsystemMasterClock = 1500000 << ((CS->CTL0 & CS_CTL0_DCORSEL_MASK)
451 SubsystemMasterClock = calculate_DCO_clock(SubsystemMasterClock);
452 break;
453 }
455 case CS_CTL1_SELS__MODOSC: {
457 SubsystemMasterClock = __MODCLK;
458 break;
459 }
463 // Check if we still have a HFXT fault
464 if (CS->IFG & CS_IFG_HFXTIFG) {
465 // According to the TRM, a HFXT fault will
466 // switch over to SYSOSC...
467 SubsystemMasterClock = __SYSCLK;
468 } else {
469 SubsystemMasterClock = HfxtFrequency;
470 }
471 break;
472 }
473 }
474 // Get the MCLK and SMCLK dividers
475 int32_t __DIVM = 1 << ((CS->CTL1 & CS_CTL1_DIVM_MASK) >> CS_CTL1_DIVM_OFS);
476 int32_t __DIVS = 1 << ((CS->CTL1 & CS_CTL1_DIVS_MASK) >> CS_CTL1_DIVS_OFS);
477 // Update SystemCoreClock (MCLK) with divider value
478 SystemCoreClock /= __DIVM;
479 // Update SubsystemMasterClock (SMCLK) with divider value
480 SubsystemMasterClock /= __DIVS;
481}
482
483#ifdef __cplusplus
484}
485#endif
#define SCB
#define CS_CTL1_DIVS_MASK
#define CS_IFG_HFXTIFG
#define CS_CTL0_DCORSEL_5
#define CS_CTL1_SELS_MASK
#define CS_CTL0_DCORSEL_MASK
#define CS_CTL0_DCORSEL_OFS
#define CS_CLRIFG_CLR_LFXTIFG
#define CS_CTL0_DCOTUNE_MASK
#define CS_CTL1_SELS__HFXTCLK
#define FLCTL_BANK0_RDCTL_BUFD
#define FLCTL_BANK1_RDCTL_BUFD
#define CS_IFG_LFXTIFG_OFS
#define WDT_A_CTL_HOLD
#define CS_CLRIFG_CLR_HFXTIFG
#define PCM_CTL0_AMR__AM_DCDC_VCORE0
#define FLCTL_BANK0_RDCTL_BUFI
#define FLCTL_BANK0_RDCTL_WAIT_1
#define CS_CTL0_DCOTUNE_OFS
#define CS_CTL1_DIVM_OFS
#define CS_CTL1_SELM_MASK
#define CS_IFG_LFXTIFG
#define CS_CTL1_SELM__LFXTCLK
#define PCM_CTL0_AMR__AM_DCDC_VCORE1
#define CS_CTL0_DCORES
#define CS_KEY_VAL
#define CS_CTL2_LFXT_EN
#define WDT_A_CTL_PW
#define SCB_CPACR_CP11_MASK
#define FLCTL_BANK1_RDCTL_WAIT_1
#define CS_CTL2_HFXT_EN
#define CS_CLKEN_REFOFSEL
#define CS_CTL1_SELS__LFXTCLK
#define PCM_CTL1_PMR_BUSY
#define CS_CTL1_SELS_OFS
#define PCM_CTL0_KEY_VAL
#define SYSCTL_SRAM_BANKEN_BNK7_EN
#define FLCTL_BANK1_RDCTL_BUFI
#define CS_CTL1_DIVS_OFS
#define CS_CTL1_SELM__HFXTCLK
#define CS_CTL1_DIVM_MASK
#define CS_CTL1_SELM_OFS
#define SCB_CPACR_CP10_MASK
void __attribute__((noreturn))(*rom_reset_usb_boot_fn)(uint32_t
Reboot the device into BOOTSEL mode.
Definition bootrom.h:66