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.

msp430f5419a - trying to set MSCLK to DCO

Other Parts Discussed in Thread: MSP430F5419A

Using CCSv5.1 with MSP430F5419a

I am trying to get SMCLK based on DCO. Instead always have SMCLK=MCLK=XT2

Please, help to find problem in follows code:

#include "msp430x54xA.h"

void main(void) {

        WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

        P11DIR = BIT1+BIT2;                       // P11.1-2 to output direction
        P11SEL |= BIT1+BIT2;                      // P11.1-2 to output SMCLK,MCLK
        P5SEL |= 0x0C;                            // Port select XT2

        UCSCTL6 &= ~XT2OFF;                       // Enable XT2
        UCSCTL3 |= SELREF_2;                      // FLLref = REFO
                                                    // Since LFXT1 is not used,
                                                    // sourcing FLL with LFXT1 can cause
                                                    // XT1OFFG flag to set
        UCSCTL4 |= SELA_2;                        // ACLK=REFO,SMCLK=DCO,MCLK=DCO

          // Loop until XT1,XT2 & DCO stabilizes
          do
          {
            UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
                                                    // Clear XT2,XT1,DCO fault flags
            SFRIFG1 &= ~OFIFG;                      // Clear fault flags
          }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

          UCSCTL6 &= ~XT2DRIVE0;     // Decrease XT2 Drive according to expected frequency
          UCSCTL4 &= ~SELS_7;
          UCSCTL4 |= SELM_5;               // SMCLK=MCLK=XT2

          while(1);                                 // Loop in place
}

  • So let's see what happens. UCSCTL4 is responsible for the clock source selection, its initial state is 0x0044, which is ACLK = XT1, SMCLK = DCODIV, MCLK = DCODIV.

    UCSCTL4 |= SELA_2; -> 0x0244 ->    ACLK = REFO, SMCLK = DCODIV, MCLK = DCODIV

    UCSCTL4 &= ~SELS_7; -> 0x0204 ->   ACLK = REFO, SMCLK = XT1, MCLK = DCODIV

    UCSCTL4 |= SELM_5; -> 0x0205 ->    ACLK = REFO, SMCLK = XT1, MCLK = XT2

     

    What I'm missing is the UCSCTL4 |= SELS_3; or UCSCTL4 |= SELS__DCOCLK;, I think the latter is better as it's showing more the intention of the programmer and someone without knowledge of the register knows that DCOCLK is selected.

  • Right, when i am changing to

    UCSCTL4 |= SELM_XT2CLK + SELS_DCOCLK;

    same result. Seeing on pin 11.2 same frequency as on pin 11.1

  • gxk said:
    UCSCTL4 |= SELM_XT2CLK + SELS_DCOCLK;

    This is indeed better readable. However, some things need to be taken into account:

    SELS_DCOCLK is an alias to SELS_0 which is 0. So SELS_DCOCLK will not se any bits in UCSCTL4. It does, however, not clear any bits too. So if a different SELS_x setting was set before, this won't be changed by an |= operation. Luckily, SELS_DCOCLK is the power-on default.
    Abut there are other defaults that are non-0 and there an |= with a value that is zero won't give the expected result.

    In general, |= and &= operations with multi-bit constants are a possibly source of trouble.
    It's better to use somehting like

    UCSCTL4 = (UCSCTL4 & ~(SELS_3|SELM_3))|SELS_DCOCLK|SELM_XT2CLK; (assuming, SELS_3/SELM_3 is the maximum setting, with all possible bits set)

    Thsi will first clear the two bitfields SELMx and SELSx, and then OR the required values in. It is slower and larger than two UCSCTL4&=,,,UCSCTL4|=... instructions, but does only one write to UCSCTL4, which might be important (no unintended intermediate clock switches). And ensures a proper setting, independently of the former state of UCSCTL4.

    Of course, if all new settings of UCSCTL4 are known (the former state is unimportant), a simple

    UCSCTL4 = ...

    is the fastest, shortest and safest way.

  • I have to disagree with some parts you wrote.

    1.)  SELS__DCOCLK (note the double underscore) is an alias to SELS_3. Which is 0x0030, so it does set bits in UCSCTL4.

    2.) The power up register value of UCSCTL4 is 0x0044 (at least if the family guide is right) which corresponds to MCLK = SMCLK = DCOCLK_DIV, ACLK = XT1CLK

    I do agree however that a simple UCSCTL4 = SELA__REFOCLK | SELS__DCOCLK | SELM__XT2CLK; is the best way to get the settings right.

  • It helps a lot. Thank you.

     

    Let's use UCSCTL4 = SELA__REFOCLK | SELS__DCOCLK | SELM__XT2CLK;

    For some reason the code sets SELA before stabilization loop and SELS and SELM after.

    Current change of UCSCTL4 will put all settings before the loop. Is it Ok?

     


  • Hmm, I'm not sure about that because if you set it before the stabilization loop it might be that the XT2 is not oscillating and your MCLK will be sourced from that - so it would stall or reset the MSP.

    I think it would be better to put that line after the stabilization loop finished because you can be sure that XT2CLK is working as intended then.

    Also leave the line which selects the REFOCLK for ACLK because otherwise you might get trapped in the stabilization loop as the XT1 fault flag will be set all the time.

  • Bernhard Weller said:
    SELS__DCOCLK (note the double underscore) is an alias to SELS_3. Which is 0x0030, so it does set bits in UCSCTL4.

    You're right. I had the older clock modules in mind where DCO is the default value and it is the 0 value too.

    Indeed, the default on UCSCTL4 is SELS__DCODIV, which is 0x0040. OR-ing SELS__DCOCLK which is 0x0030 would result in 0x0070, which is SELS_7 and reserved (defaults to XT2CLK on the 5419A)

    So for SMCLK, there will be no clock selected at all (0Hz) if XT2 is not running.
    Same for MCLK, but MCLK wil fall back to DCOCLKDIV if XT2 is not running, so it will at least have a clock.

**Attention** This is a public forum