Contiki-NG
Toggle main menu visibility
Loading...
Searching...
No Matches
msp430.c
1
/*
2
* Copyright (c) 2005, Swedish Institute of Computer Science
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
* This file is part of the Contiki operating system.
30
*/
31
32
#include "contiki.h"
33
#include "dev/watchdog.h"
34
35
/* dco_required set to 1 will cause the CPU not to go into
36
* sleep modes where the DCO clock stopped */
37
int
msp430_dco_required;
38
39
#if defined(__MSP430__) && defined(__GNUC__)
40
#define asmv(arg) __asm__ __volatile__ (arg)
41
#endif
42
43
/*---------------------------------------------------------------------------*/
44
#if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND
45
void
*
46
w_memcpy(
void
*out,
const
void
*in,
size_t
n)
47
{
48
uint8_t *src, *dest;
49
src = (uint8_t *)in;
50
dest = (uint8_t *)out;
51
while
(n-- > 0) {
52
*dest++ = *src++;
53
}
54
return
out;
55
}
56
#endif
/* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */
57
/*---------------------------------------------------------------------------*/
58
#if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND
59
void
*
60
w_memset(
void
*out,
int
value
,
size_t
n)
61
{
62
uint8_t *dest;
63
dest = (uint8_t *)out;
64
while
(n-- > 0) {
65
*dest++ =
value
& 0xff;
66
}
67
return
out;
68
}
69
#endif
/* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */
70
/*---------------------------------------------------------------------------*/
71
void
72
msp430_init_dco
(
void
)
73
{
74
if
(CALBC1_8MHZ != 0xFF) {
75
DCOCTL = 0x00;
76
BCSCTL1 = CALBC1_8MHZ;
/*Set DCO to 8MHz */
77
DCOCTL = CALDCO_8MHZ;
78
}
else
{
/*start using reasonable values at 8 Mhz */
79
DCOCTL = 0x00;
80
BCSCTL1 = 0x8D;
81
DCOCTL = 0x88;
82
}
83
84
/*BCSCTL1 |= XT2OFF; // Make sure XT2 is off */
85
/* BCSCTL2 = 0x00; // MCLK = DCOCLK/1 */
86
/* SMCLK = DCOCLK/1 */
87
/* DCO Internal Resistor */
88
}
89
/*---------------------------------------------------------------------------*/
90
static
void
91
init_ports
(
void
)
92
{
93
/* Turn everything off, device drivers enable what is needed. */
94
95
/* All configured for digital I/O */
96
#ifdef P1SEL
97
P1SEL = 0;
98
#endif
99
#ifdef P2SEL
100
P2SEL = 0;
101
#endif
102
#ifdef P3SEL
103
P3SEL = 0;
104
#endif
105
#ifdef P4SEL
106
P4SEL = 0;
107
#endif
108
#ifdef P5SEL
109
P5SEL = 0;
110
#endif
111
#ifdef P6SEL
112
P6SEL = 0;
113
#endif
114
115
/* All available inputs */
116
#ifdef P1DIR
117
P1DIR = 0;
118
P1OUT = 0;
119
#endif
120
#ifdef P2DIR
121
P2DIR = 0;
122
P2OUT = 0;
123
#endif
124
#ifdef P3DIR
125
P3DIR = 0;
126
P3OUT = 0;
127
#endif
128
#ifdef P4DIR
129
P4DIR = 0;
130
P4OUT = 0;
131
#endif
132
133
#ifdef P5DIR
134
P5DIR = 0;
135
P5OUT = 0;
136
#endif
137
138
#ifdef P6DIR
139
P6DIR = 0;
140
P6OUT = 0;
141
#endif
142
143
#ifdef P7DIR
144
P7DIR = 0;
145
P7OUT = 0;
146
#endif
147
148
#ifdef P8DIR
149
P8DIR = 0;
150
P8OUT = 0;
151
#endif
152
153
P1IE = 0;
154
P2IE = 0;
155
}
156
/*---------------------------------------------------------------------------*/
157
/* msp430-ld may align _end incorrectly. Workaround in cpu_init. */
158
#if defined(__MSP430__) && defined(__GNUC__)
159
extern
int
_end;
/* Not in sys/unistd.h */
160
static
char
*cur_break = (
char
*)&_end;
161
#endif
162
163
/*---------------------------------------------------------------------------*/
164
/* add/remove_lpm_req - for requiring a specific LPM mode. currently Contiki */
165
/* jumps to LPM3 to save power, but DMA will not work if DCO is not clocked */
166
/* so some modules might need to enter their LPM requirements */
167
/* NOTE: currently only works with LPM1 (e.g. DCO) requirements. */
168
/*---------------------------------------------------------------------------*/
169
void
170
msp430_add_lpm_req(
int
req)
171
{
172
if
(req <= MSP430_REQUIRE_LPM1) {
173
msp430_dco_required++;
174
}
175
}
176
void
177
msp430_remove_lpm_req(
int
req)
178
{
179
if
(req <= MSP430_REQUIRE_LPM1) {
180
msp430_dco_required--;
181
}
182
}
183
void
184
msp430_cpu_init(
void
)
185
{
186
dint();
187
watchdog_init
();
188
init_ports
();
189
/* set DCO to a reasonable default value (8MHz) */
190
msp430_init_dco
();
191
/* calibrate the DCO step-by-step */
192
msp430_sync_dco
();
193
eint();
194
#if defined(__MSP430__) && defined(__GNUC__)
195
if
((uintptr_t)cur_break & 1) {
/* Workaround for msp430-ld bug! */
196
cur_break++;
197
}
198
#endif
199
msp430_dco_required = 0;
200
}
201
/*---------------------------------------------------------------------------*/
202
203
/*---------------------------------------------------------------------------*/
204
/*
205
* Mask all interrupts that can be masked.
206
*/
207
int
208
splhigh_
(
void
)
209
{
210
/* Clear the GIE (General Interrupt Enable) flag. */
211
int
sr;
212
#ifdef __IAR_SYSTEMS_ICC__
213
sr = __get_SR_register();
214
__bic_SR_register(GIE);
215
#else
216
asmv(
"mov r2, %0"
:
"=r"
(sr));
217
asmv(
"bic %0, r2"
: :
"i"
(GIE));
218
/* GCC 9 warns about risk of incorrect execution without nop after
219
interrupt state changes. */
220
asmv(
"nop"
);
221
#endif
222
return
sr & GIE;
/* Ignore other sr bits. */
223
}
224
/*---------------------------------------------------------------------------*/
225
/*
226
* Restore previous interrupt mask.
227
*/
228
/* void */
229
/* splx_(int sr) */
230
/* { */
231
/* #ifdef __IAR_SYSTEMS_ICC__ */
232
/* __bis_SR_register(sr); */
233
/* #else */
234
/* /\* If GIE was set, restore it. *\/ */
235
/* asmv("bis %0, r2" : : "r" (sr)); */
236
/* #endif */
237
/* } */
238
/*---------------------------------------------------------------------------*/
239
#ifdef __IAR_SYSTEMS_ICC__
240
int
241
__low_level_init(
void
)
242
{
243
/* turn off watchdog so that C-init will run */
244
WDTCTL = WDTPW + WDTHOLD;
245
/*
246
* Return value:
247
*
248
* 1 - Perform data segment initialization.
249
* 0 - Skip data segment initialization.
250
*/
251
return
1;
252
}
253
#endif
254
/*---------------------------------------------------------------------------*/
255
void
256
msp430_sync_dco
(
void
)
257
{
258
uint16_t oldcapture;
259
int16_t diff;
260
/* DELTA_2 assumes an ACLK of 32768 Hz */
261
#define DELTA_2 ((MSP430_CPU_SPEED) / 32768)
262
263
/* Select SMCLK clock, and capture on ACLK for TBCCR6 */
264
TBCTL = TBSSEL1 | TBCLR;
265
TBCCTL6 = CCIS0 + CM0 + CAP;
266
/* start the timer */
267
TBCTL |= MC1;
268
269
while
(1) {
270
/* wait for the next capture */
271
TBCCTL6 &= ~CCIFG;
272
while
(!(TBCCTL6 & CCIFG));
273
oldcapture = TBCCR6;
274
275
/* wait for the next capture - and calculate difference */
276
TBCCTL6 &= ~CCIFG;
277
while
(!(TBCCTL6 & CCIFG));
278
diff = TBCCR6 - oldcapture;
279
280
/* resynchronize the DCO speed if not at target */
281
if
(DELTA_2 == diff) {
282
break
;
/* if equal, leave "while(1)" */
283
}
else
if
(DELTA_2 < diff) {
/* DCO is too fast, slow it down */
284
DCOCTL--;
285
if
(DCOCTL == 0xFF) {
/* Did DCO roll under? */
286
BCSCTL1--;
287
}
288
}
else
{
/* -> Select next lower RSEL */
289
DCOCTL++;
290
if
(DCOCTL == 0x00) {
/* Did DCO roll over? */
291
BCSCTL1++;
292
}
293
/* -> Select next higher RSEL */
294
}
295
}
296
297
/* Stop the timer - conserves energy according to user guide */
298
TBCTL = 0;
299
}
300
/*---------------------------------------------------------------------------*/
value
static int value(int type)
Definition
cc2538-temp-sensor.c:49
watchdog_init
void watchdog_init(void)
Initialisation function for the WDT.
Definition
watchdog.c:63
msp430_init_dco
static void msp430_init_dco(void)
Initialize the Clock System (CS) module.
Definition
msp430.c:60
init_ports
static void init_ports(void)
Initialize all ports to output low to reduce power consumption.
Definition
msp430.c:124
splhigh_
int splhigh_(void)
Mask all interrupts that can be masked.
Definition
msp430.c:166
msp430_sync_dco
void msp430_sync_dco(void)
Synchronize DCO (no-op for FR5969, DCO is automatically calibrated).
Definition
msp430.c:157
arch
cpu
msp430
f2xxx
msp430.c
Generated on
for Contiki-NG by
1.17.0