This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

The XT1 Problem in CC430F6137



Hello,
I install a 32KHz crystal on EM430F6137RF900 board, and set it as the source of ACLK.
I test the output frequency from Port2-0. I find that the output signal is always come
from the internal RC oscillator and can not be get from XT1, even the XT1 is working well.
I guess there is a problem in the chip design. Who knows that how to get the XT1 output.

Following is the code for test. To change i=3, the output should be from XT1, but the
output frequency is not changed. In my test, the internal RC oscillator output is 34KHz.

Thanks.

Zhifen


//*****************************************************************************
// Main Routine
//*****************************************************************************
#include "cc430x613x.h"

void main( void )
{
 unsigned int i = 1;  // i can be set to 1 or 3.

 WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset

 PMAPPWD = 0x02D52;   // Get write-access to port mapping regs 
 P2MAP0 = PM_ACLK;   // Map ACLK output to P2.0
 PMAPPWD = 0;    // Lock port mapping registers 

 P2DIR |= BIT0;    // enable output
 P2SEL |= BIT0;    // ACK output. 32K

 if(i == 3)
 {
  P5SEL = 0x03;     // Port select XT1
  UCSCTL6 = XT2OFF | XCAP_3;
  do {
   UCSCTL7 &= ~XT1LFOFFG;  // Clear fault flags
  } while (UCSCTL7 & XT1LFOFFG); // Test oscillator fault flag
 }

 while(i)
  __no_operation();
}

  • Hello,

    I install a 32KHz crystal on EM430F6137RF900 board, and set it as the souce of ACLK.

    I test the output frequency from Port2-0. I found that the frequency is always same as the

    internal RC oscillator. I guess it is a bug in the chip.

    Can somebody help me.

    Thanks.

    Zhifen

    Following is the code for testing.

    #include "cc430x613x.h"

    //*****************************************************************************
    // Main Routine
    //*****************************************************************************
    void main( void )
    {
      unsigned int i = 3; // i can be set to 1 or 3.

      WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset

      PMAPPWD = 0x02D52; // Get write-access to port mapping regs
      P2MAP0 = PM_ACLK; // Map ACLK output to P2.0
      PMAPPWD = 0; // Lock port mapping registers

      P2DIR |= BIT0; // enable output
      P2SEL |= BIT0; // ACK output. 32K

      if(i == 3)
      {
        P5SEL = 0x03; // Port select XT1
        UCSCTL6 = XT2OFF | XCAP_3;
        do {
          UCSCTL7 &= ~XT1LFOFFG; // Clear fault flags
        } while (UCSCTL7 & XT1LFOFFG); // Test oscillator fault flag
      }

      while(i)
        __no_operation();
    }

     

  • The first thing that catches my eye is the wait loop. After clearing XT1LFOFFG, it wills tay off for some time. Obviously, since if the crystal runs with 32kHz, it will only produce a clock trick every 32 microseconds. And the detection whether the crystral is running must wait at least this time to determine whether the crystal is there or not. The datasheet lists the minimum frequency to be >10kHz worst case, the the detection time is >100microseconds. But your code will check again within nanoseconds and so the flag will always be clear at the first run. With the crystal not running at all.

    After clearing XT1OFFIFG, you'll need to make a delay that is at least as long as the longest possible deteection time, based on the datasheet. (100 microseconds is the shortest). On the 5438, it is 100 milli(!)seconds (worst case, 10 Hz will be enough to not cause a fault). On the 6137 it won't be too different.
    So you need a delay. And please don't use a for-loop. It's not reliable, depends on compiler optimization and will probably not work at all (even if TI used it in their examples from teh MSP stone-age and continues copying it into newer projects)

    There are several threads dealing with simple timer-based delays. As a quickhack (which still is MCLOCK dependent) you can use __delay_cycles() from intrinsics.h to wait for a given number of processor cycles.

  • Try clearing the OFIFG flag in SFRIFG1 after the XT1LFOFFG flag finally stays clear.

    Jeff

  • Jeff,

    After clear the OFIFG, I get the XT1 output. Thanks a lot.

    Have a good weekend.

    Zhifen

  • Looks like my post from Friday somwhow was swallowed...

    Zhifen said:
     do {
       UCSCTL7 &= ~XT1LFOFFG;  // Clear fault flags
      } while (UCSCTL7 & XT1LFOFFG); // Test oscillator fault flag

    This is effectively a NOP.
    Why?
    Because the hardware that detects an oscillator fault requires some time to do so. Thr datasheet of the 5438 (and likely yours is not much different) lists a required frequency of 10Hz to 10kHz for not triggering the OFFG. This means that the OFFG hardware has at least 100µs timeout before the OFFG is set again after resetting it. Worst case can be 100ms.

    So between clearing the OFFG and testing it for staying clear, you'll have to wait 100ms (worst case), or else your while condition will be always true, even with no quartz attached.

    Anyway, clearing the OFIFG bit is also necessary as this bit is not reset and while it is set, it will automatically switch ACLK from LFXT1 (but only in LF mode) to a backup clock (VLO, REFO, depends on the MSP)

  • Jens-Michael Gross said:

    Looks like my post from Friday somwhow was swallowed...

    no, it's still there, not swallowed. Zhifen created two threads posing the same question. They're now merged into one.

    Regards,

    Dung

  • Jens-Michael Gross said:

    ... So between clearing the OFFG and testing it for staying clear, you'll have to wait 100ms (worst case), or else your while condition will be always true, even with no quartz attached. ...

    I don't think that's right.  The fault-detection circuitry doesn't let software clear the OFFG until the circuitry is satisfied.  The Users Guide refers to an internal signal called XT1_LF_OscFault with the following description: 

    "This signal is set after the XT1 (LF mode) oscillator has stopped and cleared after operation resumes. The fault condition causes XT1LFOFFG to
    be set and remain set. If the user clears XT1LFOFFG and the fault condition still exists, XT1LFOFFG remains set."

    So code can clear the flag and then immediately check to see if the clearing attempt was successful.  If it was successful, then the fault logic has already had enough time (maybe as much as 100ms as you suggest) to be satisfied with the oscillator.  Plus it has seen 8192 ticks with no fault condition.

    Jeff

     

  • The XT1LFOFFG bit in the UCSCTL7 is not the correct flag to clear and wait for. This bit is set and cleared by hardware. The statement:

    do {
       UCSCTL7 &= ~XT1LFOFFG;
      } while (UCSCTL7 & XT1LFOFFG);

    is useless even if you insert a delay after you clear it.

    do {
       UCSCTL7 &= ~XT1LFOFFG;  delay(xxx);
      } while (UCSCTL7 & XT1LFOFFG);


  • Jeff Tenney said:
    The fault-detection circuitry doesn't let software clear the OFFG until the circuitry is satisfied.  The Users Guide refers to an internal signal called XT1_LF_OscFault with the following description: 


    Internal signal and register bit are two different things, and so is their meaning and behaviour.

    The OFFG circuitry is basically a retriggerable monoflop. Or a watchdog, (re)triggered by the XT1 input. If no signal comes from the XT1 input for some time (and this time is pointed out in the datasheet), the watchdog will trigger/the monoflop will expire and the internal signal will flag the fault condition.

    Following your description, the signal will raise if a certain time has passed since the last pulse and fall when the next pulse comes (or remain low, if it was in time), which does not necessarily mean that this next pulse was in time or that the oscillator is really properly running. You can (assuming the fastest condition) apply a 5kHz clock signal to LFXT1 and see this internal signal fall for 100 microseconds, the raise for 100 microseconds, then fall again.

    While the signal is low, you can clear the LF1OFFG bit and be happy, and 100 microseconds it will pop up again and you won't notice.

    Also, since switching on the XT1 and/or resetting the MSP will likely cause a pulse and/or reset the monoflop, you have plenty of time in which the XT1OFFG bit can be successfully cleared even if there is no crystal attached at all.

    The passus you cite from your datasheet sounds different in mine (5438):

    "XT1 oscillator fault flag (LF mode). If this bit is set, the OFIFG flag is also set. XT1LFOFFG is set if a XT1 fault condition exists. XT1LFOFFG can be cleared via software. If the XT1 fault condition still remains, XT1LFOFFG is set."

  • Software can't clear XT1LFOFFG unless the internal counter is at 8192.  That requires 8192 XT1 ticks without the monoflop you're talking about ever indicating a fault condition (because that monoflop clears the counter).

    So the fault detection is based on the concepts you describe but there's a bit more circuitry before getting to XT1_LF_OscFault, and there's yet a little bit more before finally getting to the actual XT1LFOFFG bit.

    It's really a cool design.

  • Jeff Tenney said:
    Software can't clear XT1LFOFFG unless the internal counter is at 8192.

    You're right, I forgot about the counters. They are new in the 5x/6x series. Also, their only appearance is in this note, nowhere else. So it's easy to miss it.

    So right with these counters, software can only clear the OFFG after 8192 crystal ticks have arrived without a significant delay between. This covers the wait time for stable quartz operation and eliminates the need for a delay loop (after 8192 ticks without fault, the crystal can be considered stable).

    It introduces, however, a different problem: 8192 ticks of a 32kHz clock are 1/4s. Plus the real quartz startup time, it can easily be a delay of 1/2 s or more in this loop. A minor eternity for an embedded system.
    Also, the WDT is initially sourced by DCOCLKDIV, which is 500kHz (DCOCLKDIV, once adjusted by the FLL), with a 32k counter. This means the WDT will expire after 65ms. It is necessary to either disable the WDT (which I don't recommend for embedded applications), trigger it inside the waiting loop (which I also do not recommend, as it renders it useless) or reporgram it for a longer delay than expected startup time.

    Jeff Tenney said:
    It's really a cool design.

    Indeed it is, if you can collect all pieces of information together from the docs. Yet I'm not that happy with the default values for the fault counters. 8192 is way too much for both, LF mode and bypass mode, while 1024 is quite low for an HF quartz. It would be better the opposite way, since external clock sources are usually stable or not, so 1024 is enough, for an LF quartz 8192 is way too much while an HF crystal easily swings for some microseconds (especially if it is a 16MHz quartz or even higher) and then ceases again.

    Anyway, the counters eliminate the need for a waiting loop, which is usually done by a for loop (even by TI itself in their examples) which might get optimized away and even if not, highly depends on the current clock speed.

    So back to the original topic, for the 5x/6x series, the loop in the OPs code is okay as it is but will take a longer time to execute, but to enable the LFXT1 as ACLK source, OFIFG needs to be cleared too, or else the ACLK will be sourced by REFO fallback.

  • Jens-Michael Gross said:

    So back to the original topic, for the 5x/6x series, the loop in the OPs code is okay as it is but will take a longer time to execute, but to enable the LFXT1 as ACLK source, OFIFG needs to be cleared too, or else the ACLK will be sourced by REFO fallback.

    We have published a code library to configure & operate core peripherals of the 5xx/6xx devices. The updated code looks OK but I'd still recommend checking out & abiding by the functions in the code library.

    Regards,

    Dung

     

  • I usually refrain from using a library for several reasons.

    First, you don't know what it does and what side-effects it might have.
    Then it keeps you from understanding what you're dealing with (Why do we need power plants? We get our power from the wall outlet!)
    Also, using library functions often adds unnecessary overhead which can be deadly to time-critical situations (Well, at startup it usually isn't). Or space-critical.
    And finally there are the license issues. Maybe unimportant for any hobby-project but a problem for anything that will go into mass-production.

    If it is a source code library, it's better - as long as it's well documented. (Which most of the application notes' codes aren't). You can see what it does and pull the required code into your own project. Or learn and do it yourself. There's still the license issue. And as I feared, in the mentioned code library, the license notice in the files is often (much) longer than the contained code.

    It's a good reference for own code anyway.

  • Jens-Michael,

    the intention of these code libraries is to help users quickly understand the new modules and how to properly configure those modules and get the system up and running. Specifically the 5xx/6xx family devices introduce several new and complex modules including the PMM, UCS, Port Map, SYS, etc. These delicate modules are critical to the operation of the 430, and require good understanding to use correctly. Along with the ultimate source of info, the User's Guide, providing this particular library code examples is to help developers get to this level quicker. In other words, the code library is to help better understand the User's Guide, not to bypass the most important step altogether.

    License point aside, feel free to use the library for your MSP430 projects as is, or simply use them as guideline to develop your own code.

    Regards,

    Dung

**Attention** This is a public forum