Skip to content

Add support for ARM architected timer #20175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

carlocaione
Copy link
Collaborator

@carlocaione carlocaione commented Oct 27, 2019

cc @stephanosio @bbolen @timork @vladimir-podbrezsky

This is the ARM architected timer driver. This has been tested on my ARMv8 / AArch64 working branch (using the QEMU virt platform) and it is working fine.

BTW this depends on #19860

ARM cores may have a per-core architected timer, which provides per-cpu
timers, attached to a GIC to deliver its per-processor interrupts via
PPIs. This is the most common case supported by QEMU in the virt
platform.

This patch introduces support for this timer abstracting the way the
timer registers are actually accessed. This is needed because different
architectures (for example ARMv7-R vs ARMv8-A) use different registers
and even the same architecture (ARMv8-A) can actually use different
timers (ELx physical timers vs ELx virtual timers).

So we introduce the common driver here but the actual SoC / architecture
/ board must provide the three helpers (arm_arch_timer_set_compare(),
arm_arch_timer_toggle(), arm_arch_timer_count()) using an header file
imported through the arch/cpu.h header file.

Signed-off-by: Carlo Caione <[email protected]>
@stephanosio
Copy link
Member

@carlocaione Would it be possible for you to write some tests for these (GIC and generic timer) running on qemu (possibly qemu_cortex_r5, which is Zynq)?

I think one of the major barriers to getting these merged is that there is no way for third parties to verify that these are actually functional as intended.

Copy link
Member

@stephanosio stephanosio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__STATIC_FORCEINLINE uint64_t __get_CNTPCT(void)

CMSIS-Core(A) provides the same set of functions, so no shim of any sort would be required. CMSIS-Core(A) can be added to the repository in the future if necessary as well. As for ARMv8-A, we could either patch CMSIS-Core(A), or write a separate driver header that maps to CMSIS Generic Timer-related functions. Nevermind, it turns out AArch64 is doing something otherworldly.

@stephanosio
Copy link
Member

@carlocaione I just tried running this on qemu_cortex_r5 (xilinx_zynqmp) and found that it is unable to boot (faults at 0x3928 = Generic Timer CP15 configuration instruction).

z_arm_fault: exc_return = 0x00003928
E: >>> ZEPHYR FATAL ERROR 0: CPU exception
E: Current thread: 0x00005e60 (unknown)
E: Halting system

So I took a quick glance at the Zynq UltraScale+ TRM, and it seems like the RPU (Cortex-R5) does not implement Generic Timer (which also aligns with my previous knowledge that, for ARMv7, Generic Timer is only available on Cortex-R7 and -R8). Only APU implements Generic Timer and other arch timers (private timer and global timer).

Am I looking at wrong docs or have you not tested this?!

@carlocaione
Copy link
Collaborator Author

carlocaione commented Oct 28, 2019

Am I looking at wrong docs or have you not tested this?!

As I wrote in the commit message I tested this on my ARMv8 (AArch64) branch where it works fine. The Cortex-R commit wast not tested and just to explain how to hookup the helpers, we can not merge that. On ARMv8 I'm of course using different helpers.

@carlocaione
Copy link
Collaborator Author

@stephanosio I'm going to drop the Cortex-R commit, so we can discuss on the generic driver only.

@stephanosio
Copy link
Member

@carlocaione Just wondering- have you tried running the following tests with this driver?

tests/timer/timer_monotonic
tests/timer/timer_api

I tried to see if I can get it to work using the arm64_clean branch on your fork, but compilation fails with the following error:

/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/../lib/gcc/aarch64-elf/8.3.0/../../../../aarch64-elf/bin/ld: zephyr/subsys/testsuite/ztest/libsubsys__testsuite__ztest.a(ztest.c.obj): in function `k_thread_create':
/home/stephanos/Dev/zephyr-public/zephyr/tests/kernel/timer/timer_monotonic/build_ca53/zephyr/include/generated/syscalls/kernel.h:81: undefined reference to `z_impl_k_thread_create'
/home/stephanos/Dev/zephyr-public/zephyr/tests/kernel/timer/timer_monotonic/build_ca53/zephyr/include/generated/syscalls/kernel.h:81:(.text.z_ztest_run_test_suite+0x120): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `z_impl_k_thread_create'collect2: error: ld returned 1 exit status

@carlocaione
Copy link
Collaborator Author

carlocaione commented Oct 28, 2019

I tried to see if I can get it to work using the arm64_clean branch on your fork, but compilation fails with the following error:

OMG, that is definitely not a branch to use and definitely not to be public. Forgot to make it private. I'm currently cleaning it up. Sorry you had to look at that code :)

Anyway if you want that branch to compile use MULTITHREADING=y.

And yes, actually those tests have problems with the driver. Weird. The basic test case I was using was working fine. I probably rushed this driver. Let me close this PR and rework this better to not waste anyone else time on this.

@carlocaione carlocaione deleted the arm_arm_timer branch November 12, 2019 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants