Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

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.

SysCtlClockSet not working for some parameters in TivaWare 1.0

I am using CCS 5.3.0.00090 and ARM compiler 5.0.5.  I have just moved working code from StellarisWare to TivaWare. 
I am working two of code having very similar initialization code.  One uses an external oscillator,
and another uses the internal oscillator.

I use the FLASH versions of these functions when driving the oscillator at 80MHz,
due to the SYSCTL_SYSDIV_2_5 not being supported in the ROM_version

    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_20MHZ);
    sysCtlClock = SysCtlClockGet(); // Returns 80,000,000

For the second implementation I used,

    SysCtlClockSet(SYSCTL_OSC_INT|SYSCTL_SYSDIV_10|SYSCTL_USE_PLL);
    sysCtlClock = SysCtlClockGet();  // For StellarisWare, this returns 20,000,000, for TivaWare 37,500

I switched back to the ROM_ versions:

    ROM_SysCtlClockSet(SYSCTL_OSC_INT|SYSCTL_SYSDIV_10|SYSCTL_USE_PLL);
    sysCtlClock = ROM_SysCtlClockGet();  // returns 20,000,000 for both StellarisWare and TivaWare

I see many changes to this function in sysctl.c.  Somebody dropped the ball here.

When feeding 37,500 into (ROM or FLASH versions)

ROM_SSIConfigSetExpClk(SSI0_BASE, sysCtlClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 10000000, 8);

This leads to a forever loop inside of SSIConfigSetExpClk.  This is nasty.

  • With TivaWare 1.0 the following combination returns 20,000,000:

    SysCtlClockSet(SYSCTL_OSC_INT|SYSCTL_SYSDIV_10|SYSCTL_USE_PLL);
      sysCtlClock = ROM_SysCtlClockGet();

    This suggests the fault may be in SysCtlClockGet returning the wrong value, rather than SysCtlClockSet setting the wrong value.

  • John Osen said:
    For the second implementation I used,

        SysCtlClockSet(SYSCTL_OSC_INT|SYSCTL_SYSDIV_10|SYSCTL_USE_PLL);
        sysCtlClock = SysCtlClockGet();  // For StellarisWare, this returns 20,000,000, for TivaWare 37,500

    Debugging shows that the SysCtlClockSet function has set the following registers:

    SYSCTL_RCC 0x04CE0010 Run-Mode Clock Configuration [Memory Mapped]
        SYSCTL_RCC_ACG 0 Auto Clock Gating
        SYSCTL_RCC_SYSDIV 1001 System Clock Divisor
        SYSCTL_RCC_USESYSDIV 1 Enable System Clock Divider
        SYSCTL_RCC_USEPWMDIV 0 Enable PWM Clock Divisor
        SYSCTL_RCC_PWMDIV 111 PWM Unit Clock Divisor
        SYSCTL_RCC_PWRDN 0 PLL Power Down
        SYSCTL_RCC_BYPASS 0 PLL Bypass
        SYSCTL_RCC_XTAL 00000 Crystal Value
        SYSCTL_RCC_OSCSRC 01 Oscillator Source
        SYSCTL_RCC_IOSCDIS 0 Internal Oscillator Disable
        SYSCTL_RCC_MOSCDIS 0 Main Oscillator Disable


    SYSCTL_RCC2 0x04C04010 Run-Mode Clock Configuration 2 [Memory Mapped]
        SYSCTL_RCC2_USERCC2 0 Use RCC2
        SYSCTL_RCC2_DIV400 0 Divide PLL as 400 MHz vs. 200 MHz
        SYSCTL_RCC2_SYSDIV2 001001 System Clock Divisor 2
        SYSCTL_RCC2_SYSDIV2LSB 1 Additional LSB for SYSDIV2
        SYSCTL_RCC2_USBPWRDN 1 Power-Down USB PLL
        SYSCTL_RCC2_PWRDN2 0 Power-Down PLL 2
        SYSCTL_RCC2_BYPASS2 0 PLL Bypass 2
        SYSCTL_RCC2_OSCSRC2 001 Oscillator Source 2

    The SYSCTL_RCC2_USERCC2 bit is clear, which means the SYSCTL_RCC register is used.

    SYSCTL_RCC_OSCSRC = 01, which means the oscillator source is "Precision internal oscillator" (16 MHz). However, single stepping SysCtlClockGet shows that ui32Clk gets set to 30000 (Low-frequency internal oscillator) which results in SysCtlClockGet reporting a frequency which is too low:

  • Chester Gillon said:
    However, single stepping SysCtlClockGet shows that ui32Clk gets set to 30000 (Low-frequency internal oscillator) which results in SysCtlClockGet reporting a frequency which is too low

    SysCtlClockGet in TivaWare 1.0 contains the following switch statement:

        //
        // Get the base clock rate.
        //
        switch((ui32RCC2 & SYSCTL_RCC2_USERCC2) ?
               (ui32RCC2 & SYSCTL_RCC2_OSCSRC2_M) :
               (ui32RCC & SYSCTL_RCC_OSCSRC_M))
        {
            //
            // The main oscillator is the clock source.  Determine its rate from
            // the crystal setting field.
            //
            case SYSCTL_RCC_OSCSRC_MAIN:
            {
                ui32Clk = g_pui32Xtals[(ui32RCC & SYSCTL_RCC_XTAL_M) >>
                                       SYSCTL_RCC_XTAL_S];
                break;
            }

            //
            // The internal oscillator is the source clock.
            //
            case SYSCTL_RCC_OSCSRC_INT:
            {
                //
                // The internal oscillator on all devices is 16 MHz.
                //
                ui32Clk = 16000000;
            }

            //
            // The internal oscillator divided by four is the source clock.
            //
            case SYSCTL_RCC_OSCSRC_INT4:
            {
                //
                // The internal oscillator on all devices is 16 MHz.
                //
                ui32Clk = 16000000 / 4;
            }

            //
            // The internal 30-KHz oscillator is the source clock.
            //
            case SYSCTL_RCC_OSCSRC_30:
            {
                //
                // The internal 30-KHz oscillator has an accuracy of +/- 30%.
                //
                ui32Clk = 30000;
                break;
            }

            //
            // The 32.768-KHz clock from the hibernate module is the source clock.
            //
            case SYSCTL_RCC2_OSCSRC2_32:
            {
                ui32Clk = 32768;
                break;
            }

            //
            // An unknown setting, so return a zero clock (that is, an unknown
            // clock rate).
            //
            default:
            {
                return(0);
            }
        }

    Note that the case for SYSCTL_RCC_OSCSRC_INT and SYSCTL_RCC_OSCSRC_INT4 are missing a break statement - which causes them to "fall through" and set ui32Clk to 30000. When I added a break to the case for SYSCTL_RCC_OSCSRC_INT and SYSCTL_RCC_OSCSRC_INT4 SysCtlClockGet then returned the correct value.

  • John Osen said:
    I see many changes to this function in sysctl.c.  Somebody dropped the ball here.

    The following is a comparison of the TivaWare 1.0 erroneous switch (on the left) compared to StellarisWare (on the right):

      

    This shows in deleting the code for SandStorm and Fury classes the break statement was deleted by mistake (TivaWare only has to support the Blizzard class). A review of TivaWare .vs. StellarisWare would be a useful exercise to see if any other such errors can be identified.

  • John Osen said:
    When feeding 37,500 into (ROM or FLASH versions)

    ROM_SSIConfigSetExpClk(SSI0_BASE, sysCtlClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 10000000, 8);

    This leads to a forever loop inside of SSIConfigSetExpClk.  This is nasty.

    That combination is an invalid set of parameters to SSIConfigSetExpClk, since the ui32SSIClk (clock supplied to the SSI module) parameter is less than the ui32BitRate (requested SSI bit rate) parameter. From looking at the code, if the driverlib was compiled with DEBUG then the asserts at the start of the SSIConfigSetExpClk would have detected the invalid parameters.

    The pre-compiled driverlib supplied with TivaWare 1.0 doesn't have DEBUG defined so the assert doesn't do anything. To get the validation performed by assert you have to re-compile driverlib with the predefined symbol DEBUG set in the CCS project properties.

  • Chester,

    For a community member, you are awesome.  You really dug deep for this answer.  If I had a calm mind, I should have seen it myself as the file differences were sitting right in front of me, if I had only done a code review.  ;)  My "revert to ROM function" works for me, so I will not try to fix the code and recompile.  That would mean importing TivaWare into our SW CM system and branching ... yuk!

    As this exchange is between two community members, do you believe a TI employee is going to pick up the thread as a fix for TivaWare 1.1?

    If not, how do we make it so?  (I will try a separate post.)

    Thanks so much for your time.

  • @Chester:

    Chester's skill/effort ++;

    Systematic, detailed, and drilled down to the exact cause.  (wonderful post mortem)  We're in your debt - thank you.

    Collateral Damage on further display - this "most necessary" re-brand exercise.  (never explained/justified)

    Your attention to detail and care in assisting fellow users hereby memorialized - too bad that those "responsible" appear to have improperly planned and/or implemented so vast a change - and without providing any justification for so doing...  Full Speed Ahead...(what iceberg?)

  • FYI, I've raised a bug report on this. As far as I can remember, this is already fixed (I hit it a while ago) but not released. Look for an update in the next TivaWare release scheduled in a month or so.

    Regarding the issue of a TI person not seeing this, it's likely because you all discussed and answered the question without TI help before the engineer responsible for Jun 12th actually got to the thread. We each have a day every couple of weeks when we monitor the forum and are responsible for answering questions that come in. If a question is already answered, though, I can imagine some people would just skip the thread. I'll send an email asking people to make sure they read all new threads started on their day regardless of whether or not they are marked as answered. Hopefully that will prevent bug reports like this one from slipping through the net in future.