Search code examples
carmtimingcortex-m

Timing functions on cortex-m1 gives weird results


I'm having problems timing functions on cortex-M1. I'm using an Arty A7 and I'm using systick to count the clock duration of a function. The problem is that the clocks I'm getting don't make sense, while prototyping the function on my PC I measured its clock duration with clock() from time.h - it took about 5000 clocks. Next I tried to measure it on cortex-M1 and used systick to count the clocks - now the results showed millions of clocks, which I think doesn't make sense.

Here is how I measure using systick

#define STCTRL      (*( ( uint32_t *) 0xE000E010 ))
#define STRELOAD    (*( ( uint32_t *) 0xE000E014 ))
#define STCURR      (*( ( uint32_t *) 0xE000E018 ))

int main(void)
{
    SystemInit();
    STRELOAD = 16000000;
    uint32_t start, stop;

    STCTRL = (1<<0) | (1<<2);
    wait(1000);
    start = STCURR;
    function();
    stop = STCURR;
    STCTRL = (0<<0);
    printf("%d", (int)(start-stop));
}

I'm not sure how relevant this information is, but when prototyping i compiled with gcc-9 and used -O3 -Otime, when compiling for cortex-M1 I use armcc v5.06 - update 7 with flags: --c99 --gnu -c --cpu Cortex-M1 -D__EVAL --li -g -O3 -Otime

My question is how and why are the 2 measurements so different? Am I doing something wrong when measuring clock cycles (either with clock() or systick)?


Solution

  • First, your register definitions are wrong because they are missing out volatile:

    #define SysTick_TCTRL      (*((volatile uint32_t*)0xE000E010))
    etc.
    

    Next, you need to set SysTick_LOAD to (period - 1), not period. In your example the period is 16000001.

    After that, systick counts down and wraps at 24 bits or the limit that you set, so you need to undo this with modulo or just if-then-subtract. Modulo is tidier but the divide pulls in libraries on ARMv6M.

    if (start > stop)
    {
      duration = (start - stop);
    }
    else
    {
      duration = (period - (stop - start));
    }