![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
**RT_USING_MBOX** builds **mailbox.c** (controller registry, OFW **mboxes** resolution, **rt_mbox_send** / **recv**) and optionally **mailbox-pic.c** (**rt-thread,pic-mailbox**). The layer is a Linux-style mailbox framework: controllers expose channels; clients request by DT phandle and exchange small payloads (often one **uint32_t** or a pointer to shared memory).
Client/controller API semantics: Mailbox subsystem.
Sources: **components/drivers/mailbox/mailbox.c**, **mailbox-pic.c**, **components/drivers/include/drivers/mailbox.h**.
| Option | Role |
|---|---|
**RT_USING_DM** | Required |
**RT_USING_OFW** | Required — **mboxes**, **#mbox-cells**, **mbox-names** |
**RT_USING_MBOX** | Core **mailbox.c** |
**RT_MBOX_PIC** | In-tree **rt-thread,pic-mailbox** (default y when MBOX on) |
**SOC_DM_MBOX_DIR** | BSP adds SoC mailbox controllers |
There is no separate mailbox rt_bus — providers register **struct rt_mbox_controller** and bind **rt_ofw_data(provider_np) = ctrl**.
| Role | Object | Responsibility |
|---|---|---|
| Controller | **struct rt_mbox_controller** | **num_chans**, **ops**, per-chan timer (created by core) |
| Channel | **struct rt_mbox_chan** | Binds **client**, **priv**, send state |
| Client | **struct rt_mbox_client** | Lives on consumer **rt_device**; **rx_callback**, **tx_*** |
| Check | Detail |
|---|---|
**ctrl->dev**, **ops**, **num_chans > 0** | Required or **-RT_EINVAL** |
**ops->send**, **ops->release** | De facto mandatory — unregister always calls **release** per channel |
**ops->request**, **ops->peek**, **ops->ofw_parse** | Optional |
| Per-channel timer | One-shot; used when **rt_mbox_send(..., timeout_ms)** is not **RT_WAITING_FOREVER** |
**ofw_parse**: custom channel index from **mboxes** cells; default parser expects one cell = channel index.
| Property | Role |
|---|---|
**mboxes** | Phandle list + **#mbox-cells** per controller |
**mbox-names** | Optional; used with **rt_mbox_request_by_name** |
**#mbox-cells** | On provider node (default 1 = channel id) |
**rt_mbox_request_by_index** calls **rt_platform_ofw_request** on the provider if **rt_ofw_data** is empty. Returns **struct rt_mbox_chan *** or error pointer — test with **rt_is_err_ptr**.
**rt_mbox_request_by_name**: returns **NULL** if the name is missing in **mbox-names** (distinct from error pointers).
Compatible: **rt-thread,pic-mailbox**
| Offset | Name | Role |
|---|---|---|
**0x00** | **MAILBOX_IMASK** | Channel interrupt mask |
**0x04** | **MAILBOX_ISTATE** | Pending / doorbell state |
**0x08 + n*4** | **MAILBOX_MSG(n)** | 32-bit message slot per channel |
**reg** spans local + peer windows (each **size/2**). **position = <0>** (captain): iomap low half, peer = **regs + size/2**, initializes both **IMASK/ISTATE**. **position = <1>**: peer low, local high.
| Property | Role |
|---|---|
**interrupts** | Local mailbox IRQ |
**peer-interrupts** | HW IRQ number on peer PIC to poke remote CPU |
**uid** | Device name suffix **pic-mbox{N}** |
**#mbox-cells = <1>** | Channel index 0..31 (**num_chans = 32**) |
send**: waits until peer **ISTATE** bit clear; writes ***(uint32_t *)data** to **MAILBOX_MSG(index)**; sets peer **ISTATE** bit; triggers **rt_pic_irq_set_state_raw** on **peer_hwirq**.ISTATE**, loads **MAILBOX_MSG** from peer window, **rt_mbox_recv(chan, &msg)** per bit.rt_mbox_send_done — TX completion is not hardware-ACKed; use a finite timeout_ms in **rt_mbox_send** if **tx_done** matters, or treat send as fire-and-forget.RT_USING_MBOX** (+ BSP Kconfig under **SOC_DM_MBOX_DIR**).struct rt_mbox_controller** + private state; set **dev**, **num_chans**, **ops**.send** (required) and **release** (required).request**: unmask channel / enable clock.peek**: non-destructive pending check.ofw_parse**: if **#mbox-cells** is not a single channel index.rt_mbox_controller_register** after HW init; store pointer in probe (**user_data** or **rt_ofw_data**).rt_mbox_recv(chan, payload_ptr)**.rt_mbox_send_done(chan, err)**.remove**: detach IRQ, **rt_mbox_controller_unregister**.| Issue | Mitigation |
|---|---|
Missing release | Unregister crashes — always provide **ops->release** |
PIC + tx_done | PIC path never calls **send_done** — use timeout or do not rely on **tx_done** |
**data lifetime** | Keep buffer valid until **tx_done** or synchronous send failure |
**tx_prepare under spinlock** | No blocking calls |
| Error pointer vs NULL | **by_index** → err ptr; missing **by_name** → **NULL** |
| 32-bit payload on PIC | **send** dereferences **uint32_t** — pass pointer to at least 4 bytes |
components/drivers/include/drivers/mailbox.h