Jump to content
43oh

Flashing the missing DCO calibration constants


Recommended Posts

  • 1 month later...
  • Replies 45
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

EDIT: Here's another really nice DCO calibration program. It's part of TinyOS-msp430. http://code.google.com/p/tinyos-msp430/ It's the file called calibrate-dco. As gordon, who discovered it said,

Hi Guys,   I wanted to tack on my calibration code that I successfully used to calibrate my G2231 device.   It's almost exactly like naturetm's code. The only difference is the setDCO() function h

IMHO it's not good idea, erase full segment A. There is probably stored more device-depended constants, not only DCO calibration. (Look at page 644 in slau144.pdf - "SegmentA structure"). Better idea

Hi, guys!

I realize I'm bringing up an old thread, but I just wanted to say that after seeing this,

/************************************************************
* Calibration Data in Info Mem
************************************************************/
CALDCO_16MHZ       = 0x10F8;
CALBC1_16MHZ       = 0x10F9;
CALDCO_12MHZ       = 0x10FA;
CALBC1_12MHZ       = 0x10FB;
CALDCO_8MHZ        = 0x10FC;
CALBC1_8MHZ        = 0x10FD;
CALDCO_1MHZ        = 0x10FE;
CALBC1_1MHZ        = 0x10FF;

I combined it with this in my IAR Kickstart msp430g2231_mod.h,

/************************************************************
* Calibration Data in Info Mem
************************************************************/

#ifndef __DisableCalData

#define CALDCO_1MHZ_          (0x10FEu)  /* DCOCTL  Calibration Data for 1MHz */
READ_ONLY DEFC( CALDCO_1MHZ      , CALDCO_1MHZ_)
#define CALBC1_1MHZ_          (0x10FFu)  /* BCSCTL1 Calibration Data for 1MHz */
READ_ONLY DEFC( CALBC1_1MHZ      , CALBC1_1MHZ_)

#endif /* #ifndef __DisableCalData */

 

to get this,

 

/************************************************************
* Calibration Data in Info Mem
************************************************************/

#ifndef __DisableCalData

#define CALDCO_16MHZ_          (0x10F8u)  /* DCOCTL  Calibration Data for 16MHz */
READ_ONLY DEFC( CALDCO_16MHZ      , CALDCO_16MHZ_)
#define CALBC1_16MHZ_          (0x10F9u)  /* BCSCTL1 Calibration Data for 16MHz */
READ_ONLY DEFC( CALBC1_16MHZ      , CALBC1_16MHZ_)
#define CALDCO_12MHZ_          (0x10FAu)  /* DCOCTL  Calibration Data for 12MHz */
READ_ONLY DEFC( CALDCO_12MHZ      , CALDCO_12MHZ_)
#define CALBC1_12MHZ_          (0x10FBu)  /* BCSCTL1 Calibration Data for 12MHz */
READ_ONLY DEFC( CALBC1_12MHZ      , CALBC1_12MHZ_)
#define CALDCO_8MHZ_          (0x10FCu)  /* DCOCTL  Calibration Data for 8MHz */
READ_ONLY DEFC( CALDCO_8MHZ      , CALDCO_8MHZ_)
#define CALBC1_8MHZ_          (0x10FDu)  /* BCSCTL1 Calibration Data for 8MHz */
READ_ONLY DEFC( CALBC1_8MHZ      , CALBC1_8MHZ_)
#define CALDCO_1MHZ_          (0x10FEu)  /* DCOCTL  Calibration Data for 1MHz */
READ_ONLY DEFC( CALDCO_1MHZ      , CALDCO_1MHZ_)
#define CALBC1_1MHZ_          (0x10FFu)  /* BCSCTL1 Calibration Data for 1MHz */
READ_ONLY DEFC( CALBC1_1MHZ      , CALBC1_1MHZ_)
#endif /* #ifndef __DisableCalData */

 

and used it this way,

       BCSCTL1 = CALBC1_16MHZ;
       DCOCTL = CALDCO_16MHZ;

 

I tested it on a program built for 1 Mhz, with LCDs that display messages, a set delay between messages, it was MUCH faster.

 

Please correct me if I'm wrong about anything.

Link to post
Share on other sites
  • 1 month later...

I would like to thank NatureTM for this topic and say that if someone afraid to apply this method, then there is no reason. Official TI page offers code samples for MSP430G2xx1 that includes file msp430x20xx_dco_flashcal.c which almost identical with the file on the second page of this topic, written by zeke and needs no DCO library, so this is at least semi-official method :thumbup:

Link to post
Share on other sites
  • 4 weeks later...

Quick question on the calculate_chksum() routine:

 

unsigned int calculate_chksum(void)
{
   unsigned char i;
   unsigned int sum=0;

   for(i=0;i        sum = CAL_DATA[i];

return sum;
}

 

Shouldn't line 160 be

sum ^= CAL_DATA[i]

or am I completely misunderstanding the point of a chksum?

 

EDIT: Not +=, changed to ^=. slau144 says the chksum is an XOR operation. chksum should be the two's complement of the cumulative XOR of the remaining words in the segment.

Link to post
Share on other sites
  • 1 month later...

For anyone who is interested, I've completed the (3) tutorials on my blog about calibrating the DCO and writing to flash. I've done it in Segment B instead of Segment A and for a non-standard DCO of 7.3728 MHz (for UART). It also includes some information on the TLV formatting TI uses and the correct way to deal with the checksum.

 

Hope these are helpful!

Link to post
Share on other sites
  • 2 months later...

I have a question about the DCO calibration constants.

 

Do these calibration constants have any real calibration for the DCO so you are sure it's close to, say, 16 MHz or are they simply commands that allow you to select different speeds?

 

I ask because I was playing with a 2131 at my desk(I like the little bugger I don't know why) and Grace plugin for CCS with a blink program and while it would only let me pick 1MHz from the clock speed dropdown, I was able to manually type in 16MHz and my __delay_cycles(1000000) command had to be changed to 16M to function the same.

 

Is this essentially writing the commands that you guys are trying to write to get past the 1MHz default programmed into the lower end chips?(I've noticed that the higher-end G series has 1,4?,12,16 available from dropdown).

Link to post
Share on other sites
  • 7 months later...

Kyle,

 

The calibration constants should give you more exactly the specified frequency, as long as the temperature and voltage values are near where they were when the calibration happened. The idea we've been getting at in this thread is putting the standard 1, 8, 12, and 16 MHz calibrations into the value line devices (or correcting those values for specific operating conditions). The example I did on my blog did a calibration for a custom frequency, and you can use the method to get any frequency you like within the operating range of the DCO.

Link to post
Share on other sites

You can use info segments B, C and D for whatever you want - the factory cal uses only segment A.

 

There is always at least one clock calibration. There can also be temperature sensor and ADC calibration in some chips. The calibration data allows for compensation of device variation. See section 24 of slau144 for more info.

 

Related: Using temperature calibration, comprehensive DCO calibration (uses segments B, C and D) and TLV parse and display

Link to post
Share on other sites
  • 2 months later...
  • 8 months later...

Hi Guys,

 

I wanted to tack on my calibration code that I successfully used to calibrate my G2231 device.

 

It's almost exactly like naturetm's code. The only difference is the setDCO() function has a little more fine tuning in it.

 

Take a look and notice that the setDCO() function is slightly different. I stole the idea from a post aBUGSworstnightmare made on the ti.com website. Here's the link.

 

//******************************************************************************
//  MSP430F20xx Demo - DCO Calibration Constants Programmer
//
//  NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION
//  CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL
//  CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED.
//
//  Description: This code re-programs the F2xx DCO calibration constants.
//  A software FLL mechanism is used to set the DCO based on an external
//  32kHz reference clock. After each calibration, the values from the
//  clock system are read out and stored in a temporary variable. The final
//  frequency the DCO is set to is 1MHz, and this frequency is also used
//  during Flash programming of the constants. The program end is indicated
//  by the blinking LED.
//  ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
//  //* External watch crystal installed on XIN XOUT is required for ACLK *//
//
//           MSP430F20xx
//         ---------------
//     /|\|            XIN|-
//      | |               | 32kHz
//      --|RST        XOUT|-
//        |               |
//        |           P1.0|--> LED
//        |           P1.4|--> SMLCK = target DCO
//
//  A. Dannenberg
//  Texas Instruments Inc.
//  May 2007
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************
//#include "msp430x20x1.h" // do not forget to change this according to the device you're using
#include <msp430g2231.h>

#define DELTA_1MHZ    244                   // 244 x 4096Hz = 999.4Hz
#define DELTA_8MHZ    1953                  // 1953 x 4096Hz = 7.99MHz
#define DELTA_12MHZ   2930                  // 2930 x 4096Hz = 12.00MHz
#define DELTA_16MHZ   3906                  // 3906 x 4096Hz = 15.99MHz

unsigned char CAL_DATA[8];                  // Temp. storage for constants
volatile unsigned int i;
int j;
char *Flash_ptrA;                           // Segment A pointer
void Set_DCO(unsigned int Delta);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  
  BCSCTL3 |= XCAP_3; // Launchpad watch crystals need ~12.5 pF
  
  for (i = 0; i < 0xfffe; i++);             // Delay for XTAL stabilization
  P1OUT = 0x00;                             // Clear P1 output latches
  P1SEL = 0x10;                             // P1.4 SMCLK output
  P1DIR = 0x11;                             // P1.0,4 output

  j = 0;                                    // Reset pointer

  Set_DCO(DELTA_16MHZ);                     // Set DCO and obtain constants
  CAL_DATA[j++] = DCOCTL;
  CAL_DATA[j++] = BCSCTL1;

  Set_DCO(DELTA_12MHZ);                     // Set DCO and obtain constants
  CAL_DATA[j++] = DCOCTL;
  CAL_DATA[j++] = BCSCTL1;

  Set_DCO(DELTA_8MHZ);                      // Set DCO and obtain constants
  CAL_DATA[j++] = DCOCTL;
  CAL_DATA[j++] = BCSCTL1;

  Set_DCO(DELTA_1MHZ);                      // Set DCO and obtain constants
  CAL_DATA[j++] = DCOCTL;
  CAL_DATA[j++] = BCSCTL1;

  Flash_ptrA = (char *)0x10C0;              // Point to beginning of seg A
  FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator
  FCTL1 = FWKEY + ERASE;                    // Set Erase bit
  FCTL3 = FWKEY + LOCKA;                    // Clear LOCK & LOCKA bits
  *Flash_ptrA = 0x00;                       // Dummy write to erase Flash seg A
  FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
  Flash_ptrA = (char *)0x10F8;              // Point to beginning of cal consts
  for (j = 0; j < 8; j++)
    *Flash_ptrA++ = CAL_DATA[j];            // re-flash DCO calibration data
  FCTL1 = FWKEY;                            // Clear WRT bit
  FCTL3 = FWKEY + LOCKA + LOCK;             // Set LOCK & LOCKA bit

  while (1)
  {
    P1OUT ^= 0x01;                          // Toggle LED
    for (i = 0; i < 0x4000; i++);           // SW Delay
  }
}

void Set_DCO(unsigned int Delta)            // Set DCO to selected frequency
{
  unsigned int Compare, Oldcapture = 0;

  BCSCTL1 |= DIVA_3;                        // ACLK = LFXT1CLK/8
  TACCTL0 = CM_1 + CCIS_1 + CAP;            // CAP, ACLK
  TACTL = TASSEL_2 + MC_2 + TACLR;          // SMCLK, cont-mode, clear

  while (1)
  {
    while (!(CCIFG & TACCTL0));             // Wait until capture occured
    TACCTL0 &= ~CCIFG;                      // Capture occured, clear flag
    Compare = TACCR0;                       // Get current captured SMCLK
    Compare = Compare - Oldcapture;         // SMCLK difference
    Oldcapture = TACCR0;                    // Save current captured SMCLK

    if (Delta == Compare)
      break;                                // If equal, leave "while(1)"
    else if (Delta < Compare)
    {
      DCOCTL--;                             // DCO is too fast, slow it down
      if (DCOCTL == 0xFF)                   // Did DCO roll under?
        if (BCSCTL1 & 0x0f)
          BCSCTL1--;                        // Select lower RSEL
    }
    else
    {
      DCOCTL++;                             // DCO is too slow, speed it up
      if (DCOCTL == 0x00)                   // Did DCO roll over?
        if ((BCSCTL1 & 0x0f) != 0x0f)
          BCSCTL1++;                        // Sel higher RSEL
    }
  }
  TACCTL0 = 0;                              // Stop TACCR0
  TACTL = 0;                                // Stop Timer_A
  BCSCTL1 &= ~DIVA_3;                       // ACLK = LFXT1CLK
}
Concerning the mods that were made to the cmd file, I just threw them into the default files because I know that I'm going to forget to made the project edits that are suggested in the first post above.

 

Just calibrate the g2231 first then use the code after.

 

 

 

Dum question, but does this require the external crystal to be installed?

I'm having this issue (lost calibration info) on a board that has a surface mount MSP430.  Trying to repair the data on the MSP430 enough to get it running, but this doesn't seem to work (clock cal info still reads out as 0xff after it's done).

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...