From a661949f8a567eae94368a1a988926aedf78827f Mon Sep 17 00:00:00 2001 From: Lourens Naude Date: Thu, 8 Oct 2026 12:59:51 +0100 Subject: [PATCH] boards/arm/imxrt/fmu-v6xrt: Add an rptun configuration for the CM4. The Pixhawk 6X-RT is an RT1176. The rptun configuration registers the CM4 as /dev/rptun/cm4 from the board bring-up with the TCM memory map the LMEM backdoor window allows, maps the shared window non-cacheable and loads the CM4 ELF on rptun start. The image comes from the SD card (CONFIG_FMU_V6XRT_CM4_FIRMWARE) or, with CONFIG_FMU_V6XRT_CM4_ROMFS, from the etc ROMFS built from src/etc/cm4.elf, so no card is needed. The nsh rptun builtin starts and stops the core and rpmsg ping /dev/rpmsg/cm4 exercises the link; syslog goes to a RAM log readable with dmesg. The board page documents the configuration and the uploader. Assisted-by: Claude:claude-fable-5-1 Signed-off-by: Lourens Naude --- .../arm/imxrt/boards/fmu-v6xrt/index.rst | 41 ++++++- Documentation/platforms/arm/imxrt/index.rst | 9 ++ boards/arm/imxrt/fmu-v6xrt/Kconfig | 22 ++++ .../imxrt/fmu-v6xrt/configs/rptun/defconfig | 79 +++++++++++++ boards/arm/imxrt/fmu-v6xrt/src/.gitignore | 3 + boards/arm/imxrt/fmu-v6xrt/src/CMakeLists.txt | 17 +++ boards/arm/imxrt/fmu-v6xrt/src/Makefile | 8 ++ boards/arm/imxrt/fmu-v6xrt/src/fmu-v6xrt.h | 13 +++ .../arm/imxrt/fmu-v6xrt/src/imxrt_bringup.c | 10 ++ boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.c | 106 ++++++++++++++++++ 10 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 boards/arm/imxrt/fmu-v6xrt/configs/rptun/defconfig create mode 100644 boards/arm/imxrt/fmu-v6xrt/src/.gitignore create mode 100644 boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.c diff --git a/Documentation/platforms/arm/imxrt/boards/fmu-v6xrt/index.rst b/Documentation/platforms/arm/imxrt/boards/fmu-v6xrt/index.rst index d7740f5be9b..a8e5b1184da 100644 --- a/Documentation/platforms/arm/imxrt/boards/fmu-v6xrt/index.rst +++ b/Documentation/platforms/arm/imxrt/boards/fmu-v6xrt/index.rst @@ -92,14 +92,16 @@ Installation The toolchain is the same as for every i.MX RT board; see :doc:`the platform page <../../index>`. -Flashing needs ``px_uploader.py`` from the PX4 source tree. The bootloader -enumerates as a USB CDC/ACM device for roughly five seconds after reset, so -start the uploader first and then reset the board: +Flashing uses the uploader from the PX4 source tree, ``Tools/px4_uploader.py``. +PX4 releases before 1.18 ship it as ``px_uploader.py``, without the ``4``, with +the same arguments. The bootloader enumerates as a USB CDC/ACM device for +roughly five seconds after reset, so start the uploader first and then reset +the board: .. code-block:: console $ python Tools/px_mkfw.py --prototype firmware.prototype --image nuttx.bin > nuttx.px4 - $ python Tools/px_uploader.py --port "/dev/serial/by-id/*PX4*" nuttx.px4 + $ python Tools/px4_uploader.py --port "/dev/serial/by-id/*PX4*" nuttx.px4 The uploader expects a ``.px4`` container rather than a raw binary. @@ -113,3 +115,34 @@ The basic NuttShell configuration. The console is USB CDC/ACM, so the shell appears on the same connector used for flashing, at ``/dev/ttyACM0`` on the host. ``/dev/random`` and ``/dev/urandom`` are backed by the CAAM hardware entropy source. + +rptun +----- + +``nsh`` plus the SD card and the RPTUN backend for the CM4 +(``CONFIG_IMXRT_RPTUN``). The board bring-up registers ``/dev/rptun/cm4`` and +holds the core; ``rptun start`` loads the ELF named by +``CONFIG_FMU_V6XRT_CM4_FIRMWARE`` (``/mnt/sd/cm4.elf``) into the CM4 code TCM +and releases it. The image must carry a ``.resource_table`` section and link +to ``0x1ffe0000`` with its shared memory in the upper 64 KB of that TCM; see +the RPTUN section of :doc:`the platform page <../../index>`. + +.. code-block:: console + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sd + nsh> rptun start /dev/rptun/cm4 + nsh> sleep 2 + nsh> rpmsg ping /dev/rpmsg/cm4 100 64 3 0 + nsh> rpmsg dump all + nsh> rptun stop /dev/rptun/cm4 + +Start is asynchronous; the rpmsg node ``/dev/rpmsg/cm4`` appears once the CM4 +has announced its endpoints. ``rpmsg ping`` and ``rpmsg dump`` report through +syslog, which this configuration keeps in a RAM log: read it with ``dmesg``. +After ``rptun stop`` the CM4 is parked in a ``wfi`` loop at its boot address; +the next start reloads the image. + +To run without an SD card, enable ``CONFIG_FMU_V6XRT_CM4_ROMFS`` and copy the CM4 image to +``boards/arm/imxrt/fmu-v6xrt/src/etc/cm4.elf`` before building. It is baked into the etc ROMFS +that NuttX mounts at boot and the firmware path becomes ``/etc/cm4.elf``, so the ``mount`` step +goes away. The file is ignored by git. diff --git a/Documentation/platforms/arm/imxrt/index.rst b/Documentation/platforms/arm/imxrt/index.rst index 285f3330c9b..c430b981f49 100644 --- a/Documentation/platforms/arm/imxrt/index.rst +++ b/Documentation/platforms/arm/imxrt/index.rst @@ -326,6 +326,15 @@ The driver: - Starts the remote from :c:func:`rptun_initialize` when the board sets ``autostart``; otherwise ``RPTUNIOC_START`` on ``/dev/rptun/`` or :c:func:`rptun_boot` starts it. +The ``fmu-v6xrt:rptun`` configuration is the reference user: ``imxrt_cm4_initialize()`` in the board +bring-up registers ``/dev/rptun/cm4`` with the memory map below, maps the shared window non-cacheable +and leaves the core held. Copy an ELF built for the CM4 to the SD card as +``CONFIG_FMU_V6XRT_CM4_FIRMWARE`` (``/mnt/sd/cm4.elf``), then from nsh:: + + mount -t vfat /dev/mmcsd0 /mnt/sd + rptun start /dev/rptun/cm4 + rptun ping /dev/rptun/cm4 100 64 3 0 + Memory map rules the board must follow: - The CM7 reaches the CM4 TCM through the LMEM backdoor window at ``IMXRT_OCRAM_M4_BASE``. Only the diff --git a/boards/arm/imxrt/fmu-v6xrt/Kconfig b/boards/arm/imxrt/fmu-v6xrt/Kconfig index 5c6bd455634..cae2444c7ce 100644 --- a/boards/arm/imxrt/fmu-v6xrt/Kconfig +++ b/boards/arm/imxrt/fmu-v6xrt/Kconfig @@ -35,4 +35,26 @@ config IMXRT1170_FLEXSPI_FRAM depends on IMXRT_FLEXSPI select MTD +config FMU_V6XRT_CM4_ROMFS + bool "Embed the CM4 firmware in the etc ROMFS" + default n + depends on IMXRT_RPTUN + select FS_ROMFS + select ETC_ROMFS + ---help--- + Build boards/arm/imxrt/fmu-v6xrt/src/etc/cm4.elf into the etc + ROMFS that is mounted at boot, so no SD card is needed. The file + is not part of the tree; copy the CM4 image there before building. + +config FMU_V6XRT_CM4_FIRMWARE + string "CM4 firmware path" + default "/mnt/sd/cm4.elf" + depends on IMXRT_RPTUN && !FMU_V6XRT_CM4_ROMFS + ---help--- + ELF image the RPTUN loader writes into the CM4 TCM on + "rptun start /dev/rptun/cm4". It must carry a .resource_table + section and link against the CM4 code TCM at 0x1ffe0000, with + its shared memory in the upper 64 KB of that TCM. With + FMU_V6XRT_CM4_ROMFS the path is /etc/cm4.elf. + endif diff --git a/boards/arm/imxrt/fmu-v6xrt/configs/rptun/defconfig b/boards/arm/imxrt/fmu-v6xrt/configs/rptun/defconfig new file mode 100644 index 00000000000..17c9279d2e7 --- /dev/null +++ b/boards/arm/imxrt/fmu-v6xrt/configs/rptun/defconfig @@ -0,0 +1,79 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_RAMFUNCS is not set +# CONFIG_NSH_DISABLE_DATE is not set +# CONFIG_NSH_DISABLE_MB is not set +# CONFIG_NSH_DISABLE_MH is not set +# CONFIG_NSH_DISABLE_MW is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="fmu-v6xrt" +CONFIG_ARCH_BOARD_FMU_V6XRT=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1176DVMAA=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_ITCM=y +CONFIG_ARM_MPU=y +CONFIG_BINFMT_DISABLE=y +CONFIG_BOARD_INITRNGSEED=y +CONFIG_BOARD_LOOPSPERMSEC=104926 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_CONSOLE=y +CONFIG_CRYPTO=y +CONFIG_CRYPTO_RANDOM_POOL=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_IPC=y +CONFIG_DEBUG_IPC_ERROR=y +CONFIG_DEBUG_IPC_WARN=y +CONFIG_DEV_URANDOM=y +CONFIG_FAT_LFN=y +CONFIG_FS_FAT=y +CONFIG_FS_FATTIME=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_DTCM=0 +CONFIG_IMXRT_ITCM=0 +CONFIG_IMXRT_LPUART1=y +CONFIG_IMXRT_RNG=y +CONFIG_IMXRT_RPTUN=y +CONFIG_IMXRT_USBDEV=y +CONFIG_IMXRT_USDHC1=y +CONFIG_IMXRT_USDHC1_INVERT_CD=y +CONFIG_IMXRT_USDHC1_WIDTH_D1_D4=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_LOCALTIME=y +CONFIG_LINE_MAX=64 +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_USBCONSOLE=y +CONFIG_RAMLOG=y +CONFIG_RAMLOG_BUFSIZE=8192 +CONFIG_RAMLOG_SYSLOG=y +CONFIG_RAM_SIZE=524288 +CONFIG_RAM_START=0x20240000 +CONFIG_RAW_BINARY=y +CONFIG_RPMSG_PING=y +CONFIG_RPTUN=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=249 +CONFIG_SCHED_LPWORK=y +CONFIG_SDIO_BLOCKSETUP=y +CONFIG_START_DAY=14 +CONFIG_START_MONTH=3 +CONFIG_SYSTEM_NSH=y +CONFIG_USBDEV=y diff --git a/boards/arm/imxrt/fmu-v6xrt/src/.gitignore b/boards/arm/imxrt/fmu-v6xrt/src/.gitignore new file mode 100644 index 00000000000..456fdd03d62 --- /dev/null +++ b/boards/arm/imxrt/fmu-v6xrt/src/.gitignore @@ -0,0 +1,3 @@ +/etc/cm4.elf +/etctmp +/etctmp.c diff --git a/boards/arm/imxrt/fmu-v6xrt/src/CMakeLists.txt b/boards/arm/imxrt/fmu-v6xrt/src/CMakeLists.txt index 22596a36b9c..3a2aeebc93d 100644 --- a/boards/arm/imxrt/fmu-v6xrt/src/CMakeLists.txt +++ b/boards/arm/imxrt/fmu-v6xrt/src/CMakeLists.txt @@ -23,8 +23,25 @@ set(SRCS imxrt_boot.c imxrt_flexspi_nor_boot.c imxrt_flexspi_nor_flash.c imxrt_clockconfig.c imxrt_bringup.c) +if(CONFIG_IMXRT_RPTUN) + list(APPEND SRCS imxrt_cm4.c) +endif() + target_sources(board PRIVATE ${SRCS}) +if(CONFIG_FMU_V6XRT_CM4_ROMFS) + nuttx_add_romfs( + NAME + etc + MOUNTPOINT + etc + RCRAWS + etc/cm4.elf + PATH + ${CMAKE_CURRENT_BINARY_DIR}/etc) + target_link_libraries(board PRIVATE romfs_etc) +endif() + if(CONFIG_BOOT_RUNFROMFLASH) set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") elseif(CONFIG_BOOT_RUNFROMISRAM) diff --git a/boards/arm/imxrt/fmu-v6xrt/src/Makefile b/boards/arm/imxrt/fmu-v6xrt/src/Makefile index f11b15bd63a..1ef687f9f31 100644 --- a/boards/arm/imxrt/fmu-v6xrt/src/Makefile +++ b/boards/arm/imxrt/fmu-v6xrt/src/Makefile @@ -31,4 +31,12 @@ else ifeq ($(CONFIG_BOARD_LATE_INITIALIZE),y) CSRCS += imxrt_bringup.c endif +ifeq ($(CONFIG_IMXRT_RPTUN),y) +CSRCS += imxrt_cm4.c +endif + +ifeq ($(CONFIG_FMU_V6XRT_CM4_ROMFS),y) +RCRAWS = etc/cm4.elf +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/imxrt/fmu-v6xrt/src/fmu-v6xrt.h b/boards/arm/imxrt/fmu-v6xrt/src/fmu-v6xrt.h index 09e2401339b..d96b64ce70b 100644 --- a/boards/arm/imxrt/fmu-v6xrt/src/fmu-v6xrt.h +++ b/boards/arm/imxrt/fmu-v6xrt/src/fmu-v6xrt.h @@ -337,5 +337,18 @@ int imxrt_flexspi_nor_initialize(void); int imxrt_flexspi_fram_initialize(void); #endif +/**************************************************************************** + * Name: imxrt_cm4_initialize + * + * Description: + * Register the CM4 as an RPTUN remote (/dev/rptun/cm4) and map its shared + * window non-cacheable. The core is started with "rptun start". + * + ****************************************************************************/ + +#ifdef CONFIG_IMXRT_RPTUN +int imxrt_cm4_initialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_IMXRT_FMU_V6XRT_SRC_FMU_V6XRT_H */ diff --git a/boards/arm/imxrt/fmu-v6xrt/src/imxrt_bringup.c b/boards/arm/imxrt/fmu-v6xrt/src/imxrt_bringup.c index c8aaed2b7ea..2a4f7be8a7e 100644 --- a/boards/arm/imxrt/fmu-v6xrt/src/imxrt_bringup.c +++ b/boards/arm/imxrt/fmu-v6xrt/src/imxrt_bringup.c @@ -168,6 +168,16 @@ int imxrt_bringup(void) nsh_sdmmc_initialize(); #endif +#ifdef CONFIG_IMXRT_RPTUN + /* Register the CM4 as an RPTUN remote; "rptun start" loads and runs it */ + + ret = imxrt_cm4_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: imxrt_cm4_initialize failed: %d\n", ret); + } +#endif + #ifdef CONFIG_IMXRT_LPSPI imxrt_spidev_initialize(); #endif diff --git a/boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.c b/boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.c new file mode 100644 index 00000000000..c1be629cbe0 --- /dev/null +++ b/boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * boards/arm/imxrt/fmu-v6xrt/src/imxrt_cm4.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 + +#include + +#include "arm_internal.h" +#include "mpu.h" +#include "imxrt_rptun.h" +#include "hardware/imxrt_memorymap.h" +#include "fmu-v6xrt.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The CM4 tightly coupled memories as the CM4 sees them (device addresses) + * and as the CM7 reaches them through the LMEM backdoor window (physical + * addresses). Only the code TCM half of the window is reachable, so the + * CM4 image, its resource table, the vrings and the rpmsg buffers all live + * there: code in the lower 64 KB, shared memory in the upper 64 KB. The + * CM4 boots from the backdoor alias; the CM4-native address does not boot. + */ + +#define CM4_CODE_TCM_DA 0x1ffe0000 +#define CM4_SYS_TCM_DA 0x20000000 +#define CM4_TCM_SIZE (128 * 1024) +#define CM4_CODE_TCM_PA IMXRT_OCRAM_M4_BASE +#define CM4_SYS_TCM_PA (IMXRT_OCRAM_M4_BASE + CM4_TCM_SIZE) +#define CM4_SHM_PA (CM4_CODE_TCM_PA + (64 * 1024)) +#define CM4_SHM_SIZE (64 * 1024) + +#ifdef CONFIG_FMU_V6XRT_CM4_ROMFS +# define CM4_FIRMWARE "/etc/cm4.elf" +#else +# define CM4_FIRMWARE CONFIG_FMU_V6XRT_CM4_FIRMWARE +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct rptun_addrenv_s g_cm4_addrenv[] = +{ + { .pa = CM4_CODE_TCM_PA, .da = CM4_CODE_TCM_DA, .size = CM4_TCM_SIZE }, + { .pa = CM4_SYS_TCM_PA, .da = CM4_SYS_TCM_DA, .size = CM4_TCM_SIZE }, + { .size = 0 }, +}; + +static const struct imxrt_rptun_config_s g_cm4_config = +{ + .cpuname = "cm4", + .firmware = CM4_FIRMWARE, + .addrenv = g_cm4_addrenv, + .boot_addr = CM4_CODE_TCM_PA, + .autostart = false, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_cm4_initialize + * + * Description: + * Register the CM4 as /dev/rptun/cm4. The CM4 writes the vrings and the + * rpmsg buffers, so the CM7 must not read them through its D-cache: map + * the shared window Normal, non-cacheable and shareable. The region is + * added after imxrt_mpu_initialize() and therefore wins over the + * cacheable OCRAM_M4 region it overlaps. + * + ****************************************************************************/ + +int imxrt_cm4_initialize(void) +{ + mpu_configure_region(CM4_SHM_PA, CM4_SHM_SIZE, + MPU_RASR_AP_RWRW | MPU_RASR_TEX_NOR | + MPU_RASR_S | MPU_RASR_XN); + + return imxrt_rptun_init(&g_cm4_config); +}