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.

TM4C129ENCPDT: SysCtlClockFreqSet do not set the frequency correctly

Part Number: TM4C129ENCPDT

Hello.

In our project we are facing following problem ...

There's running long term test with 14 pieces of our device (TIVA controller). These devices are connected to one power supply, which is cyclically turned off and on for 3 seconds. After each restart there's checked the state of all the devices (they have to start to properly communicate with PLC via Profinet) and if all of them are ok the power supply is turned off and on again. After several hundreds of restarts of the system (which means thousands of restarts of devices, because 14 devices are restarted every time), one of the devices (a different piece every time) gets to a very strange state, it's somehow slowered down. It seems to be approx. 15 times slower, startup is longer, LEDs blinking is slower, responses on ethernet bus (Profinet) is slower. It seems to be a problem with clock frequency.

We set the clock frequency in the following way ...
uint32_t realFrequency = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); //120 MHz
and checking the return value that it was se properly. There's returned the required value of 120000000 every time even in the problematic cycle of the device. 

When I set 8 MHz instead of 120 MHz ...
MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 8000000); //8MHz
then the device behavior is similar to the issue which can be seen in our long term test.

I was reading the err data document and I found there the error SYSCTL#22 Change to the PLL Clock Divider may Cause System Clock to be out of Specification.
I thought that it could also be our problem but then I found out that we're using TivaWare_C_Series-2.1.4.178_drl and it should contain the fix for that error.

My questions ...

1) Don't you have any explanation for that issue? Aren't there any other "frequency" problems in the controller which could cause similar behavior?

2) When the problem described in SYSCTL#22 occurs, what's the result, what does it mean that "cause the system clock to be out of specification"? Which frequency is set? Could it cause similar behavior as in case of our device?

3) How could I verify that the 120MHz frequncy was really set properly? Could you me provide a piece of code how to handle it, please?

Thank you in advance for any help.

Zdenek Krejsa

  • I have heard this once before, but the low occurrence of the behavior made it difficult to debug. I suspect there may still be an issue in how the divider at the output of the PLL is initialized after power-on. You can write to the divider and you read back what you wrote, but the value never propagates to actual divide circuitry. Can you try a test for me? Add a call to SysCtlClockFreqSet() which sets the PLL clock to 60MHz, and then call it again setting the clock to 120MHz. Would you be able to run your test again and report the results?

      MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 60000000);
      realFrequency = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); 

  • Thank you for a very fast response.

    So do I understand it correctly that there's no way how to verify that the clock frequency was set correctly?

    I will add the suggested workaround to our FW and test it during next week.

    Best regards,

    Zdenek Krejsa

  • Sorry, I failed to address that part of your question. Yes, there are several ways to validate that the PLL is working correctly. They may not be extremely accurate, but for this fail mode the difference between proper operation and improper operation will be by at least one count in the PSYSDIV register. In version 2.1.4.178 of TivaWare and later, the PLL uses a 240MHz VCO and a PSYSDIV of 2 for 120MHz operation. (The function call uses SYSCTL_CFG_VCO_480 for compatibility with earlier versions, but it is really at 240MHz.) The minimum the PLL frequency can be off is with PSYSDIV equal to three which gives a system clock of 80MHz. In your case you saw a much bigger difference.

    A simple way to check the PLL frequency is to enable the system timer to run off of the PIOSC (always 16MHz) and have a software loop count while the system time decrements to zero. Choose an initial count value for the system timer based on how accurate you want the check and how much time you are willing to consume for this startup check. Compare the software loop count to the value you get when the PLL started up properly, with a small +/- window to allow for synchronization. This must be done before you enable any interrupts.

  • Here is a simple piece of code that uses Timer0 running from the PIOSC to check for proper PLL operation. The value 1711 was found by running the code and seeing the count when the PLL worked properly. That value may change with different compiler versions and different optimization levels. In my case I used the TI compiler version 18.12.6 and optimization level 2, speed vs size setting of 1.

    int main(void)
    {
        uint32_t ui32SysClock;
        uint32_t count;
    
        //
        // Run from the PLL at 120 MHz.
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Enable and wait for the timer to be ready for access
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0))
        {
        }
        TimerClockSourceSet(TIMER0_BASE, TIMER_CLOCK_PIOSC);
        TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);
        TimerLoadSet(TIMER0_BASE, TIMER_A, 16000000/5000); // 200uS
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        count = 0;
        TimerEnable(TIMER0_BASE, TIMER_A);
        while(TimerIntStatus(TIMER0_BASE, false) != TIMER_TIMA_TIMEOUT)
        {
            count++;
        }
        if((count > (1711 + 17)) || (count < (1711 - 17)))
        {
            for(;;); // fail
        }
    }
    

  • We tested the suggested simple fix ... "Add a call to SysCtlClockFreqSet() which sets the PLL clock to 60MHz, and then call it again setting the clock to 120MHz."

    The results ... we have a network containing 14 devices with TIVA controller. With the fix in the FW, we succesfully switched off and on the power supply for 10.000 times and all the devices started correctly each time! So it means 14.000 correct restartsof the controller, the fix works.

    So we will use the "magic" fix in our FW for now.

    What will be you  further steps? Will you add new point to err data and apply similar fix to Tivaware library?

    Best regards,

    Zdenek Krejsa

  • Thank you for the feedback. I will discuss the next steps with the team. It will likely be an update to the errata document short term followed with a fix in TivaWare at the next TivaWare release.

  • A few questions ...

    - when the setting of 60 MHz before 120 MHz frequency solved the problem, can you estimate what causes the issue?

    - we did similar test with other type of device which contains the same type of controller (TM4C129ENCPDT), but we are not able to reproduce the problem there. Do you have any idea what could increase the probability of the issue ... temperature, curve of the power supply?

  • We believe the issue is related to the output stage divider of the PLL. That register is actually double buffered with logic that prevents updating the second buffer when the divide register is written with the same value, that is you re-write the divide register with the same value as it previously had. We suspect that on some parts, that logic is not getting properly reset. The logic requires seeing a change in the divide register. By setting the PLL clock to 60MHz, the divide register is set to two, then at 120MHz it gets set to one. This sequence clears the logic and the second write is effective. 

    I suspect the issue is related to the process. I do not know if it is related to a process corner or local mismatch. Changes in core voltage (the 1.2V supply) and temperature may affect this issue. If possible, could you provide the date codes of the devices you tested which showed the issue, and the date code of the devices on the product that you tested which did not show the issue. That might be helpful for us to better understand the problem.