How to wait 1 second. Interface with timers.

The technical reference manual states that the Cortex-A57 generic timer events are not affected by CPU clock frequency change. My challenge is that I can’t use any built in linux libraries to create a delay because whenever I try it clears performance register that i’m trying to observe. Does anyone know a simple way to get the timer ticks value or even perhaps configure the timer. My attempts so far have all yielded in illegal instruction errors.
Thanks for any help.

A57 uses the ARM architecture timers. Nvidia/Upstream Linux Kernel code enables accessing the timer value from userspace.

For 32-bit systems : Check the below function and use can use the same asm instruction in your code to read the 64-bit timer value from your program in userspace.

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/arch_timer.h?id=refs/tags/v4.6-rc5#n90

(That’s Line 90 - arch_counter_get_cntvct)

Hope this helps.

That doesn’t seem to work when i try to incorporate that into my code.

static inline u32 arch_timer_get_cntfrq(void)
{
u32 val;
asm volatile(“mrc p15, 0, %0, c14, c0, 0” : “=r” (val));
return val;
}

In trying to get the simplest case to work it is giving an error unknown mnemonic mrc.

I’m currently writing and reading the performance registers with the MRS/MSR commands with success.
Reading CNTFRQ_EL0 is also successful with MRS though CNTPCT_EL0 fails. I’m assuming that is because CNTKNCTL_EL1 bit[9] is set to 0; I can’t read that verify though.

It would seem that the Kernel doesn’t set up the AArch64 system for timer access from the userspace.
The only other counter register I seem to have access to is CNTVCT_EL0. Which would indicate these two are only registers made available by the kernel as bit[1] of CNTKCTL_EL1 is high.

Hi kaminsknator

Few options for your reference:

  1. You can use the T210 SOC timers. There is a microsecond timer that runs all the time. See tegra_read_usec_raw() in drivers/clocksource/tegra210_timer.c. We use that function in a few places for profiling.
  2. You could modify the SOC timer driver above to run faster than every 1 microsecond. The block at line 251 (switch (tegra210_timer_freq)…) controls the divider. The call to clocks_calc_mult_shift() at the bottom would need to be modified so that the timer is programmed properly.
  3. For more accuracy, you can disable dynamic frequency scaling for the memory controller (if it is enabled). I don’t know how to disable that. Then use the BUS_CYCLES performance counter event as a time base.

Thanks

Wasn’t sure how to get any of those timer functions to work in my code but ended up using the virtual timer that is accessible and it works well enough for my application. If I was ambitious enough i could re-enable access and rebuild the kernel. Thanks for all the help!