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.

AM3359 CPU frequency changes while running

Hi,

I have an application that runs under Arago with kernel 3.12.10.  One part of the application makes heavy use of the DCAN peripheral.  I have found that under relatively heavy load on the CAN bus my application will run well for an indeterminate length of time (1 minute up to several hours).  By heavy load I mean it has to process as many as 1500 messages per second.  I have found that under such (heavy but shouldn't be) load the CPU frequency will randomly get scaled back from 600 Mhz to around 45-60 Mhz.  I have no idea what is causing this to happen.

I have never seen this happen when CAN data is not being handled, or when the frequency of incoming CAN message is low (eg 10 Hz).  I have seen it happen when the only user space application is candump.  Therefore it isn't a problem with the application that we have written.

The kernel was built with CPU frequency scaling enabled.  But the only permitted frequencies are 300,000 and 600,000.  But the apparent reduction in speed was down to 60,000 or even lower.  I am not sure how that is possible.  When seen it was possible to recover by setting the CPU frequency to 300,000 and then to 600,000.  Setting directly to 600,000 had no effect, presumably because the driver thought that the frequency was already at 600,000.

The problem appears to have been solved by rebuilding the kernel without any of the CPU frequency scaling functionality.  Now whatever was causing the problem is being stymied.

I really want to understand what has happened here.  Has anyone else seen this problem?  Has anyone managed to find the root cause?

  • It seems your speed indications are only approximate.. is it possible the CPU frequency actually dropped down all the way to the main osc frequency (often 24 or 25 MHz) ? Since that would suggest the dynamic frequency scaling is somehow mismanaging the PLL and causing it to enter bypass mode...

    Note sure what the link with CAN would be though... other than giving the CPU a reason for switching frequency I guess.

  • My speed indications are approximate. It does make sense that the PLL has gone to bypass mode as that is more understandable than having a random value assigned to the frequency scaling.

    Can you suggest where I might look to find out what the frequency has been set to? i.e which registers do I want to look at?
  • It turns out that this issue was raised 4 months ago.

    e2e.ti.com/.../1419278

    Has TI idntified the root cause or found a fix?
  • Bob Koen said:
    Can you suggest where I might look to find out what the frequency has been set to? i.e which registers do I want to look at?

    Attached is a little prog that dumps the state of the MPU PLL. I've included the compiled version since my slightly eccentric style of C++ needs g++ 4.9 which isn't available on all systems.

    0451.subarctic-pllcheck.tar.gz

    Updated: Altered makefile slightly and recompiled to avoid unnecessary shared library dependencies. It now only depends on libc.

  • The bug may be related to a problem in routine pll_bypass() in file dpll.c in the firmware section of the Cortex M3 code. The routine saves the content of register CM_CLKMODE_DPLL_MPU when going into bypass mode. If the bypass mode routine is called again before the routine to put the DPLL into lock mode runs then it will save the bypass value for the register the second time, while expecting that it is saving the value for lock mode. When coming out of bypass mode and going into lock mode the stored register value is inserted into the register. In random cases this value seems to be incorrect, probably because bypass was called twice in a row. If this happens then the DPLL will stay in bypass mode indefinitely.

    Note that this theory isn't tested. We have chosen to just disable the CPU idle function in menuconfig and rebuild the kernel.