msp430x22x4_dco_flashcal.c


1
//******************************************************************************
2
//  MSP430F22x4 Demo - DCO Calibration Constants Programmer
3
//
4
//  NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION
5
//  CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL
6
//  CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED.
7
//
8
//  Description: This code re-programs the F2xx DCO calibration constants.
9
//  A software FLL mechanism is used to set the DCO based on an external
10
//  32kHz reference clock. After each calibration, the values from the
11
//  clock system are read out and stored in a temporary variable. The final
12
//  frequency the DCO is set to is 1MHz, and this frequency is also used
13
//  during Flash programming of the constants. The program end is indicated
14
//  by the blinking LED.
15
//  ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
16
//  //* External watch crystal installed on XIN XOUT is required for ACLK *//
17
//
18
//           MSP430F22x4
19
//         ---------------
20
//     /|\|            XIN|-
21
//      | |               | 32kHz
22
//      --|RST        XOUT|-
23
//        |               |
24
//        |           P1.0|--> LED
25
//        |           P2.1|--> SMLCK = target DCO
26
//
27
//  A. Dannenberg
28
//  Texas Instruments Inc.
29
//  April 2006
30
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
31
//******************************************************************************
32
#include "msp430x22x4.h"
33
34
#define DELTA_1MHZ    244                   // 244 x 4096Hz = 999.4Hz
35
#define DELTA_8MHZ    1953                  // 1953 x 4096Hz = 7.99MHz
36
#define DELTA_12MHZ   2930                  // 2930 x 4096Hz = 12.00MHz
37
#define DELTA_16MHZ   3906                  // 3906 x 4096Hz = 15.99MHz
38
39
unsigned char CAL_DATA[8];                  // Temp. storage for constants
40
volatile unsigned int i;
41
int j;
42
char *Flash_ptrA;                           // Segment A pointer
43
void Set_DCO(unsigned int Delta);
44
45
void main(void)
46
{
47
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
48
  for (i = 0; i < 0xfffe; i++);             // Delay for XTAL stabilization
49
  P1OUT = 0x00;                             // Clear P1 output latches
50
  P1DIR = 0x01;                             // P1.0 output
51
  P2SEL |= 0x02;                            // P2.1 SMCLK output
52
  P2DIR |= 0x02;                            // P2.1 output
53
54
  j = 0;                                    // Reset pointer
55
56
  Set_DCO(DELTA_16MHZ);                     // Set DCO and obtain constants
57
  CAL_DATA[j++] = DCOCTL;
58
  CAL_DATA[j++] = BCSCTL1;
59
60
  Set_DCO(DELTA_12MHZ);                     // Set DCO and obtain constants
61
  CAL_DATA[j++] = DCOCTL;
62
  CAL_DATA[j++] = BCSCTL1;
63
64
  Set_DCO(DELTA_8MHZ);                      // Set DCO and obtain constants
65
  CAL_DATA[j++] = DCOCTL;
66
  CAL_DATA[j++] = BCSCTL1;
67
68
  Set_DCO(DELTA_1MHZ);                      // Set DCO and obtain constants
69
  CAL_DATA[j++] = DCOCTL;
70
  CAL_DATA[j++] = BCSCTL1;
71
72
  Flash_ptrA = (char *)0x10C0;              // Point to beginning of seg A
73
  FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator
74
  FCTL1 = FWKEY + ERASE;                    // Set Erase bit
75
  FCTL3 = FWKEY + LOCKA;                    // Clear LOCK & LOCKA bits
76
  *Flash_ptrA = 0x00;                       // Dummy write to erase Flash seg A
77
  FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
78
  Flash_ptrA = (char *)0x10F8;              // Point to beginning of cal consts
79
  for (j = 0; j < 8; j++)
80
    *Flash_ptrA++ = CAL_DATA[j];            // re-flash DCO calibration data
81
  FCTL1 = FWKEY;                            // Clear WRT bit
82
  FCTL3 = FWKEY + LOCKA + LOCK;             // Set LOCK & LOCKA bit
83
84
  while (1)
85
  {
86
    P1OUT ^= 0x01;                          // Toggle LED
87
    for (i = 0; i < 0x4000; i++);           // SW Delay
88
  }
89
}
90
91
void Set_DCO(unsigned int Delta)            // Set DCO to selected frequency
92
{
93
  unsigned int Compare, Oldcapture = 0;
94
95
  BCSCTL1 |= DIVA_3;                        // ACLK = LFXT1CLK/8
96
  TACCTL2 = CM_1 + CCIS_1 + CAP;            // CAP, ACLK
97
  TACTL = TASSEL_2 + MC_2 + TACLR;          // SMCLK, cont-mode, clear
98
99
  while (1)
100
  {
101
    while (!(CCIFG & TACCTL2));             // Wait until capture occured
102
    TACCTL2 &= ~CCIFG;                      // Capture occured, clear flag
103
    Compare = TACCR2;                       // Get current captured SMCLK
104
    Compare = Compare - Oldcapture;         // SMCLK difference
105
    Oldcapture = TACCR2;                    // Save current captured SMCLK
106
107
    if (Delta == Compare)
108
      break;                                // If equal, leave "while(1)"
109
    else if (Delta < Compare)
110
    {
111
      DCOCTL--;                             // DCO is too fast, slow it down
112
      if (DCOCTL == 0xFF)                   // Did DCO roll under?
113
        if (BCSCTL1 & 0x0f)
114
          BCSCTL1--;                        // Select lower RSEL
115
    }
116
    else
117
    {
118
      DCOCTL++;                             // DCO is too slow, speed it up
119
      if (DCOCTL == 0x00)                   // Did DCO roll over?
120
        if ((BCSCTL1 & 0x0f) != 0x0f)
121
          BCSCTL1++;                        // Sel higher RSEL
122
    }
123
  }
124
  TACCTL2 = 0;                              // Stop TACCR2
125
  TACTL = 0;                                // Stop Timer_A
126
  BCSCTL1 &= ~DIVA_3;                       // ACLK = LFXT1CLK
127
}