Contiki-NG
Loading...
Searching...
No Matches
msp430.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2026, RISE Research Institutes of Sweden AB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/**
31 * \file
32 * MSP430FR5969 CPU initialization
33 *
34 * Configures the Clock System (CS) for 8MHz DCO operation.
35 */
36
37#include "contiki.h"
38#include <msp430.h>
39
40#if defined(__MSP430__) && defined(__GNUC__)
41#define asmv(arg) __asm__ __volatile__(arg)
42#endif
43
44/* Flag for timers/serial to indicate DCO must be kept on in LPM */
45int msp430_dco_required;
46
47/*---------------------------------------------------------------------------*/
48/**
49 * Initialize the Clock System (CS) module.
50 *
51 * Configure:
52 * - DCO at 8 MHz
53 * - MCLK = SMCLK = DCO
54 * - ACLK = LFXT (32.768 kHz on-board crystal), with VLOCLK fallback
55 * if the crystal fails to stabilize.
56 *
57 * Also configures FRAM wait states for 8MHz operation.
58 */
59static void
61{
62 /* Route PJ.4/PJ.5 to the LFXT crystal before unlocking the LPM5
63 * port latch so the pins come up in peripheral function. */
64 PJSEL0 |= BIT4 | BIT5;
65 PJSEL1 &= ~(BIT4 | BIT5);
66
67 /* Disable the GPIO power-on default high-impedance mode to activate
68 * previously configured port settings */
69 PM5CTL0 &= ~LOCKLPM5;
70
71 /* Configure FRAM wait state (required for >8MHz operation)
72 * FWPW = FRAM write password
73 * NACCESS_0 = 0 wait states for up to 8MHz operation
74 */
75 FRCTL0 = FWPW | NACCESS_0;
76
77 /* Unlock CS registers (CSKEY >> 8 to get high byte) */
78 CSCTL0_H = (CSKEY >> 8);
79
80 /* Configure DCO to 8MHz */
81 CSCTL1 = DCOFSEL_6; /* DCO = 8 MHz */
82
83 /* Start LFXT with default drive strength. Source ACLK from VLO
84 * initially so the system can run even before the crystal
85 * stabilizes; we switch to LFXT below once OFIFG stays cleared. */
86 CSCTL4 = (CSCTL4 & ~(LFXTOFF | LFXTBYPASS)) | LFXTDRIVE_3;
87 CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
88
89 /* Set clock dividers (all divide by 1) */
90 CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;
91
92 /* Wait up to ~500 ms for the LFXT to stabilize. Each iteration
93 * clears LFXTOFFG and the system oscillator fault flag, then
94 * delays ~10 ms at 8 MHz; 50 iterations gives a 500 ms cap. If
95 * the crystal never stabilizes (e.g. unpopulated or broken), we
96 * leave ACLK on VLOCLK so etimer/rtimer still tick. */
97 for(int retries = 0; retries < 50; retries++) {
98 CSCTL5 &= ~LFXTOFFG;
99 SFRIFG1 &= ~OFIFG;
100 __delay_cycles(80000);
101 if((CSCTL5 & LFXTOFFG) == 0 && (SFRIFG1 & OFIFG) == 0) {
102 break;
103 }
104 }
105 if((SFRIFG1 & OFIFG) == 0) {
106 CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
107 }
108
109 /* Lock CS registers */
110 CSCTL0_H = 0;
111
112 msp430_dco_required = 0;
113}
114/*---------------------------------------------------------------------------*/
115/**
116 * Initialize all ports to output low to reduce power consumption.
117 *
118 * PJ is intentionally left at its reset default (all inputs):
119 * - PJ.0..PJ.3 carry the JTAG signals used by the eZ-FET probe.
120 * - PJ.4/PJ.5 are the LFXT crystal pins; driving them as outputs
121 * would jam the 32.768 kHz oscillator that sources ACLK.
122 */
123static void
125{
126 /* Configure all GPIO to output low */
127 P1OUT = 0;
128 P1DIR = 0xFF;
129 P2OUT = 0;
130 P2DIR = 0xFF;
131 P3OUT = 0;
132 P3DIR = 0xFF;
133 P4OUT = 0;
134 P4DIR = 0xFF;
135}
136/*---------------------------------------------------------------------------*/
137void
138msp430_cpu_init(void)
139{
140 /* Stop watchdog timer */
141 WDTCTL = WDTPW | WDTHOLD;
142
143 /* Initialize ports first (reduces power) */
144 init_ports();
145
146 /* Initialize DCO and clock system */
148
149 /* Enable global interrupts */
150 eint();
151}
152/*---------------------------------------------------------------------------*/
153/**
154 * Synchronize DCO (no-op for FR5969, DCO is automatically calibrated).
155 */
156void
158{
159 /* FR5969 DCO is factory calibrated, no sync needed */
160}
161/*---------------------------------------------------------------------------*/
162/**
163 * Mask all interrupts that can be masked.
164 */
165int
167{
168 int sr;
169 /* Clear the GIE (General Interrupt Enable) flag. */
170#ifdef __IAR_SYSTEMS_ICC__
171 sr = __get_SR_register();
172 __bic_SR_register(GIE);
173#else
174 asmv("mov r2, %0" : "=r" (sr));
175 asmv("bic %0, r2" : : "i" (GIE));
176 /* GCC 9 warns about risk of incorrect execution without nop after
177 interrupt state changes. */
178 asmv("nop");
179#endif
180 return sr & GIE; /* Ignore other sr bits. */
181}
182/*---------------------------------------------------------------------------*/
183#ifdef __IAR_SYSTEMS_ICC__
184int __low_level_init(void)
185{
186 /* turn off watchdog so that C-init will run */
187 WDTCTL = WDTPW + WDTHOLD;
188 return 1;
189}
190#endif
191/*---------------------------------------------------------------------------*/
static void msp430_init_dco(void)
Initialize the Clock System (CS) module.
Definition msp430.c:60
static void init_ports(void)
Initialize all ports to output low to reduce power consumption.
Definition msp430.c:124
int splhigh_(void)
Mask all interrupts that can be masked.
Definition msp430.c:166
void msp430_sync_dco(void)
Synchronize DCO (no-op for FR5969, DCO is automatically calibrated).
Definition msp430.c:157