![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
RPMsg character device RPMsg name service
Header: **components/drivers/include/drivers/rpmsg.h**. Core bus: **components/drivers/rpmsg/rpmsg.c**.
RPMsg is an endpoint-oriented IPC bus on top of a transport (VirtIO + shared memory + mailbox in the in-tree example). The core matches **struct rt_rpmsg_device** to **struct rt_rpmsg_driver** by **id.name**, then manages endpoints (name + src/dst addresses) and **send** via **struct rt_rpmsg_ops**.
| Layer | File | Role |
|---|---|---|
| RPMsg bus | **rpmsg/rpmsg.c** | Endpoints, match **rpmsg-char** / **rpmsg-name-service** |
| VirtIO RPMsg device | **virtio/virtio-rpmsg.c** | **rt_rpmsg_ops**, virtqueues, NS announce |
| AMP transport | **rpmsg/rpmsg-rt-thread-virtio.c** | Shared mem, mailbox doorbell, VirtIO transport |
| Class drivers | **rpmsg_char.c**, **rpmsg_ns.c** | Char devices + name service |
Kconfig: **RT_USING_RPMSG**, **RT_RPMSG_RT_THREAD_VIRTIO** (default y), **RT_RPMSG_CHAR_***.
This is the reference integration in-tree: **rpmsg-rt-thread-virtio.c** + **virtio-rpmsg.c**.
| Piece | DT / code | Role |
|---|---|---|
| Shared memory | **shmem = <&soc_sram>** | Descriptor rings + virtio buffers + link registers at base |
| Mailbox | **mboxes = <&mbox N>** | **RPMSG_VIRTIO_EVENT_LINK** (exchange queue pointers) and **EVENT_QUEUE** (kick) |
**queue-max** | Both sides must match | Virtqueue depth |
**master / slave** | Property on node | Master publishes queue offsets; slave reads peer TX ring for RX |
Boot role: **rpmsg.mode=master** or **slave** in **/chosen bootargs** (INIT_CORE_EXPORT rpmsg_mode_setup in **rpmsg.c**). Must match firmware on the other core. **virtio_rpmsg_probe** swaps RX/TX queue indices for slave vs master.
Remote side (conceptually):
After both sides probe: master writes **MASTER_QUEUE_*** offsets; **EVENT_LINK** makes slave map **peer_tx_virtq** and process inbound RPMsg frames.
**RT_PLATFORM_DRIVER_EXPORT(rpmsg_virtio_driver)** — does not register **rt_rpmsg_device** itself.
**rpmsg_virtio_probe** checklist:
rt_mbox_request_by_index(&mbox_client, 0)** — **rx_callback = rpmsg_virtio_rx_callback**shmem**, **rt_ioremap_cached**master** property → **is_master**, feature **VIRTIO_RPMSG_F_NS** only on masterrt_slab_init** on half of shmem (DMA buffers for virtqueues)rt_dma_device_set_ops** — copy to/from shmem for non-coherent AMPrt_virtio_device**: **VIRTIO_DEVICE_ID_RPMSG**, **rpmsg_virtio_trans**rt_virtio_device_register(vdev)** → triggers **virtio_rpmsg_probe**Mailbox ISR (rpmsg_virtio_rx_callback):
EVENT_LINK**: peer published descriptor ring addresses — wire **peer_tx_virtq**EVENT_QUEUE**: **rt_virtqueue_isr** for local virtqueuesused** index update (feeds virtio RX path)**RT_VIRTIO_DRIVER_EXPORT(virtio_rpmsg_driver)**
**virtio_rpmsg_probe**:
| Op | **virtio_rpmsg behavior** |
|---|---|
**create_endpoint** | Local: optional NS CREATE message to **RT_RPMSG_NS_ADDR**. Remote-created: **src == RT_RPMSG_ADDR_ANY** |
**destroy_endpoint** | Optional NS DESTROY |
**send** | Build **struct virtio_rpmsg_hdr** (src, dst, len), **rt_virtqueue_add_outbuf**, **kick** |
Wire header (**virtio-rpmsg.h**):
rt_virtqueue_read_buf** on RX queuefind_endpoint(rdev, dst=hdr->dst, src=ANY)** dst == RT_RPMSG_NS_ADDR** → use **vrpmsg->ns** deviceept->rx_callback(rdev, hdr->src, data, len)**rt_virtqueue_add_inbuf****RT_RPMSG_DRIVER_EXPORT** → **INIT_DEVICE_EXPORT** → **rt_rpmsg_driver_register** → probes all **rt_rpmsg_device** on bus with matching **id.name**.
If you implement a non-VirtIO link:
Bus **probe**: **rt_dm_power_domain_attach** then **rdrv->probe(rdev)**.
| API | Role |
|---|---|
**rt_rpmsg_create_endpoint** | **ops->create_endpoint**, insert on **ept_nodes** |
**rt_rpmsg_destroy_endpoint** | Backend destroy + **rt_free** |
**rt_rpmsg_find_endpoint** | Match src/dst/name wildcards (**RT_RPMSG_ADDR_ANY**) |
**rt_rpmsg_send / sendto / send_wait** | **ops->send** under **ept->lock** |
RX callback: per-endpoint **rx_cb**, or driver-wide **struct rt_rpmsg_driver::rx_callback** if **rx_cb == NULL**.
Well-known address **RT_RPMSG_NS_ADDR (0x35)**. Remote CREATE can auto-create endpoints (driver default RX logs only). Local CREATE from **virtio_rpmsg_create_endpoint** announces name+addr to peer when **VIRTIO_RPMSG_F_NS**.
Details: RPMsg name service.
rpmsg_charN** (from **rpmsg_char probe**)RT_DEVICE_CTRL_RPMSG_CREATE_EPT** with **struct rt_rpmsg_endpoint_info**rpmsg_<src>x<dst>**, **read/write**Details: RPMsg character device.
| Step | Check |
|---|---|
| 1 | **RT_USING_RPMSG**, **RT_RPMSG_RT_THREAD_VIRTIO**, mailbox + shmem drivers |
| 2 | Same **queue-max**, same **shmem** region, correct **mboxes** index per role |
| 3 | **rpmsg.mode=** bootarg matches remote |
| 4 | Master has **master;** property; slave has **slave;** |
| 5 | **virtio_rpmsg_probe** succeeds → **rpmsg_char** / **rpmsg-name-service** on bus |
| 6 | Create endpoint or wait for NS CREATE; verify **rt_rpmsg_send** returns OK |
| 7 | Hardware spinlock / Mailbox subsystem ordering if shared with other AMP IPC |
Implement **struct rt_rpmsg_ops** and register **rt_rpmsg_device** with an **id.name** your class driver matches (or reuse **rpmsg-char**):
create_endpoint**: book-keep addresses / shared memory slotssend**: push frame with src/dst header to remotert_rpmsg_find_endpoint** → call **ept->rx_callback**Do not call **rt_rpmsg_*** from ISR if your **send** sleeps on virtqueue completion — use workqueue.
| Issue | Mitigation |
|---|---|
**id.name mismatch** | Backend **rpmsg-char** vs driver table **rpmsg-char** / **rpmsg-raw** |
| Master/slave queue swap | Wrong **rpmsg.mode** → no RX |
**queue-max mismatch** | Corrupt rings |
| NS without feature | Master must advertise **VIRTIO_RPMSG_F_NS** |
| Endpoint without RX cb | **create_endpoint(..., NULL)** needs driver **rx_callback** |
| Buffer size | Payload ≤ **VIRTIO_RPMSG_MAX_BUF_SIZE - sizeof(hdr)** (512 default) |
NULL send addr | **RT_RPMSG_ADDR_ANY** rejected in **virtio_rpmsg_send** |
| Power domain | Bus probe attaches domain; **-RT_EEMPTY** OK |
components/drivers/rpmsg/rpmsg-rt-thread-virtio.ccomponents/drivers/virtio/virtio-rpmsg.ccomponents/drivers/virtio/virtio_config/virtio-rpmsg.h