Apalis M4 and TorizonOS

Hi,

I am still trying to make the Cortex M4 processors work together with TorizonOS on the A-cores. See my previous question: Apalis IMX8 cortex M4 and linux conflict

At the moment I am working with this BSP: 5.4.193-5.7.0-devel+git.90bfeac00dbe because according to other topics, BSP 5.x does work for this purpose. some examples:

I have followed multiple of these posts and made changes to the devicetree according to posts on this forum. I still have the problem that I can start the M4 core via boot (I can see the hello world output looping), but once I start the A-cores, the M4 core seems to stop. I suspect an issue related to a peripheral conflict, but I disabled all relevant uart,pwm,… in my devicetree. I have uploaded a copy of my full dt. Can you see what is still going wrong?

imx8qm-apalis-v1.1-eval.dts (199.3 KB)

best regards

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


Cortex-M4 and Linux Conflict Resolution

Based on the available documentation and community discussions, the issue you’re experiencing where the Cortex-M4 stops when Linux boots is a common problem in Heterogeneous Multicore Processing environments. Here are the key areas to address:

Resource Domain Controller (RDC) Configuration

The Resource Domain Controller is crucial for preventing conflicts between the A-cores and M-cores (1). The RDC controls access to peripherals and memory areas for individual bus masters. By default, both the A7 and M4 cores start in domain 0, but the M4 should be reassigned to domain 1 along with its required peripherals (1).

Device Tree Modifications Required

For proper HMP operation, you need to ensure proper memory buffer allocation for RPMsg communication (2). The device tree overlays must configure:

  • Correct RAM buffer allocation
  • VRING base addresses
  • Resource table memory locations

Critical Linux Kernel Parameters

Recent community reports indicate that on newer TorizonOS versions, you may need to add specific kernel command line arguments to prevent Linux from interrupting the M-core during boot (3). Without these parameters, the Linux kernel can take over the M4 core, causing it to stop functioning.

Peripheral Conflict Resolution

When a peripheral is used by the Cortex-M4, it must be completely disabled in the Linux device tree (1). For any device that should be used on the Cortex-M4 which is also used by the Linux kernel, you must set the status property to disabled in the device tree.

Memory Areas and Linker Configuration

Ensure your firmware is properly linked to run in the appropriate memory area (typically TCM for most examples) (1). The memory addresses used in your U-Boot loading commands must match the addresses specified in your device tree overlay and firmware linker scripts.

Recommended Troubleshooting Steps

  1. Verify M4 Debug Output: Connect to the M4 debug UART to monitor if the firmware continues running after Linux boot
  2. Check RPMsg Initialization: Look for proper RPMsg initialization messages on the M4 side
  3. Review Kernel Messages: Use dmesg | grep -i rpmsg to check for any conflicts or errors
  4. Validate Memory Configuration: Ensure the resource table and VRING addresses match between firmware and device tree

Unfortunately, I cannot review the specific device tree file you’ve uploaded, but the key is ensuring all peripherals used by the M4 are properly disabled in the Linux device tree and that the memory regions are correctly configured for RPMsg communication.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Hi @Jens0501!

How are you checking if the Cortex M4 stopped? If you are not seeing the loop in the serial console, it doesn’t necessarily mean that the M4 stopped.

What could be happening is: the A-core is attaching this UART and, because of that, you stop seeing the loop, but it is still running in the background. I personally faced this before, and what I did was disable the UART used by the Cortex M4 in the device tree (as shown in this example), so the A-core wouldn’t attach it, allowing me to keep seeing the loop after Linux boot.

Besides that, are you using overlays for your modifications, or are you modifying the device tree directly?

Best regards.

Hi @lucas_az.tx,

I tried to disable all UARTs (even the ones that are not used at all by the M4) in the devicetree and I still get the same behaviour.

I am modifying the devicetree directly since I have more experience with this. According to the overlay below, all I would need to change are the UART control pins (which I did). But this doesn’t change anything:

/dts-v1/;
/plugin/;

/* Disable UART1 Control Pins to use M4 Core 0 and 1 UART */

/ {
    compatible = "toradex,apalis-imx8";
};

&iomuxc {
    pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
            <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
            <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,
            <&pinctrl_gpio_usbh_oc_n>,
            <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
            <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
            <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,
            <&pinctrl_sata1_act>, <&pinctrl_sim0_gpios>,
            <&pinctrl_usdhc1_gpios>;
};

I also cannot get remoteproc to work to check the status of the M-cores or stop/start them

Best regards

Hi @Jens0501!

Could you please try the following overlay? It is not official, since it is still a work in progress and will probably be updated.

That being said, we can’t offer much support with it, as it hasn’t been tested, and I’m not sure if it is even working properly. Although it may contain some useful information that can help you.

To compile and use the overlay, you can follow this article.

Best regards.

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
 * Copyright 2023 Toradex
 */

// Enable RPMSG support for Apalis iMX8

/dts-v1/;
/plugin/;

/ {
	compatible = "toradex,apalis-imx8-v1.1",
		     "toradex,apalis-imx8";
};

&{/} {
	#address-cells = <2>;
	#size-cells = <2>;

	reserved-memory {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		rpmsg0mem: rpmsg0mem@90000000 {
			compatible = "shared-dma-pool";
			reg = <0 0x90000000 0 0x20000>;
			no-map;
		};
		rpmsg1mem: rpmsg1mem0@90100000 {
			compatible = "shared-dma-pool";
			reg = <0 0x90100000 0 0x20000>;
			no-map;
		};
		vdev0buffer: vdevbuffer@90400000 {
                        compatible = "shared-dma-pool";
			reg = <0 0x90400000 0 0x100000>;
			no-map;
		};
	};

	rpmsg@90000000 {
		compatible = "fsl,imx8qm-rpmsg";
		reg = <0 0x90000000 0 0x20000>;
		mbox-names = "tx", "rx", "rxdb";
		mboxes = <&lsio_mu5 0 1
			  &lsio_mu5 1 1
			  &lsio_mu5 3 1>;
		mub-partition = <3>;
		vdev-nums = <2>;
	};

	rpmsg@90100000 {
		compatible = "fsl,imx8qm-rpmsg";
		reg = <0 0x90100000 0 0x20000>;
		mbox-names = "tx", "rx", "rxdb";
		mboxes = <&lsio_mu6 0 1
			  &lsio_mu6 1 1
			  &lsio_mu6 3 1>;
		mub-partition = <4>;
		vdev-nums = <2>;
	};
};

&iomuxc {
	pinctrl-0 = <&pinctrl_cam1_gpios>, <&pinctrl_dap1_gpios>,
		    <&pinctrl_esai0_gpios>, <&pinctrl_fec2_gpios>,
		    <&pinctrl_gpio3>, <&pinctrl_gpio4>, <&pinctrl_gpio_keys>,
		    <&pinctrl_gpio_usbh_oc_n>,
		    <&pinctrl_lvds0_i2c0_gpio>, <&pinctrl_lvds1_i2c0_gpios>,
		    <&pinctrl_mipi_dsi_0_1_en>, <&pinctrl_mipi_dsi1_gpios>,
		    <&pinctrl_mlb_gpios>, <&pinctrl_qspi1a_gpios>,
		    <&pinctrl_sata1_act>, <&pinctrl_sim0_gpios>,
		    <&pinctrl_usdhc1_gpios>;
};

/*
 * NXP SDK for Cortex-M4 core 0 uses the UART2 as default debugging UART, so
 * this interface needs to be disabled to prevente conflicts in the Cortex-A
 * side.
 */

  

  
&lpuart2 {
	status = "disabled";
};

/*
 * NXP SDK for Cortex-M4 core 1 uses UART0_RTS_B and UART0_CTS_B pins
 * as default Cortex-M debugging UART. These pins are assigned as
 * LSIO.PWM0.OUT and LSIO.PWM1.OUT on Toradex modules by default,
 * therefore they need to be disable to prevent conflicts.
 */

  

  
&lsio_pwm0 {
	status = "disabled";
};

&lsio_pwm1 {
	status = "disabled";
};