Blame view

RIOT/boards/msb-430-common/board_init.c 6.17 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  /*
   * Copyright (C) 2014 INRIA
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @ingroup boards
   * @{
   */
  
  /**
   * @file
   * @brief       msb-430 common board initialization
   *
   * @author      Oliver Hahm <oliver.hahm@inria.fr>
   * @author      Kaspar Schleiser <kaspar@schleiser.de>
   *
   */
  
  #include "cpu.h"
  #include "irq.h"
  #include "board.h"
  #include "uart_stdio.h"
  #include "periph_conf.h"
  #include "msp430.h"
  #include "debug.h"
  
  static volatile uint32_t __msp430_cpu_speed = MSP430_INITIAL_CPU_SPEED;
  
  void msp430_init_dco(void);
  
  static void msb_ports_init(void)
  {
      /* Port 1: Free port, for energy saving all outputs are set to zero. */
      P1SEL = 0x00;   /* Port1 I/O Function */
      P1OUT = 0x00;   /* Port1 Output register: 00000000 = 0x00 */
      P1DIR = 0xFF;   /* Port1 Direction: 11111111 = 0xFF */
  
      P2SEL = 0x20;   /* Port2 I/O Function */
      P2OUT = 0x00;   /* Port2 Output register: 00000000 = 0x00 */
      P2DIR = 0x1C;   /* Port2 Direction: 00011010 = 0x1C */
      /*   0 - P2.0 [IN ] - */
      /*   0 - P2.1 [OUT] - */
      /*   1 - P2.2 [IN ] - */
      /*   1 - P2.3 [OUT] - */
      /*   1 - P2.4 [OUT] - */
      /*   0 - P2.5 [IN ] - */
      /*   0 - P2.6 [IN ] - SDC Protect */
      /*   0 - P2.7 [IN ] - SDC Detect */
  
      P3SEL = 0x00;   /* Port3 Pins 6 & 7 for USART */
      P3OUT = 0x00;   /* Port3 Output register: 01001001: 0x49 */
      P3DIR = 0xFF;   /* Port3 Direction: 10101011: 0xAB */
      /*   1 - P3.0 */
      /*   1 - P3.1 */
      /*   0 - P3.2 */
      /*   1 - P3.3 */
      /*   0 - P3.4 [IN ] - SHT 11 DATA (OUT/IN) */
      /*   1 - P3.5 [OUT] - SHT 11 CLK */
      /*   0 - P3.6 [2-Funktion] - RS232_RxD */
      /*   1 - P3.7 [2-Funktion] - RS232_TxD */
  
      /* Port 4: Free port, for energy saving all outputs are set to zero. */
      P4SEL = 0x00;   /* Port4 I/O Function */
      P4OUT = 0x00;   /* Port4 Output register: 00000000 = 0x00 */
      P4DIR = 0xFF;   /* Port4 Direction: 11111111 = 0xFF */
      /*   1 - P4.0 [OUT] - unused */
      /*   1 - P4.1 [OUT] - unused */
      /*   1 - P4.2 [OUT] - unused */
      /*   1 - P4.3 [OUT] - unused */
      /*   1 - P4.4 [OUT] - unused */
      /*   1 - P4.5 [OUT] - unused */
      /*   1 - P4.6 [OUT] - unused */
      /*   1 - P4.7 [OUT] - unused */
  
      P5SEL = 0x00;   /* Port5 I/O Function: 00000000 = 0x00 */
      P5OUT = 0x80;   /* Port5 Output register: 00001001 = 0x09 */
      P5DIR = 0xFF;   /* Port5 Direction: 11111011 = 0xFB */
      /*   1 - P5.0 [OUT] - SDC /CS */
      /*   1 - P5.1 [OUT] - SDC DI */
      /*   0 - P5.2 [IN ] - SDC DO */
      /*   1 - P5.3 [OUT] - SDC DCLK */
      /*   1 - P5.4 [OUT] - MMA GS1 */
      /*   1 - P5.5 [OUT] - MMA GS2 */
      /*   1 - P5.6 [OUT] - MMA /SLEEP */
      /*   1 - P5.7 [OUT] - LED_RED 0-on, 1-off */
  
      P6SEL = 0x00;   /* Port6 I/O Function = 0x07 */
      P6OUT = 0x00;   /* Port6 Output register: 00000000 = 0x00 */
      P6DIR = 0xFF;   /* Port6 Direction: 11111000 = 0xF8 */
      /*   0 - P6.0 [AD-IN] - MMA X-Axis */
      /*   0 - P6.1 [AD-IN] - MMA Y-Axis */
      /*   0 - P6.2 [AD-IN] - MMA Z-Axis */
      /*   1 - P6.3 [OUT] - unused */
      /*   1 - P6.4 [OUT] - unused */
      /*   1 - P6.5 [OUT] - unused */
      /*   1 - P6.6 [OUT] - unused */
      /*   1 - P6.7 [OUT] - unused */
  }
  
  void msp430_set_cpu_speed(uint32_t speed)
  {
      irq_disable();
      __msp430_cpu_speed = speed;
      msp430_init_dco();
      irq_enable();
  }
  
  /*---------------------------------------------------------------------------*/
  void msp430_init_dco(void)
  {
  #if MSP430_HAS_EXTERNAL_CRYSTAL
      /*------------------ use external oszillator -----------------------*/
      uint16_t i;
  
      /* Stop watchdog */
      WDTCTL = WDTPW + WDTHOLD;
  
      //Init crystal for mclk
      //XT2 = HF XTAL
      BCSCTL1 = RSEL2;
  
      /* Wait for xtal to stabilize */
      do {
          IFG1 &= ~OFIFG;             /* Clear oscillator fault flag */
  
          for (i = 0xFF; i > 0; i--); /* Time for flag to set */
      }
      while ((IFG1 & OFIFG) != 0);    /* Oscillator fault flag still set? */
  
      BCSCTL2 = SELM_2 + SELS;        /* MCLK und SMCLK = XT2 (safe) */
  #else
      int delta = __msp430_cpu_speed >> 12;
      unsigned int oldcapture = 0;
      unsigned int i;
  
      BCSCTL1 = 0xa4; /* ACLK is devided by 4. RSEL=6 no division for MCLK
               and SSMCLK. XT2 is off. */
  
      /* Init FLL to desired frequency using the 32762Hz crystal */
  #if MSP430_HAS_DCOR
      BCSCTL2 = 0x01;
  #else
      BCSCTL2 = 0x00;
  #endif
  
      WDTCTL = WDTPW + WDTHOLD;             /* Stop WDT */
      BCSCTL1 |= DIVA1 + DIVA0;             /* ACLK = LFXT1CLK/8 */
  
      for (i = 0xffff; i > 0; i--);         /* Delay for XTAL to settle */
  
      CCTL2 = CCIS0 + CM0 + CAP;            /* Define CCR2, CAP, ACLK */
      TACTL = TASSEL1 + TACLR + MC1;        /* SMCLK, continous mode */
  
  
      while (1) {
          unsigned int compare;
  
          while ((CCTL2 & CCIFG) != CCIFG);   /* Wait until capture occured! */
  
          CCTL2 &= ~CCIFG;                    /* Capture occured, clear flag */
          compare = CCR2;                     /* Get current captured SMCLK */
          compare = compare - oldcapture;     /* SMCLK difference */
          oldcapture = CCR2;                  /* Save current captured SMCLK */
  
          if (delta == compare) {
              break;                            /* if equal, leave "while(1)" */
          }
          else if (delta < compare) {         /* DCO is too fast, slow it down */
              DCOCTL--;
  
              if (DCOCTL == 0xFF) {             /* Did DCO role under? */
                  BCSCTL1--;
              }
          }
          else {                              /* -> Select next lower RSEL */
              DCOCTL++;
  
              if (DCOCTL == 0x00) {             /* Did DCO role over? */
                  BCSCTL1++;
              }
  
              /* -> Select next higher RSEL  */
          }
      }
  
      CCTL2 = 0;                            /* Stop CCR2 function */
      TACTL = 0;                            /* Stop Timer_A */
  
      BCSCTL1 &= ~(DIVA1 + DIVA0);          /* remove /8 divisor from ACLK again */
  #endif
  }
  
  void board_init(void)
  {
      msp430_cpu_init();
      msb_ports_init();
  
      msp430_set_cpu_speed(CLOCK_CORECLOCK);
  
      /* finally initialize STDIO over UART */
      uart_stdio_init();
  }