![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Header: **components/drivers/include/drivers/mailbox.h**. Core: **components/drivers/mailbox/mailbox.c**.
The mailbox layer is a lock-aware wrapper around hardware doorbell / message-slot IPs: one side sends a small notification, the peer is woken by IRQ and handles **rx_callback**. Use for AMP IPC, SCMI doorbells, remoteproc handshakes, and PIC-backed mailboxes—not bulk DMA.
Device-tree binding and **rt-thread,pic-mailbox**: Mailbox device model (DM).
| Use mailbox when… | Prefer something else when… |
|---|---|
| You need a hardware channel with IRQ to peer (SoC mailbox IP, PIC mailbox). | Thread-to-thread only: semaphore, message queue, completion. |
| Firmware expects doorbell + shared memory (SCMI, AMP). | Large payloads — put data in SRAM, pass a pointer or single word. |
DT exposes **mboxes / #mbox-cells / mbox-names**. | No controller: implement **rt_mbox_controller_ops** and register first. |
| Named RPMsg endpoints and bus matching are required. | RPMsg |
| Role | Responsibility |
|---|---|
| Controller driver | **rt_mbox_controller_register**: **num_chans**, **ops**. Implements **send**, **release**, optional **peek**, **request**, **ofw_parse**. Calls **rt_mbox_send_done** when HW TX completes (if applicable). |
| Client driver | **struct rt_mbox_client** on consumer **rt_device**: **tx_prepare**, **tx_done**, **rx_callback**. **rt_mbox_request_by_index** or **by_name**. |
| API | Returns |
|---|---|
**request_by_index** | Channel pointer or error pointer (rt_is_err_ptr) |
**request_by_name** | Channel, error pointer, or **NULL** if name not in **mbox-names** |
Prerequisites: valid **client->dev->ofw_node**; provider probed (**rt_ofw_data** = controller). Optional **ops->request** runs after channel selection; on failure core **release**s and returns error pointer.
Flow (under **chan->lock**):
client->tx_prepare(client, data)**ctrl->ops->send(chan, data)** — return value is only the ops resultchan->data**, clear **complete**; if **timeout_ms != RT_WAITING_FOREVER**, start one-shot timercomplete = RT_TRUE** immediately**RT_EOK from rt_mbox_send** means the controller accepted the submission, not that **tx_done** ran.
**rt_mbox_send_done**: clears **chan->data**, calls **tx_done**, sets **complete = RT_TRUE**. Controller must invoke after HW TX finish (or on error). Timer calls it with **-RT_ETIMEOUT** if still incomplete.
Implications:
data** (or pointed buffer) until **tx_done** or synchronous send failuretx_prepare** runs with channel spinlock — non-blocking onlyRT_WAITING_FOREVER**: no timer; requires **send_done** from controller for **tx_done** (see Mailbox device model (DM) for PIC caveat)Does not read hardware. Invokes **client->rx_callback(client, data)** if set. Controller ISR reads registers/FIFO, then passes payload pointer (e.g. local **uint32_t**) into **rt_mbox_recv**.
Forwards to **ops->peek** if present; else **RT_FALSE**.
**rt_mbox_controller_unregister**: removes from global list, **rt_dm_dev_unbind_fwdata**, **rt_mbox_release** on every channel (reverse order), frees **chans**. **release** must be safe even if **request** never ran for a channel.
| Issue | Mitigation |
|---|---|
No send_done in controller | Use finite timeout or fire-and-forget (Mailbox device model (DM) — PIC) |
**release NULL** | Always implement **ops->release** |
Blocking in tx_prepare | Deadlock risk under spinlock |
| Confusing return types | Distinguish **NULL** (name) vs **rt_err_ptr** (index) |
components/drivers/mailbox/mailbox.ccomponents/drivers/mailbox/mailbox-pic.c