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.

Confusion about SMCLK of MSP430F5510

Other Parts Discussed in Thread: MSP430F5510

Hi, I'm using a MSP430F5510 for my master degree thesis, and I'm a bit confused about the MCLK and SMCLK. I read the datasheet part concerning the clock module lots of times, but I think it is not so clear, at least for me. I use a TI example code to set up the microcontroller at 25MHz, because I need it to work at full speed, since my application is quite heavy. This is the code:

void Clock_Init(void)
{
// Increase VCore, step by step, to support 25MHz
Clock_SetVCoreUp(0x01);
Clock_SetVCoreUp(0x02);
Clock_SetVCoreUp(0x03);
UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_7; // Select DCO range 50MHz operation
UCSCTL2 = FLLD_1 + 762; // Set DCO Multiplier for 25MHz: (762 + 1) * 32768 = 25MHz
__bic_SR_register(SCG0); // Enable the FLL control loop
__delay_cycles(782000); // Settling time for DCO
// Loop until XT1, XT2 and DCO stabilizes
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
} while (SFRIFG1&OFIFG); // Test oscillator fault flag
}
// Set the VCore to the specified level
void Clock_SetVCoreUp(unsigned int level)
{
PMMCTL0_H = PMMPW_H; // Open PMM registers for write
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level; // Set SVS/SVM high side new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level; // Set SVM low side to new level
while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait until SVM is settled
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); // Clear already set flags
PMMCTL0_L = PMMCOREV0 * level; // Set VCore to new level
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0); // Wait till new level reached
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level; // Set SVS/SVM low side to new level
PMMCTL0_H = 0x00; // Lock PMM registers for write access
}

In my circuit I also use the SMCLK (from port P2.2) as a clock source for another device. I read that normally the SMCLK frequency is around 1MHz. My question is: if I set up the DCO to 25MHz, will the SMCLK frequency be 25MHz or I can choose a different value? The other device needs a clock source of 1MHz or 2MHz, and I chose the SMCLK for this reason, but I never thought that the SMCLK can change with the DCO. Can I have a DCO frequency of 25MHz and a SMCLK frequency of 1MHz? If yes, how can I configure the SMCLK frequency?

  • Figure 5.1 UCS Block Diagram in the MSP430x5xx/MSP430x6xx Family User's Guide SLAU208J shows the options for sourcing MCLK and SMCLK. This shows that MCLK and SMCLK have independent divisors of either /1, /2, /4, /8, /16 or /32 from their sources.

    i.e. MCLK and SMCLK can be different frequencies, but the range of possible divisors is limited. e.g. if SMCLK needs to be 1MHz or 2MHz then your options are:

    1) Set DCOCLK to 16MHz.  Set MCLK to be sourced from DCOCLK / 1, so the CPU runs at 16MHz. Set  Set SMCLK to be sourced from DCOCLK/16, so the SMCLK runs at 1MHz 

    2) Set DCOCLK to 16MHz.  Set MCLK to be sourced from DCOCLK / 1, so the CPU runs at 16MHz. Set  Set SMCLK to be sourced from DCOCLK/8, so the SMCLK runs at 2MHz

    Emanuele Bellocchia said:
    In my circuit I also use the SMCLK (from port P2.2) as a clock source for another device.

    If you can change the clock source to be a different pin, an alternative might be to:

    a)  Set DCOCLK to 24MHz.  Set MCLK to be sourced from DCOCLK / 1, so the CPU runs at 24MHz. 

    b) Set SMCLK to be sourced from DCOCLK / 1, so the SMCLK runs at 24MHz. 

    c) Set a Timer clocked from SMCLK in Up Mode with a period of 12, and use a Compare Module  with an Out Mode of "toggle". That should cause the timer Compare Module output to be a 1MHz clock. (for 2 MHz clock would use a period of 6)

  • Aside from the data-sheet, you also need to read the 5xx Family User's Guide.

    DCO oscillator is a source of clock signal. So are the LFXT1 oscillator, the XT2 oscillator, etc.

    MCLK, SMCLK, and ACLK are not clock sources, they are what I called clock-routers. You can use these clock-routers to deliver clock signals from the oscillators to CPU and various other places. Which router delivers what are set up in clock control registers. There are also options of having the clock sources divide by 1, 2, 4 or 8 before it is put on the routers.

  • Thank you very much for your answers, now I understand how it works. I decide to set DCO to 24MHz, MCLK divided by 1 and SMCLK divided by 8, so SMCLK = 3MHz that is also ok for me. I modify the first function in this way:

    // Increase VCore, step by step, to support 24MHz
    Clock_SetVCoreUp(0x01);
    Clock_SetVCoreUp(0x02);
    Clock_SetVCoreUp(0x03);
    UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
    UCSCTL4 |= (SELA_2 | SELS_3 | SELM_3); // Set ACLK = REFO, MCLK = DCOCLK, SMCLK = DCOCLCK
    UCSCTL5 |= DIVS_3; // Set SMCLK divider = 8
    __bis_SR_register(SCG0); // Disable the FLL control loop
    UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
    UCSCTL1 = DCORSEL_7; // Select DCO range 50MHz operation
    UCSCTL2 = FLLD_1 + 731; // Set DCO Multiplier for 24MHz: (731+ 1) * 32768 = 24MHz
    __bic_SR_register(SCG0); // Enable the FLL control loop
    __delay_cycles(752000);  // Worst-case settling time for DCO
    // Loop until XT1, XT2 and DCO stabilizes
    do
    {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
    } while (SFRIFG1&OFIFG); // Test oscillator fault flag

    Is it right to set the divider at the beginning?

  • Emanuele Bellocchia said:
    Is it right to set the divider at the beginning?

    It is rather unimportant. It just should happen before you program any peripheral to use SMCLK.
    However, before changing the DCORSELx bits, you should not only set the DCOx bits to lowest, but also set the MCLK divider to at least 2, as in the moment of change, an incomplete (and therefore high-frequency) clokc puls emay happen, which will crash the CPU. Having a divider on MCLK will average two pulses, and since only one is off, the result will still be in the allowed range. You may change back immediately after changing DCORSELx.

  • Emanuele Bellocchia said:
    UCSCTL4 |= (SELA_2 | SELS_3 | SELM_3); // Set ACLK = REFO, MCLK = DCOCLK, SMCLK = DCOCLCK

    Actually, that code doesn't work as intended. The reason is that:

    a) After a reset (Power Up Clear) UCSCTL4 is set to:
    SELA = 000 = XT1CLK
    SELS = 100 = DCOCLKDIV
    SELM = 100 = DCOCLKDIV

    b) The code bitwise-ORs (SELA_2 | SELS_3 | SELM_3) into UCSCTL4 resulting in:
    SELA = 010 = REFOCLK
    SELS = 111 = Reserved for future use. Defaults to XT2CLK when available, otherwise DCOCLKDIV.
    SELM = 111 = Reserved for future use. Defaults to XT2CLK when available, otherwise DCOCLKDIV.

    c) As a result XT2CLK is attempted to be used to source SMCLK and MCLK. The while loop waiting for the oscillator fault flag to clear never exits, due to the XT2OFFG flag being set. (even if the is a crystal connected to XT2 the code hasn't selected the P5.2/P5.3 pins for the XT2 module).

**Attention** This is a public forum