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.

PLL configuration

Other Parts Discussed in Thread: TM4C129ENCPDT

Hi,

I'm using a TM4C129ENCPDT and I would like to obtain a CPU system clock of 100MHz.

The SysCtlClockFreqSet( ) allowed me to get close i.e. 96MHz using the following instruction

    gSysCtlClock = SysCtlClockFreqSet(
                        SYSCTL_USE_PLL    |
                        SYSCTL_OSC_MAIN   |
                        SYSCTL_XTAL_25MHZ |
                        SYSCTL_CFG_VCO_480,
                        100000000);        //desired system frequency

Looked more into the data sheets and apparently I need to change the PLL fvco frequency to get what I need (Mint = 16, Mfrac = 0, Q = 0, N = 0, PSYSDIV = 3).

Do you have an example code with the proper sequence of event that I could use to change the PLL fvco and thus set the system clock to 100MHz?

thanks.

Khaled.

  • Hello Khaled,

    No, we do not have an example to change the parameter as it would conflict with the ROM Image.

    However if you want to change the same, then corresponding entry for the 25MHz crystal for VCO of 480 needs to be changed in the constant g_pppui32XTALtoVCO in sysctl.c file

    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(5) }, // 25 MHz

    to
    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(6) }, // 25 MHz

    to get a 400MHz VCO on which a divider of 4 can be configured for 100MHz and a change of g_pui32VCOFrequencies from 480000000 to 400000000

    Regards
    Amit
  • Hi Amit
    But don't I need to shut down the PLL, reconfigure the PLL SYSCTL_PLLFREQ0 and SYSCTL_PLLFREQ1 and then restart the PLL?
    Khaled
  • Hello Khaled,

    No, you do not need to shut down the PLL and reconfigure. By making the changes in the sysctl.c file it will allow the first lock of the PLL to be with a VCO of 400MHz which can be used to get 100MHz System Clock.

    Do note that do not use ROM version or MAP version of SysCtlClockFreqSet after making this change to sysctl.c

    Regards
    Amit
  • But those values are defined in the driverlib.lib library. Does that means that I need to change the sysCtl.h and included it?
    Bottom line, what is the best way to make the change? I can add a increase the MAX_VCO_ENTRIES from 2 to 3 and add a new section for 400MHz VCO?
    Khaled
  • Hello Khaled

    Yes, that would be another way of updating the sysctl.c file. But do note that every entry for 320 and 480 Mhz VCO has to be done for the lookup table.

    Regards
    Amit
  • I made a local copy of sysctl.c and included it in my project so I can make the changes independently of TIVAware (in case a new revision is installed).
    {
    //
    // VCO 400 MHz
    //
    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(1) }, // 4.1666 MHz
    { PLL_M_TO_REG(93, 768), PLL_N_TO_REG(1) }, // 4.2666 MHz
    { PLL_M_TO_REG(80, 0), PLL_N_TO_REG(1) }, // 5 MHz
    { PLL_M_TO_REG(78, 128), PLL_N_TO_REG(1) }, // 5.12 MHz
    { PLL_M_TO_REG(65, 107), PLL_N_TO_REG(1) }, // 6.143 MHz
    { PLL_M_TO_REG(60, 0), PLL_N_TO_REG(1) }, // 6.666 MHz
    { PLL_M_TO_REG(58, 608), PLL_N_TO_REG(1) }, // 6.826 MHz
    { PLL_M_TO_REG(48, 0), PLL_N_TO_REG(1) }, // 8.333 MHz
    { PLL_M_TO_REG(40, 0), PLL_N_TO_REG(1) }, // 10 MHz
    { PLL_M_TO_REG(39, 64), PLL_N_TO_REG(1) }, // 10.24 MHz
    { PLL_M_TO_REG(35, 408), PLL_N_TO_REG(1) }, // 11.299 MHz
    { PLL_M_TO_REG(33, 536), PLL_N_TO_REG(1) }, // 11.931 MHz
    { PLL_M_TO_REG(30, 0), PLL_N_TO_REG(1) }, // 13.333 MHz
    { PLL_M_TO_REG(29, 304), PLL_N_TO_REG(1) }, // 13.653 MHz
    { PLL_M_TO_REG(80, 0), PLL_N_TO_REG(3) }, // 15 MHz
    { PLL_M_TO_REG(24, 0), PLL_N_TO_REG(1) }, // 16.666 MHz
    { PLL_M_TO_REG(20, 0), PLL_N_TO_REG(1) }, // 20 MHz
    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(6) }, // 25 MHz
    },

    But where should I set the new SYSCTL_CFG_VCO_400 value to? and how should I modify the SysCtlClockFreqSet( ) to take into account this new #define?
    gSysCtlClock = SysCtlClockFreqSet(
    SYSCTL_USE_PLL |
    SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_25MHZ |
    SYSCTL_CFG_VCO_400,
    100000000); //desired system frequency



    Khaled.
  • Hello Khaled

    That must be done in the sysctl.h. Based on the order in which it is defined in the sysctl.h the same order must be applied to g_pppui32XTALtoVCO and the other constants.

    Regards
    Amit
  • In the sysclt.h we have
    #define SYSCTL_CFG_VCO_480 0xF1000000 // VCO is 480 MHz
    #define SYSCTL_CFG_VCO_320 0xF0000000 // VCO is 320 MHz

    what those values means and they are not used explicitly in SysCtlClockFreqSet( ) but they do have an effect: If SysCtlClockFreqSet( ) is called without this argument it default to 320MHz.
    Explicit code showing the modification will be useful.
    thanks.
    Khaled.
  • Hello Khaled,

    Define the new VCO like the following

    #define SYSCTL_CFG_VCO_400 0xF2000000 // VCO is 400 MHz
    #define SYSCTL_CFG_VCO_480 0xF1000000 // VCO is 480 MHz
    #define SYSCTL_CFG_VCO_320 0xF0000000 // VCO is 320 MHz

    Then

    #define MAX_VCO_ENTRIES 3

    static const uint32_t g_pppui32XTALtoVCO[MAX_VCO_ENTRIES][MAX_XTAL_ENTRIES][2] =
    {
    {
    //
    // VCO 320 MHz
    //
    { PLL_M_TO_REG(64, 0), PLL_N_TO_REG(1) }, // 5 MHz
    { PLL_M_TO_REG(62, 512), PLL_N_TO_REG(1) }, // 5.12 MHz
    { PLL_M_TO_REG(160, 0), PLL_N_TO_REG(3) }, // 6 MHz
    { PLL_M_TO_REG(52, 85), PLL_N_TO_REG(1) }, // 6.144 MHz
    { PLL_M_TO_REG(43, 412), PLL_N_TO_REG(1) }, // 7.3728 MHz
    { PLL_M_TO_REG(40, 0), PLL_N_TO_REG(1) }, // 8 MHz
    { PLL_M_TO_REG(39, 64), PLL_N_TO_REG(1) }, // 8.192 MHz
    { PLL_M_TO_REG(32, 0), PLL_N_TO_REG(1) }, // 10 MHz
    { PLL_M_TO_REG(80, 0), PLL_N_TO_REG(3) }, // 12 MHz
    { PLL_M_TO_REG(26, 43), PLL_N_TO_REG(1) }, // 12.288 MHz
    { PLL_M_TO_REG(23, 613), PLL_N_TO_REG(1) }, // 13.56 MHz
    { PLL_M_TO_REG(22, 358), PLL_N_TO_REG(1) }, // 14.318180 MHz
    { PLL_M_TO_REG(20, 0), PLL_N_TO_REG(1) }, // 16 MHz
    { PLL_M_TO_REG(19, 544), PLL_N_TO_REG(1) }, // 16.384 MHz
    { PLL_M_TO_REG(160, 0), PLL_N_TO_REG(9) }, // 18 MHz
    { PLL_M_TO_REG(16, 0), PLL_N_TO_REG(1) }, // 20 MHz
    { PLL_M_TO_REG(40, 0), PLL_N_TO_REG(3) }, // 24 MHz
    { PLL_M_TO_REG(64, 0), PLL_N_TO_REG(5) }, // 25 MHz
    },
    {
    //
    // VCO 480 MHz
    //
    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(1) }, // 5 MHz
    { PLL_M_TO_REG(93, 768), PLL_N_TO_REG(1) }, // 5.12 MHz
    { PLL_M_TO_REG(80, 0), PLL_N_TO_REG(1) }, // 6 MHz
    { PLL_M_TO_REG(78, 128), PLL_N_TO_REG(1) }, // 6.144 MHz
    { PLL_M_TO_REG(65, 107), PLL_N_TO_REG(1) }, // 7.3728 MHz
    { PLL_M_TO_REG(60, 0), PLL_N_TO_REG(1) }, // 8 MHz
    { PLL_M_TO_REG(58, 608), PLL_N_TO_REG(1) }, // 8.192 MHz
    { PLL_M_TO_REG(48, 0), PLL_N_TO_REG(1) }, // 10 MHz
    { PLL_M_TO_REG(40, 0), PLL_N_TO_REG(1) }, // 12 MHz
    { PLL_M_TO_REG(39, 64), PLL_N_TO_REG(1) }, // 12.288 MHz
    { PLL_M_TO_REG(35, 408), PLL_N_TO_REG(1) }, // 13.56 MHz
    { PLL_M_TO_REG(33, 536), PLL_N_TO_REG(1) }, // 14.318180 MHz
    { PLL_M_TO_REG(30, 0), PLL_N_TO_REG(1) }, // 16 MHz
    { PLL_M_TO_REG(29, 304), PLL_N_TO_REG(1) }, // 16.384 MHz
    { PLL_M_TO_REG(80, 0), PLL_N_TO_REG(3) }, // 18 MHz
    { PLL_M_TO_REG(24, 0), PLL_N_TO_REG(1) }, // 20 MHz
    { PLL_M_TO_REG(20, 0), PLL_N_TO_REG(1) }, // 24 MHz
    { PLL_M_TO_REG(96, 0), PLL_N_TO_REG(5) }, // 25 MHz
    },
    {
    //
    // VCO 400 MHz. Your Table Here
    //

    },
    };

    static const uint32_t g_pui32VCOFrequencies[MAX_VCO_ENTRIES] =
    {
    320000000, // VCO 320
    480000000, // VCO 480
    400000000, // VCO 400
    };


    Regards
    Amit
  • Hi Amit,

    I believe its working now. The Q, N, M values are correct in the SYSCTL_PLLFREQ0 and SYSCTL_PLLFREQ1 registers but the returned frequency is 99999984Hz instead of 100000000Hz. It could be rounding error. Should I be concerned with that?

    Khaled.

  • Hello Khaleed,

    It should be 100MHz.

    Regards
    Amit
  • Hi Amit,
    Modified the code is as you have suggested and SYSCTL_PLLFREQ0 == 0x00800060 and SYSCTL_PLLFREQ1 == 0x00000005

    _SysCtlFrequencyGet(ui32Osc) is returning 399999936 instead of 400MHz. It looks like its a rounding problem to me:
    In sysCtl.c/_SysCtlFrequencyGet(25MHz)/line 310, the division ui32Xtal /= (uint32_t)ui8N = 25MHz/6 = 4166666 instead of 4166666.667.
    This rounding error is propagating to the ui32SysClock value.

    If the multiplication by M is done before the division by N the problem could be solved!
    What do you suggest?
    Khaled.
  • Hello Khaled

    I believe you are right. The other VCO's and crystal use an integral divider value of the crystal frequency.

    Regards
    Amit
  • But this is an integral divider value as well (N + 1 = 6)! There is no fractional part (Q == 0).
    In SysCtlFrequencyGet( ) Its the division of ((25MHz / 6) * 96) that return a fractional number
    If the multiplication is done first i.e. ((25MHz * 96) / 6), this problem will not show up.

    Again, is the ui32SysClock value used by the system and if yes, what do you recommend to fix this issue?
    thanks.
    Khaled.
  • Hello Khaled

    I agree with your computation that the issue is because of (25/6)*96 and it must be turned the other way around. For your requirements, there are two options

    1. Since the value of the System Clock is fixed for 100MHz, override the return value of the SysCtlClockFreqSet in your application
    2. Make the change to sysctl.c locally, recompile the driverlib and use the value returned by the updated SysCtlClockFreqSet .

    Regards
    Amit