dpotop
Posts: 76
Joined: Mon Nov 24, 2014 2:14 pm

Best way to synchronize timers?

Thu Apr 18, 2019 8:58 am

Hello,

I'd like to execute code periodically on all cores. For instance,
I'd like to launch every 10ms computations on all cores. These
computations must start at the same time (as synchronized
as possible).

I look for the best way to do it. What I currently have is one timer
(the "local timer") driving one core which in turn triggers mailbox
interrupts on the other (everything on IRQ). The advantage is the
simple timer configuration and the fact that I have all cores in phase.
The disadvantage is that mailbox-based triggering takes some time.

Is there a better way to do it? I was looking into using the
core timers (CNTHPIRQ or CNTPNSIRQ), but its it worth it ?
Will I get better synchronization of the start dates?

Best regards,
Dumitru
dpotop

bzt
Posts: 374
Joined: Sat Oct 14, 2017 9:57 pm

Re: Best way to synchronize timers?

Fri Apr 19, 2019 10:35 am

Hi,

I think the most efficient solution is to issue WFE on the application cores, and use SEV in the local timer ISR on the main core. That's the solution with the smallest latency possible. The downside is, you can only use one randevous point like this, which is good if you have only this single 10ms job.

Main core local timer ISR:

Code: Select all

SVE
BL periodicjob
Application cores:

Code: Select all

again:
WFE
BL periodicjob
B again
This is almost simultaneous, but allows only one job.

If you need to support more functions, then I suggest to use a global variable with prefetch (DDI0487 has an example code for this in appendix K11.3.4, for both AArch32 and AArch64), use the lock variable as a function selector and a "switch" construct on application cores.

Pseudo code for main core local timer ISR to call the periodic job:

Code: Select all

corefunc = DOPERIODICJOB
SVE
periodicjob();
Pseudo code for application processors:

Code: Select all

PRFM PSTL1KEEP, [corefunc]
again:
WFE
switch (corefunc) {
  case DOPERIODICJOB: periodicjob(); break;
  ...
}
goto again
This solution also has a minimal overhead on the application cores, but much less than with the mailbox. It's no more than a few CPU cycles, depending how you implement the "switch" in Assembly. Also note that corefunc does not work as a real lock as described in K11.3, we just use some of the lock related features for it.

Cheers,
bzt

Return to “Bare metal, Assembly language”