This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7c6307bebf6c81055b5bc9bb12bb23f1e0fdb17b
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 8 21:57:36 2026 +0200

    arch/arm64/qemu: Use the PL031 RTC of the virt machine.
    
    The QEMU virt machine has a PL031 RTC at 0x09010000 (SPI 2), which QEMU
    sets from the host clock.  qemu-armv8a did not register it, so the
    system time started at CONFIG_START_YEAR, and files on a host share
    (v9fs, hostfs) had times years in the future.
    
    With CONFIG_RTC_PL031, up_rtc_initialize() now registers the PL031 as
    the RTC, so the system time starts at the host's time.
    
    The new option QEMU_RTC_PL031_SYNC makes the boot wait (up to a second)
    for the RTC second to change.  The PL031 counts whole seconds, so
    without the wait the time starts up to a second behind the host.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 arch/arm64/src/qemu/CMakeLists.txt |  3 ++
 arch/arm64/src/qemu/Kconfig        | 25 ++++++++++++++
 arch/arm64/src/qemu/Make.defs      |  4 +++
 arch/arm64/src/qemu/qemu_rtc.c     | 69 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 101 insertions(+)

diff --git a/arch/arm64/src/qemu/CMakeLists.txt 
b/arch/arm64/src/qemu/CMakeLists.txt
index 141673930a1..05c43928518 100644
--- a/arch/arm64/src/qemu/CMakeLists.txt
+++ b/arch/arm64/src/qemu/CMakeLists.txt
@@ -30,4 +30,7 @@ endif()
 if(CONFIG_PM)
   list(APPEND SRCS qemu_initialize.c)
 endif()
+if(CONFIG_RTC_PL031)
+  list(APPEND SRCS qemu_rtc.c)
+endif()
 target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm64/src/qemu/Kconfig b/arch/arm64/src/qemu/Kconfig
index 668b9c564d9..89e0b4b6b2a 100644
--- a/arch/arm64/src/qemu/Kconfig
+++ b/arch/arm64/src/qemu/Kconfig
@@ -47,4 +47,29 @@ config ARCH_CHIP_QEMU_WITH_HV
 
 endmenu # "Qemu Chip Selection"
 
+config QEMU_RTC_PL031_BASE
+       hex "PL031 RTC base address"
+       default 0x09010000
+       depends on RTC_PL031
+       ---help---
+               Physical address of the PL031 RTC of the QEMU virt machine.
+
+config QEMU_RTC_PL031_IRQ
+       int "PL031 RTC interrupt"
+       default 34
+       depends on RTC_PL031
+       ---help---
+               Interrupt of the PL031 RTC of the QEMU virt machine (SPI 2).
+
+config QEMU_RTC_PL031_SYNC
+       bool "Start the system time at an RTC second boundary"
+       default n
+       depends on RTC_PL031
+       ---help---
+               The PL031 counts whole seconds, so the system time starts up to 
a
+               second behind the host.  Files that the host writes then look
+               up to a second in the future, and make warns about clock skew.
+               With this option the boot waits (up to a second) for the RTC
+               second to change, so the time is correct to a few milliseconds.
+
 endif # ARCH_CHIP_QEMU
diff --git a/arch/arm64/src/qemu/Make.defs b/arch/arm64/src/qemu/Make.defs
index 83c77512f22..da73b158d87 100644
--- a/arch/arm64/src/qemu/Make.defs
+++ b/arch/arm64/src/qemu/Make.defs
@@ -36,3 +36,7 @@ endif
 ifeq ($(CONFIG_PM),y)
 CHIP_CSRCS += qemu_initialize.c
 endif
+
+ifeq ($(CONFIG_RTC_PL031),y)
+CHIP_CSRCS += qemu_rtc.c
+endif
diff --git a/arch/arm64/src/qemu/qemu_rtc.c b/arch/arm64/src/qemu/qemu_rtc.c
new file mode 100644
index 00000000000..6c91e317f33
--- /dev/null
+++ b/arch/arm64/src/qemu/qemu_rtc.c
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * arch/arm64/src/qemu/qemu_rtc.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/pl031.h>
+#include <nuttx/timers/rtc.h>
+#include <nuttx/timers/arch_rtc.h>
+
+#include "arm64_internal.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_rtc_initialize
+ *
+ * Description:
+ *   Register the PL031 RTC of the QEMU virt machine.  QEMU sets it from the
+ *   host clock (-rtc base=utc by default), so the system time starts at the
+ *   host's time.
+ *
+ ****************************************************************************/
+
+int up_rtc_initialize(void)
+{
+  FAR struct rtc_lowerhalf_s *lower;
+
+#ifdef CONFIG_QEMU_RTC_PL031_SYNC
+  /* The PL031 counts whole seconds, so the system time would start up to a
+   * second late.  Wait until the second changes: the time read next is
+   * then correct to a few milliseconds.  Register 0 is the data register.
+   */
+
+  uint32_t second = getreg32(CONFIG_QEMU_RTC_PL031_BASE);
+
+  while (getreg32(CONFIG_QEMU_RTC_PL031_BASE) == second);
+#endif
+
+  lower = pl031_initialize(CONFIG_QEMU_RTC_PL031_BASE,
+                           CONFIG_QEMU_RTC_PL031_IRQ);
+  up_rtc_set_lowerhalf(lower, true);
+  return rtc_initialize(0, lower);
+}

Reply via email to