iMX7D 5.4.x kernel. Launching M4 FW using remoteproc

Hi @gustavo.tx,

I found something weird. 4.14 kernel or 5.x - the same issue. Modifying 4.14 Kconfig files I made imx_rpmsg driver loadable, put printk’s to trace MU driver and imx_rpmsg calls. Issue is somewhat fuzzy behaving device tree. I don’t know, but if cat /sys/firmware/devicetree/../rpmsg/status gives disabled, then even don’t try launching M4 from Linux, RPMSG won’t work. If status is OK, then starting M4 by m4fwloader, JTAG debugger, perhaps remoteproc as well should make RPMSG working, no matter is imx_rpmsg loaded before launching M4 or after.

The problem is something flips rpmsg DT status in /sys/firmware from okay to disabled.

Without doing any changes to DT, using the same *.dtb file, one time /sys status matches DT and is okay, and another time it doesn’t match DT and is disabled:

  1. Loading M4 FW and then issuing bootaux - makes imx_rpmsg /sys status okay.

  2. Not loading M4 FW after reset and just issuing to uninitialized memory bootuax 80800000 - makes imx_rpmsg /sys status okay again :-).

  3. Not touching bootaux, using JTAG debugger without any cool Linux kernel support or something, setting HW breakpoint at /init/main.c start_kernel() routine, reaching that breakpoint (so it stops for a while), then continuing executing … makes imx_rpmsg /sys status okay again. :slight_smile:

  4. Not using bootaux or JTAG renders /sys/firmware/devicetree/../rpmsg/status disabled. Since disabled, driver isn’t probed, which gives no chance to get RPMSG working launching M4 from Linux.

I’m picking main hair why it is so. Made many different searches though kernel sources to find what could render imx_rpmsg status disabled, no results yet.

Any advice how to figure why status could flip from okay in dtb to disabled in /sys? p4 above suggests something like missing cache flush, missing sync barrier, broken RAM, etc.

Loading dtb file in U-Boot and inspecting DT settings using fdt list and fdt print confirms okay. But Linux sometimes doesn’t agree with this.


Hi @gustavo.tx,

Well, I have workaround for oddities mentioned in my previous message. In short, for some odd reasons Linux may flip status of first rpmsg device from okay to disabled. My workaround is to disable first rpmsg instance and create new one. Renaming first instance didn’t work, mystery. Let me give you some details, which may help understanding better or reproducing.

  1. Teziying latest stable: TDX Wayland with XWayland 5.1.0+build.4 (dunfell) colibri-imx7 ttymxc0 Colibri-iMX7_Reference-Minimal-Image
  2. Not touching everything and not bootaux’ing M4 FW, original imx7d-colibri-eval-v3.dtb
  3. Check what’s inside dtb:
  4. Disabling first rpmsg, adding second rpmsg, reserving memory for vring:
    diff --git a/imx7d-colibri-eval-v3.dts~ b/imx7d-colibri-eval-v3.dts
    index 3d2b48e..9af58c9 100644
    --- a/imx7d-colibri-eval-v3.dts~
    +++ b/imx7d-colibri-eval-v3.dts
    @@ -49,8 +49,48 @@
            compatible = "toradex,colibri-imx7d-eval-v3",
    +       reserved-memory {
    +               #address-cells = <1>;
    +               #size-cells = <1>;
    +               ranges;
    +               rpmsg-vrings@0x8fff0000 {
    +                       compatible = "shared-dma-pool";
    +                       reg = <0x8fff0000 0x10000>;
    +                       no-map;
    +               };
    +       };
    +       soc {
    +               rpmsg1 {
    +                       vdev-nums = <1>;
    +                       reg = <0x8fff0000 0x10000>;
    +                       status = "okay";
    +                       compatible = "fsl,imx7d-rpmsg";
    +                       /* up to now, the following channels are used in imx rpmsg
    +                       * - tx1/rx1: messages channel.
    +                       * - general interrupt1: remote proc finish re-init rpmsg stack
    +                       *   when A core is partition reset.
    +                       */
    +                       mbox-names = "tx", "rx", "rxdb";
    +                       mboxes = <&mu 0 1
    +                               &mu 1 1
    +                               &mu 3 1>;
    +               };
    +       };
    +/* defined in imx7s.dtsi, disabled. Reenabled and specified VRING address
    +   in imx7-colibri.dtsi.
    +    Disabled it and redefine new instance
    +&rpmsg {
    +       status = "disabled";
     &usbotg2 {
            vbus-supply = <&reg_usbh_vbus>;
            status = "okay";
  1. Check dtb:
  2. Result, 2nd rpmsg instance visible to Linux:

Since status is OK, imx_rpmsg driver can be successfully probed. I was able to launch M4 from Linux and got RPMSG working. Remoteproc should work as well, will check later

Hi @gustavo.tx,

OK, it turns out that guilty for these issues is U-Boot. It checks if M4 was started or just attempted to start and disables in DT “fsl,imx7d-rpmsg”.

Here’s excerpt from u-boot-2020.07/u-boot-toradex/board/toradex/colibri_imx7/colibri_imx7.c:

int ft_board_setup(void *blob, bd_t *bd)
	int up;

	up = arch_auxiliary_core_check_up(0);
	if (up) {
		int ret;
		int areas = 1;
		u64 start[2], size[2];

		 * Reserve 1MB of memory for M4 (1MiB is also the minimum
		 * alignment for Linux due to MMU section size restrictions).
		start[0] = gd->bd->bi_dram[0].start;
		size[0] = SZ_256M - SZ_1M;

		/* If needed, create a second entry for memory beyond 256M */
		if (gd->bd->bi_dram[0].size > SZ_256M) {
			start[1] = gd->bd->bi_dram[0].start + SZ_256M;
			size[1] = gd->bd->bi_dram[0].size - SZ_256M;
			areas = 2;

		ret = fdt_set_usable_memory(blob, start, size, areas);
		if (ret) {
			eprintf("Cannot set usable memory\n");
			return ret;
	} else {
		int off;

		off = fdt_node_offset_by_compatible(blob, -1,
		if (off > 0)
			fdt_status_disabled(blob, off);

Please remove removal of imx7d-rpmsg device from DT!


Hi @Edward

Perfect that you found the solution. Thanks for the feedback.

Best regards,

Hi @Edward

Did you get the rpmsg and rproc to work together? Can you share the entrees in the DT?


Current U-Boot 2020.07, just checked it in, still disables RPMSG unless M4 is started from U-Boot. See fdt_status_disabled(blob, off) call in my May 5 answer. You need to fix it first and only then expect RPMSG working starting M4 from Linux using imx_m4fwloader or rproc. iMX7 rproc as I understand got broken after FSL or someone else added support for iMX8. Yes, I made it working, but code is too dirty hack to share.

Thank you for the update. We are planning on running a small initialization app on M4 from U-Boot and loading the main app on m4 from Linux. But I will probably use your work around to prevent that from being an issue anyway.


see attached two diffs. One fixes rproc loader crash loading uninitialized elf segments or something like that. Another one makes MU unit mailboxes optional for rproc, like it was in older kernel. Without this patch I don’t know how to make both rpmsg and rproc happy sharing MU. Presence of mailbox-names property determines will rproc use MU or not. With patch applied you need something like that in DTB to make it working:

/ {


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

		rpmsg_vrings: vrings0@0x8ff00000 {
//			compatible = "shared-dma-pool";
			reg = <0x8ff00000 0x100000>;

		cm4sramcode: cm4sramcode@0x900000 {
			compatible = "shared-dma-pool";
			reg = <0x00900000 0x40000>;

		cm4tcmcode: cm4tcmcode@0x7f8000 {
			compatible = "shared-dma-pool";
			reg = <0x007f8000 0x8000>;


/* I'm not sure regarding syscon, perhaps not required, can't retest by now */
	imx7d-cm4 {
		compatible = "fsl,imx7d-cm4", "syscon";
		clocks =  <&clks IMX7D_ARM_M4_ROOT_CLK>;


		syscon = <&src>;

/*		mbox-names = "tx", "rx", "rxdb", "txdb";
		mboxes = <&mu 0 1
			  &mu 1 1
			  &mu 3 1
			  &mu 2 1>;
		memory-region = <&cm4sramcode>, <&cm4tcmcode>;

&rpmsg {
	memory-region = <&rpmsg_vrings>;

Hope I didn’t miss required change.


@Edward the mailboxes and vrings are the two issues I have been struggling.

Can you re-upload the files, they are showing as missing when I try to download them.


@CMR, perhaps try downloading again. Download is working from Edge on PC and Chrome on Android. If still not, then please ask Toradex why you can’t download them.

@Edward hi, Thanks for answering. My board is technexion imx7d-pico (with carrier board). In it I run Yocto dunfell with kernel 5.6.xx and libgpiod v 1.5.

I talk about libgpiod because my project is as follows: Press a button/Gpio on the breadboard on the linux side (a7) and turn on a led/Gpio that is being controlled on the freertos side (m4).

At first I thought of using RPmsg for this. I don’t know if it’s possible, as I don’t want to abandon the linux mainline due to libgpiod v1.5

Could you help


Yes, RPMSG is the right way to establish communications between A7 running Linux and M4. gpiolib here is absolutely the least important thing. Since it seems you haven’t even launched any rpmsg demo, why are you asking about remoteproc??? Remoteproc has some issues using current kernel drivers. I know no way to to use it without driver mods. What mods I used I wrote above.

You should just go ahead to launch any rpmsg example, so that something on Linux side sends something using rpmsg to M4 side, and M4 recognizes it and reacts appropriately. Then you do your own protocol to command M4 from Linux to drive those LEDs.

You may start reading this:
FreeRTOS on the Cortex-M4 of a Colibri iMX7 (

Since you are using different kernel than we use with Toradex SOMs, it is up to you to figure out how to let your kernel enable RPMSG. It is up to you as well to figure out how to launch M4 firmware on your pico-imx7d.


@Edward Youd said: why are you asking about remoteproc???

1) Because I didn’t find anything ready using RPmsg in mainline linux (I’ll talk below).
1.2) What do I need to do to show devices in /sys/class/remoteproc/ on my imx7d-pico with Yocto dunfell?

2) What version of linux are you using from Toradex in SOM?
As long as it is higher than 5.5 (because of libgpiod) or even a little lower) I ask you to pass me all the changes you made (here I use make menuconfig, where everything was already enabled from rpmsg and remoteproc) to be able to use RPmsg

  1. no, you don’t need imx_rproc to make RPmsg working. RPmsg is what you need to establish communications between Linux and M4. Remoteproc is just one of the ways to launch M4 firmware.
    1.2) for remoteproc you need imx_rproc driver and properly configured kernel device tree.

  2. Toradex kernel

I am currently focusing my efforts on: OpenAmp-RPmsg in linux (Yocto-dunfell/mainline linux) part AND RPmsg-lite in Zephyr Part. But the meta-openamp layer is not yet ready for Yocto/dunfell and has stopped project progress:

@Edward Hi, Please help: I stay trying this a long 1 month: GitHub - TechNexion/freertos-tn at freertos_1.0.1_imx7d

I have issue in line: fatload mmc 0:1 0x7F8000 hello_world.bin

Technexion no longer talks to me due to hardware issues they provided.

Second way out of my problem (which is to run RPMsg on linux and m4 and not just on U-boot):

Enable remoteproc (/linux/remoteproc.h and /sys/class/remoteproc still don’t appear)

In the link above are my device tree files. Mainly the one related to m4: technexion1/imx7d-pico-pi-qca-m4.dts at master · neuberfran/technexion1 · GitHub

@Edward My dmesg (issues in imx7d-pico) is:

imx-rpmsg 30800000.bus:rpmsg: No vring buffer

imx-rpmsg: probe of 30800000.bus:rpmsg failed with error -12


If you can’t load M4 code to RAM in U-Boot, then your further DT file and dmesg are irrelevant.

Why don’t you just provide fatload command output here instead of 3rd party url???

=> fatload mmc 0:1 0x7F8000 hello_world.bin (with issue) 
   ** Reading file would overwrite reserved memory **
   Failed to load 'hello_world.bin 

How big is your bin file? It should be <=32k to fit TCML.
Since you are using imx7d-pico, I think you are using different U-Boot, not the same like we are using on Colibri. Does mw.l fail as well writing to the same TCML area? If mw.l succeds then I don’t see why fatload could complain:

Colibri iMX7 # mw.l 0x7f8000 0x11223344
Colibri iMX7 # md.l 0x7f8000
007f8000: 11223344 bded4ded ff6ec9f2 623e4f68    D3"..M....n.hO>b
007f8010: 6c8e79db 73bfffd2 5dffdb8f fbc6e25d    .y.l...s...]]...
007f8020: ebcc54f5 b7ff26ff f2ebeaaf ef7faf69    .T...&......i...
007f8030: bb5df39d 573efab1 e5c56c2e efbfffe6    ..]...>W.l......
Colibri iMX7 #

If it fails, perhaps try using OCRAM for code instead of TCML. Check if it’s possible with fatload load address 0x910000. mw.l shoudn’t complain as well:
mw.l 0x910000 0x11223344

1 Like



  1. Why don’t you just provide fatload command output here instead of 3rd party url???

A: Because in 3rd party url have more informations

  1. Answer: hello_world.bin have only 12k

U-Boot 2021.04-AUTOINC+g3930a84e3a (Feb 07 2022 - 03:13:45 +0000)

Hit any key to stop autoboot: 0
=> fatload mmc 0:1 0x910000 hello_world.bin
** Reading file would overwrite reserved memory **
Failed to load ‘hello_world.bin’

=> mw.l 0x7f8000 0x11223344
=> md.l 0x7f8000
007f8000: 11223344 a71c43f5 5d38a600 f0475006 D3"…C…8].PG.
007f8010: 05513769 49c06177 1602b728 534e7401 i7Q.wa.I(…tNS
007f8020: ba553251 f95830de d426c50a e82ea4a5 Q2U…0X…&…
007f8030: fea4428c 87126808 026a6403 fca2a0ff .B…h…dj…
007f8040: 4623a7e7 12abb4ea 712f24db 35c3036e …#F…$/qn…5
007f8050: 83a72f18 c483706b cc11f03e 5fbdd68c ./…kp…>…_
007f8060: 8b796732 46de2cb0 8a73d735 25c2fc70 2gy…,.F5.s.p…%
007f8070: 3d876ab6 b334c46d 2fcbe30b f25d697f .j.=m.4…/.i].
007f8080: 767acbc3 3c0282f6 c210f116 ed9757b4 …zv…<…W…
007f8090: 089a43d0 b894a352 21a32d5a bb5c8071 .C…R…Z-.!q..
007f80a0: c781840a ac58d684 c560d8d2 cc85a15a …X…`.Z…
007f80b0: 9e8922d0 e61496b3 6db6b285 32f358c8 ."…m.X.2
007f80c0: 440cbe73 c1e357f9 334689bd f4f899c6 s…D.W…F3…
007f80d0: 4a660f97 e8167313 6d36c4c6 38696801 …fJ.s…6m.hi8
007f80e0: 49405548 f7372f3e 66e6dce4 18b9beff HU@I>/7…f…
007f80f0: a76a9680 d4adee37 332a5471 1e09dce2 …j.7…qT*3…

Why are you using BIN file instead of ELF? (BIN is only required for imxfwloader on Linux.) You may fatload ELF to anywhere in RAM, bootaux should copy required ELF segments to required target locations.

1 Like