Jump to content
Sign in to follow this  
russm

clocking as fast as possible

Recommended Posts

I'm toying with using an msp430 as an in-line protocol converter between a couple of busses, and am trying to confirm if it's even viable.

 

As a simple test, I'm using the code below to pass signals from inputs (P1.6, P1.7) to outputs (P1.4, P1.5) and it seems capable of relaying signal features down to a size of ~2.5us. Unfortunately, that's not fast enough for what I want - I need to handle features down to 0.5us or so. :(

 

Assuming I'm running MCLK at 16MHz, this means I'm needing ~40 clocks just to copy an input GPIO to an output GPIO with some trivial bit manipulation - I'm not sure if this is expected, or if I'm just not clocking the device correctly. Given what I'm doing in the loop I'd expect only ~10 clocks or so. From my reading of the SLAU144 Basic Clock Module chapter I think I'm running it as fast as I can, but aren't really sure how to confirm that. I believe I'm setting RSELx and DCOx to their maximum values, and MCLK to DCO with a divider of 1, but is this the right way to force the fastest MCLK possible?

 

#include 
#include 

void main(void)
{
 WDTCTL = WDTPW + WDTHOLD; // stop watchdog

 BCSCTL1 = RSEL0|RSEL1|RSEL2|RSEL3; // RSELx = 0xF = AS FAST AS POSSIBLE
 DCOCTL = DCO0|DCO1|DCO2; // DCOx = 0x7 = AS FAST AS POSSIBLE
 BCSCTL2 |= SELM_0 + DIVM_0; // MCLK = DCO, divider = 1

 P1DIR |= 0x30; // P1.4 and P1.5 are output
 P1DIR &= ~0xC0; // P1.6 and P1.7 are input

 while(1)
 {
   register unsigned char a, b;
   a = P1OUT; // current output values
   a &= ~0x30; // zero P1.4, P1.5
   b = P1IN; // current input values
   b &= 0xC0; // zero all but P1.6, P1.7
   P1OUT = a | (b >> 2);
 }
}

Share this post


Link to post
Share on other sites

Yes, this is the right way to force the fastest MCLK possible. The maximum frequency that you can set is circa 21MHz (SLAS694C page 23), but TI guarantees maximum operating frequency of 16MHz. Frequencies higher than 16MHz can be used, but it is not guaranteed.

Share this post


Link to post
Share on other sites
My suggestion would be flash the DCO calibration to the chip --> use the viewtopic.php?f=10&t=234 post

It looks like that is designed to give you a nicely calibrated clock against the 32KHz crystal, but I just want "AS FAST AS POSSIBLE THANKS"...

 

I've gone back and counted up the per-instruction cycles for the compiled source, and it's 22 clocks per loop, so that fits with what I was seeing. Oh well. I may be able to hand-code an inner loop that's fast enough by dumping a bunch of the compiler's "useful" extras (no, I don't actually care if carry was set). Not confident I can fit enough of the required smarts in the cycles that are available though. :(

 

(on preview)

 

The maximum frequency that you can set is circa 21MHz (SLAS694C page 23)

Hmmm, OK, I'll have to check that out. My timings were assuming the clock was running ~16MHz, but if I can push it that high (even if it's flaky) I might be in business. Cheers!

Share this post


Link to post
Share on other sites

If I were to try to see how fast I could get it to run, I'd use one of those DCO-setting functions from the calibration thread. I'd set the DCO, log that setting though serial, then perform some operations and test the result of the operations against an expected value. If they match, increment DCO and repeat.

Maybe changing the clocks so often might make sending serial too messy, however. I think you could work around it. For the test operation, I'd think multiplying two doubles would work. That should go through a bunch of different CPU opcodes since it's done in software. I'd also be looking to get the voltage as close to max spec as possible, and maybe even a little over just for kicks, as long as you don't mind burning up a chip or two. I'd probably be logging the temperature in the serial output as well then.

 

I'm not sure if my methodology is sound, so maybe someone has some better insight, but that's how I think I'd do it. Maybe this is too involved for what you're looking to do, but I'd be interested to see how fast the typical chip could reliably go. It would be a fun experiment.

 

Edit: FYI max Vspec is 4.1 for 2231

Share this post


Link to post
Share on other sites

Even if you could run the DCO faster, the port pins will slow you back down.

 

slas694e - page 19 states that the output frequency of the port pins is 16MHz at 3V.

 

There are other msp430's that have a higher port output frequency.

 

For example, SLAS655B - page 44 says that the F5438 can run its output port pins at a frequency of 25MHz.

 

And, if you configured it just right, you could run the DCO anywhere between 60MHz and 135MHz.

Share this post


Link to post
Share on other sites

When I say Use the DCO calibration, I meant to use that to get to fast as possible - calibrated against the 32k CLOCK

All you would do is change the value of the constant for the one you want to replace for example

I used the DCO flash calibration to make my msp430F2013 2MHz default by using the below code

 

//******************************************************************************
//           Custom DCO settings- based on TI code example
//
//  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.
//
//
//           MSP430F20xx
//         ---------------
//     /|\|            XIN|-
//      | |               | 32kHz
//      --|RST        XOUT|-
//        |               |
//        |           P1.0|--> LED
//        |           P1.4|--> SMLCK = target DCO
// Orignal Code By
//  A. Dannenberg
//  Texas Instruments Inc.
//  May 2007
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************

//******************************************************************************
/*Flash Custom DCO settings, This will replace The default 1MHz */
/* to use 
//Custom calibration
 BCSCTL1 = CALBC1_1MHZ;                    // Set range
 DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation
*/

//ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
//* External watch crystal installed on XIN XOUT is required for ACLK *//
//******************************************************************************
#include "msp430f2013.h"

#define DELTA_CUSTOM    489                   // 489 x 4096Hz = 2002944Hz or 2.02MHz
#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
 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
 BCSCTL3 = XCAP_3;                         // Set internal cap to 12.5 

 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_CUSTOM);                      // 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
}

 

if you use the code above and change the custom constant to higher then 3906 you should be able to get better then 16MHz

remember this will kill the 1MHz constant and replace it, but you can always change one of the other constants instead -

 

I think this is the best way to get to the fastest reliably working CLK speed, remember every chip is slightly different, so when you use the mod,dco,rsel bits the same settings maybe a slightly different speed for each chip.

Share this post


Link to post
Share on other sites
If I were to try to see how fast I could get it to run, I'd use one of those DCO-setting functions from the calibration thread.

Again, those are for calibrating the DCO against a 32kHz crystal if your exact timing is important. slau144

Share this post


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.

Sign in to follow this  

×
×
  • Create New...