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 <lourens@bearmetal.eu>
This commit is contained in:
Lourens Naude 2026-10-08 12:59:51 +01:00 • committed by Xiang Xiao
parent 5dcaf8ace8
commit a661949f8a
10 changed files with 304 additions and 4 deletions

View file

@ -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.

View file

@ -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/<name>`` 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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,3 @@
/etc/cm4.elf
/etctmp
/etctmp.c

View file

@ -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)

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <nuttx/rptun/rptun.h>
#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);
}