Hello everyone,
First up: In my Yocto build, my goal is to start a firmware on the M4 co-processor (on Verdin AM62) which then created the device /dev/ttyRPMSG0 in userspace, so my application (running on linux) can communicate with the firmware (running on the M4).
A year ago i tried more or less the same thing in TorizonOS (see How to communicate with M4 on the Verdin AM62 through ttyRPMSG)… in the end it worked.
Now I’m setting up a Yocto with the scarthgap-7.x.y BSP from Toradex with a custom image-recipe (based on the tdx-reference-minimal-image). I had to modify my DTO for the M4 a little (in comparison to the TorizonOS DTO), because in k3-am62-mcu.dtsi from the Yocto-BSP the mcu_m4fss note is disabled. So this is my DTO which is applied successfully at system startup:
/*
* Description:
* This overlay confugured the ipc (inter processor communication) between M4F, R5F and Linux.
*/
/dts-v1/;
/plugin/; //Indicates a Device Tree Overlay
/ {
/* Set hardware compatibility */
compatible = "toradex,verdin-am62-nonwifi-dev",
"toradex,verdin-am62-nonwifi",
"toradex,verdin-am62",
"ti,am625";
};
&{/} {
/* memory reservation for ipc mailbox system */
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
ramoops@9c700000 {
compatible = "ramoops";
reg = <0x00 0x9c700000 0x00 0x00100000>;
record-size = <0x8000>;
console-size = <0x8000>;
ftrace-size = <0x00>;
pmsg-size = <0x8000>;
};
/* global cma region */
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x00 0x8000000>;
linux,cma-default;
};
rtos_ipc_memory_region: ipc-memories@9c800000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c800000 0x00 0x00300000>;
no-map;
};
mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9cb00000 0x00 0x100000>;
no-map;
};
mcu_m4fss_memory_region: m4f-memory@9cc00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9cc00000 0x00 0xe00000>;
no-map;
};
wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9da00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9da00000 0x00 0x00100000>;
no-map;
};
wkup_r5fss0_core0_memory_region: r5f-memory@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0x00c00000>;
no-map;
};
};
};
/* inter-processor communication mailbox system configuration */
&mailbox0_cluster0 {
status = "okay";
mbox_m4_0: mbox-m4-0 {
ti,mbox-rx = <0 0 0>;
ti,mbox-tx = <1 0 0>;
};
mbox_r5_0: mbox-r5-0 {
ti,mbox-rx = <2 0 0>;
ti,mbox-tx = <3 0 0>;
};
};
&mcu_m4fss {
status = "okay";
mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
mbox-names = "tx", "rx";
memory-region = <&mcu_m4fss_dma_memory_region>,
<&mcu_m4fss_memory_region>;
firmware-name = "blub.out";
wakeup-source;
};
&wkup_r5fss0_core0 {
mboxes = <&mailbox0_cluster0 &mbox_r5_0>;
memory-region = <&wkup_r5fss0_core0_dma_memory_region>,
<&wkup_r5fss0_core0_memory_region>;
};
These sources are derived from here.
So the problem is, i can start the firmware but the /dev/ttyRPMSG0 isn’t created. Here are some outputs which may be informative.
root@verdin-am62-15479005:~# cat /sys/class/remoteproc/remoteproc0/state
offline
root@verdin-am62-15479005:~# modprobe rpmsg_tty
root@verdin-am62-15479005:~# lsmod |grep rpmsg
rpmsg_tty 16384 0
rpmsg_ctrl 12288 0
rpmsg_char 16384 1 rpmsg_ctrl
virtio_rpmsg_bus 20480 0
rpmsg_ns 16384 1 virtio_rpmsg_bus
rpmsg_core 12288 5 virtio_rpmsg_bus,rpmsg_char,rpmsg_ctrl,rpmsg_tty,rpmsg_ns
root@verdin-am62-15479005:~# dmesg | grep -i rpmsg
[ 8.602715] virtio_rpmsg_bus virtio0: rpmsg host is online
[ 8.603286] virtio_rpmsg_bus virtio0: creating channel ti.ipc4.ping-pong addr 0xd
[ 8.616219] virtio_rpmsg_bus virtio0: creating channel rpmsg_chrdev addr 0xe
root@verdin-am62-15479005:~# cat /sys/module/firmware_class/parameters/path
/etc/company/m4f/
root@verdin-am62-15479005:~# cat /sys/class/remoteproc/remoteproc0/firmware
blub.out
root@verdin-am62-15479005:~# echo "start" > /sys/class/remoteproc/remoteproc0/state
[ 272.429049] remoteproc remoteproc0: powering up 5000000.m4fss
[ 272.449805] remoteproc remoteproc0: Booting fw image blub.out, size 484060
[ 272.467205] rproc-virtio rproc-virtio.6.auto: assigned reserved memory node m4f-dma-memory@9cb00000
[ 272.479756] virtio_rpmsg_bus virtio1: rpmsg host is online
[ 272.485568] rproc-virtio rproc-virtio.6.auto: registered virtio1 (type 7)
[ 272.492491] remoteproc remoteproc0: remote processor 5000000.m4fss is now up
root@verdin-am62-15479005:~# cat /sys/class/remoteproc/remoteproc0/state
running
root@verdin-am62-15479005:~# ls /sys/class/remoteproc/
remoteproc0 remoteproc1 remoteproc2 remoteproc3
root@verdin-am62-15479005:~# cat /sys/class/remoteproc/remoteproc0/name
5000000.m4fss
root@verdin-am62-15479005:~# ls /dev/ttyRPMSG0
ls: cannot access '/dev/ttyRPMSG0': No such file or directory
root@verdin-am62-15479005:~# dmesg | grep -i rpmsg
[ 8.602715] virtio_rpmsg_bus virtio0: rpmsg host is online
[ 8.603286] virtio_rpmsg_bus virtio0: creating channel ti.ipc4.ping-pong addr 0xd
[ 8.616219] virtio_rpmsg_bus virtio0: creating channel rpmsg_chrdev addr 0xe
[ 272.479756] virtio_rpmsg_bus virtio1: rpmsg host is online
As a comparison: If the firmware is started on the TorizonOS i receive the following output (note the last line):
[ 230.446611] remoteproc remoteproc0: powering up 5000000.m4fss
[ 230.447635] remoteproc remoteproc0: Booting fw image blub.out, size 484060
[ 230.451652] rproc-virtio rproc-virtio.6.auto: assigned reserved memory node m4f-dma-memory@9cb00000
[ 230.454073] virtio_rpmsg_bus virtio1: rpmsg host is online
[ 230.454136] rproc-virtio rproc-virtio.6.auto: registered virtio1 (type 7)
[ 230.454146] remoteproc remoteproc0: remote processor 5000000.m4fss is now up
[ 230.459683] virtio_rpmsg_bus virtio1: creating channel rpmsg-tty addr 0xf
The firmware is the exact same firmware which is also used in the TorizonOS setup.
Here are some snippets from the firmware:
main.c
...
status = RPMessage_waitForLinuxReady(SystemP_WAIT_FOREVER);
DebugP_assert(status==SystemP_SUCCESS);
/* Register a callback for the RP_MBOX messages from the Linux remoteproc driver*/
IpcNotify_registerClient(IPC_NOTIFY_CLIENT_ID_RP_MBOX, &ipc_rp_mbox_callback, NULL);
v_ipcDLL_rpmsgCreateRecvEndpoints();
...
ipcDLL.c
...
void v_ipcDLL_rpmsgCreateRecvEndpoints()
{
int32_t status;
RPMessage_CreateParams createParams;
RPMessage_CreateParams_init(&createParams);
createParams.localEndPt = IPC_RPMESSAGE_ENDPT_SU;
//createParams.recvCallback = &v_rpMessageRecCallback;
status = RPMessage_construct(&gIpcRecvMsgObject[0], &createParams);
DebugP_assert(status==SystemP_SUCCESS);
/* We need to "announce" to Linux client else Linux does not know a service exists on this CPU
* This is not mandatory to do for RTOS clients
*/
DebugP_log("Announce RPmessage-endpoint \r\n");
status = RPMessage_announce(CSL_CORE_ID_A53SS0_0, IPC_RPMESSAGE_ENDPT_SU, IPC_RPMESSAGE_SERVICE_SU);
DebugP_assert(status==SystemP_SUCCESS);
}
...
with
#define IPC_RPMESSAGE_SERVICE_SU "rpmsg-tty"#define IPC_RPMESSAGE_ENDPT_SU (15U)
I already tried a lot, searched the web and used some AI but can’t get it to work. So what am I missing?
Thanks in advance ![]()
Kind Regards
Uwe