> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 邮箱驱动概述

邮箱提供了一个驱动接口，用于在邮箱客户端与 RTSS 之间交换消息。消息存储在指定的邮箱区域中。下图展示了 RTSS 与 APSS 之间通过邮箱交换消息的过程：<br />

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/zh/System/FreeRTOS/media/rtss-mailbox.svg" alt="rtss-mailbox.svg" />
</Frame>

下图说明了邮箱驱动的功能：

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/zh/System/FreeRTOS/media/rtss-mailbox-features.svg%20" alt="rtss-mailbox-features.svg " />
</Frame>

以下是邮箱驱动中的关键组件：

* [Linux HLOS 邮箱服务器](https://dragonwingdocs.qualcomm.com/System/FreeRTOS/Mailbox-driver-overview)
* [RTSS 邮箱外部驱动](https://dragonwingdocs.qualcomm.com/System/FreeRTOS/Mailbox-driver-overview)
* [邮箱区域 - DDR](https://dragonwingdocs.qualcomm.com/System/FreeRTOS/Mailbox-driver-overview)

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-staging/zh/System/FreeRTOS/media/maiboxdrivercomponent.png" alt="maiboxdrivercomponent.png" />
</Frame>

**Linux HLOS 邮箱服务器**

Linux HLOS 邮箱服务器（通常称为 HLOS 邮箱资源管理器或 HLOS 邮箱接口）是用户空间或内核空间接口，可让 Linux（HLOS）应用程序使用邮箱 IPC 机制，通过 DDR 区域与 RTSS 交换消息。

Linux HLOS 邮箱服务器充当 HLOS 邮箱资源管理器，并提供以下功能的设备节点：

* 将邮箱硬件（由 RTSS 邮箱驱动配置）映射到 `/dev/sail/*` 通道。
* 为 HLOS 应用程序提供通知 API。
* 通过邮箱 IPC 机制，在 Linux 与 RTSS/NHLOS 之间实现全双工的结构化 IPC。

简单邮箱消息读/写的典型使用流程（HLOS 侧）：

1. 打开通道：应用程序打开邮箱资源管理器公开的 Tx 和 Rx 设备节点。
2. 发送：应用程序向 Tx 设备节点写入结构化消息。
3. 接收：
   * 应用程序在 Rx 设备节点上阻塞（或使用 poll()/select()）。
   * 收到通知时读取消息（异步或基于轮询）。
4. 关闭：应用程序关闭邮箱句柄；资源管理器清理上下文。

源代码详情：

* `sources/sail-mailbox/sail-mb-umd/include/sail_mailbox.h`
* `sources/sail-mailbox/sail-mb-umd/src/sail_mbox_core.c`、`sail_mbox_lib.c`、`sail_mbox_lib.h` 和 `sailmb_internal.c`

**RTSS 邮箱外部驱动**

邮箱外部驱动是在 RTSS 与 APSS（HLOS）之间创建和管理共享内存通道的机制。

* 将共享的 DDR 邮箱区域划分为多个区域，例如区域 0、区域 1 和区域 2。
* 将每个区域视为一个通道/子区域，由唯一的通道/子区域 IDN 标识。
* 为 RTSS 与 APSS 之间的消息传递提供缓冲和通知基础设施。

这是 HLOS 邮箱服务器在 RTSS 侧的对应部分。邮箱外部驱动管理底层共享内存区域和 IPC 控制器，而 HLOS 则通过 `/dev/sail/*` 节点进行通信。

消息流和通知：

1. RTSS 和 APSS 共享 DDR 邮箱区域，这些区域由邮箱外部驱动（RTSS 侧）以及相应的 APSS/HLOS 驱动管理。
2. 当 APSS 或 RTSS 向某个区域的环形缓冲区写入数据时，该数据即可供应用程序使用。
3. 为通知应用程序有新数据可用或某个缓冲区已被消费：
   > 邮箱外部驱动使用 IPCC 在 APSS 与 RTSS 之间生成异步事件。
4. 在 RTSS 上：

* 这些 IPC 事件会触发邮箱外部驱动的回调。
* 使用典型的 RTOS IPC 机制来唤醒或同步实时消费/生成消息的任务。

源代码详情：

* `sail_proc/BSP/mailboxExt/public/mailboxExt_api.h`
* `sail_proc/BSP/mailboxExt/src/mailboxExt_api.c`、`mailboxExt_config.c`

**邮箱区域 - DDR**

DDR 是一种外部内存，用作邮箱驱动的共享内存，供 Linux HLOS 和 RTSS 存储消息。

## **创建新的邮箱通道**

**RTSS 侧**

1. 添加客户端 ID。
   > 1. 将新的客户端 ID 添加到 `mailboxExt_api.h` 中的 `xMailboxExtclienttype`。
   > 2. 将该条目放在 QCMI 起始和结束标记之间：

```text theme={null}
typedef enum
{
  MAILBOX_HLOSPMU = 0,
  MAILBOX_HLOSUSS,
  MAILBOX_HLOSTST,
  MAILBOX_CONSOLE,
  MAILBOX_OTA,
  MAILBOX_TMU,
  MAILBOX_PTP,
  MAILBOX_CAN,
  MAILBOX_POWER,
  MAILBOX_FUSE,
  MAILBOX_STZ,
  /* qcmi resource manager communication client entries goes here ..start*/
  /* qcmi resource manager communication client entries goes here ..end*/
  MAILBOX_SSM,
  MAILBOX_TSM,
  MAILBOX_EBMAX
}xMailboxExtclienttype;
```

2. 添加通道 ID。

a.  将 RTSS 接收端（Rx）、发送端（Tx）或 Rx-Tx ID 对添加到 `mailboxExt_config.h` 中的 `mailboxEBChanType_e`。

b.  将这些 ID 插入 QCMI 起始和结束标记之间：

```text theme={null}
typedef enum
{
        EB_CHAN_PMU_RX_IDN,
        EB_CHAN_PMU_TX_IDN,
        EB_CHAN_ULS_RX_IDN,
        EB_CHAN_ULS_TX_IDN,
        EB_CHAN_TST_RX_IDN,
        EB_CHAN_TST_TX_IDN,
        EB_CHAN_CONSOLE_TX_IDN,
        EB_CHAN_OTA_RX_IDN,
        EB_CHAN_OTA_TX_IDN,
        EB_CHAN_TMU_RX_IDN,
        EB_CHAN_TMU_TX_IDN,
        EB_CHAN_PTP_RX_IDN,
        EB_CHAN_PTP_TX_IDN,
        EB_CHAN_CAN_RX_IDN,
        EB_CHAN_CAN_TX_IDN,
        EB_CHAN_POWER_TX_IDN,
        EB_CHAN_FUSE_RX_IDN,
        EB_CHAN_FUSE_TX_IDN,
        EB_CHAN_STZ_RX_IDN,
        EB_CHAN_STZ_TX_IDN,
        /* qcmi resource manager communication client chan entries goes here following placeholder entries always be at the end */
        EB_CHAN_SSM_RX_IDN,     /* SSM RX */
        EB_CHAN_SSM_TX_IDN,     /* SSM TX */
        EB_CHAN_TSM_RX_IDN,     /* TSM RX */
        EB_CHAN_TSM_TX_IDN,     /* TSM TX */
        EB_CHAN_MAX,
}mailboxEBChanType_e;
```

3. 更新子区域数量。

a. 更新 `mailboxExt_config.h` 中的 `mailboxEB_QCMI_NUMSUBREGION` 以反映新通道：

```text theme={null}
/* Number of SubRegions in the HLOS general mailbox */
#define mailboxEB_QCMI_NUMSUBREGION 20U
```

* 对于 Rx-Tx 对，子区域数量为 2，因此将 `mailboxEB_QCMI_NUMSUBREGION` 设置为 22。
* 对于仅 Rx 或仅 Tx，子区域数量为 1，因此将 `mailboxEB_QCMI_NUMSUBREGION` 设置为 21。

4. 定义新的通道配置条目。

a.  在 `mailboxEB_DATA` 静态资源表中添加新的通道配置条目：

```text theme={null}
static mbsub_rgn_config_t Mailbox_QCMISubRegionCfg[EB_CHAN_MAX]
```

该条目必须遵循 `xMailboxExtClientType` 枚举中定义的更新后的通道索引编号。

`mbsub_rgn_config_t` 的结构定义：

```text theme={null}
typedef struct __attribute__((packed))
{
int8    name[MB_NAME_SZ];    // mailbox sub-region name
uint32  sender;                            // mailbox sender
uint32  receiver;                         //  mailbox receiver
uint32  prot;                                 // mailbox protocol
uint32  sig;                                   // Mailbox signal Tx-Rx (Unique)
uint32  mode;                             // Mailbox Read Mode (RD) or Write Mode (WR)                           RTSS consider RD =1; WR = 0;
uint32  prio;                             // channel priority 0: means default Max , 1 : Max -1 , 2: Max-2 so on upto max 65
uint32  start_addr_offset;         // offset of sub-region startaddress.
uint32  end_addr_offset;           // offset of sub-region end address.
uint32  item_max_num;              // Sub-region maximum item number
uint32  item_max_size;             // Sub-region maximum item size
} mbsub_rgn_config_t;
```

有关现有通道配置的示例，请参阅 `mailboxExt_config.c` 文件。

`xMailboxExtClientType` 枚举中索引值为 3 的 `MAILBOX_CONSOLE` 条目定义如下：

```text theme={null}
mailboxEB_DATA static mbsub_rgn_config_t Mailbox_QCMISubRegionCfg[EB_CHAN_MAX] =
{

   * Description: sail debug log logger write channel used to send
     data to MD(HLOS\UEFI)
     */
    {
        "/dev/sail/log",
          (uint32)IPCC_C_APPS,
      (uint32)IPCC_C_SAIL0,
      (uint32)IPCC_P_COMPUTEL1,
      mailboxEB_CHAN_CONSOLE_TX_IDN_SIGID,
          MB_CHAN_WR_MODE,
      mailboxEB_QCMI_PRIORITY,
      MB_DEFAULT_CHAN_OFFSET,
      MB_DEFAULT_CHAN_OFFSET,
      mailboxEB_CHAN_CONSOLE_TX_IDN_NUMITEM,
      mailboxEB_CHAN_CONSOLE_TX_IDN_ITEMSIZE
    },
```

<Note>
  **注意**

  * `name` 字段应包含三个字符，读通道以 `0` 为后缀，写通道以 `1` 为后缀。
  * 如果 `xMailboxExtClientType` 客户端条目仅映射了单个 Rx 或 Tx ID，请使用默认值初始化其他通道条目，请参阅 `MAILBOX_CONSOLE` 示例
</Note>

5. 在 `xMailboxClientRec` 表中添加条目。

   a. 更新 `mailboxEB_CONST` 表：

```text theme={null}
const xMailboxEBClientRec_t xMailboxClientRec[MAILBOX_EBMAX]
```

`xMailboxEBClientRec_t` 的结构定义：

```text theme={null}
typedef struct
{
xMailboxEBChanRec_t ChanRec[MB_CHAN_MAX_TYP;
}xMailboxEBClientRec_t;
```

`xMailboxEBChanRec_t` 的结构定义：

```text theme={null}
/* chan descr type */
typedef struct
{
mailboxEBIDNType_e MbId;
mailboxEBChanType_e ChanId;
uint32 MbAddress;
uint32 *pDbgCnt;
xMailboxExtclienttypeClient;
const mbsub_rgn_config_t *pRgnCfg;
}xMailboxEBChanRec_t;
/* client chan descrtype  */
```

对于 `/dev/sail/log` 通道，客户端 ID 为 `MAILBOX_CONSOLE` 的客户端包含以下配置条目，其中仅定义了 Tx（写）通道。

```text theme={null}
{
  /* rd chan : NA default init */
  (mailboxEBIDNType_e)0xFF,
  (mailboxEBChanType_e)0xFF,
  0,
  NULL,
  (xMailboxExtclienttype)0xFF,
  NULL,
  /* wr chan */
  MAILBOX_QCMI_IDN,
  EB_CHAN_CONSOLE_TX_IDN,
  mailboxEB_QCMI_ADDR,
  &ulMailbox_DbgCnt[EB_CHAN_CONSOLE_TX_IDN],
  MAILBOX_CONSOLE,
  &Mailbox_QCMISubRegionCfg[EB_CHAN_CONSOLE_TX_IDN]
},
```

协议与通道映射：

下表列出了协议信号、发送端、接收端和通道支持情况，供集成人员在 mailboxExt 驱动中添加新通道时参考。

| **支持的协议** | **信号** | **发送端** | **接收端** | **支持的通道** |
| :-: | :-: | :-: | :-: | :-: |
| `IPCC_P_COMPUTEL 1` | 32 | `IPCC_C_APPS` | 某个 RTSS 核心，例如 `IPCC_C_SAIL0` 或 `IPCC_C_SAIL1` | 32 |

* 根据该表选择协议、发送端和接收端。
* RTSS 核心使用附加在宏后的逻辑编号后缀，例如核心 0 对应 IPCC\_C\_SAIL0。
* 发送端列表示 APSS 用于与 RTSS 域接收端客户端连接的发送端客户端线路。每个发送端客户端根据所选协议提供表中指定数量的信号。

参考：

`mailbox_test` 应用程序位于 `sail_proc\BSP\tests\sailsw1\mailbox_test\src\MBtests_sailsw1.c`。

**APPS 侧**

1. 在设备树中添加新的通道条目。

   1. 使用新的通道配置更新设备树：

   ```text theme={null}
   sail_mailbox: sail-mailbox@90d80000 {
     compatible = "qcom,sail-mailbox";
     reg = <0x0 0x01FFE02C 0x0 0x10>,
     <0x0 0x01FFD018 0x0 0x10>,
     <0x0 0x17C0000C 0x0 0x04>;
     mboxes =  <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x2>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x3>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x4>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x5>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x6>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0X7>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL2 0X8>,
               <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0X9>;
               +<&ipcc_computeL1 IPCC_CLIENT_SAIL0 0XA>  //Example new entry for new  channel created at RTSS side
     memory-region = <&sail_mailbox_mem>,
                     <&sail_ota_mem>;
                   interrupt-parent=<&ipcc_computeL1>;
     interrupts =  <IPCC_CLIENT_SAIL0 0x2 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0x3 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0x4 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0x5 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0x6 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0X7 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL2 0X8 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL1 0X9 IRQ_TYPE_EDGE_RISING>,
                   <IPCC_CLIENT_SAIL0 0XA IRQ_TYPE_EDGE_RISING>; //example entry for newly created channel at sail side
     sail-handshake-delay = <50000>;
     status = "okay";
            };
   ```

   <Note>
     **注意**

     <br />`&ipcc_computeL1 IPCC_CLIENT_SAIL0 0xA` 表示：

     > * `ipcc_computeL1`：协议名称（目前仅支持此协议）。
     > * `IPCC_CLIENT_SAIL1`：RTSS 核心编号。
     > * `0XA`：通道编号。

     * 映射示例：
       ```text theme={null}
       <&ipcc_computeL1 IPCC_CLIENT_SAIL0 0x3>,
       <IPCC_CLIENT_SAIL0 0x3 IRQ_TYPE_EDGE_RISING>
       ```
       这对应于 `/dev/sail/log`，映射到 `xMailboxExtClientType` 枚举中索引值为 3 的 `MAILBOX_CONSOLE`。
   </Note>

参考：

* `saildbg`
  * 位置

    `sail-mailbox/reference_apps/sail_dbg/src/saildbg.c`
  * 关键 API：
    * `open_sail_mailbox()`：为 TX 和 RX 打开邮箱通道。
    * `write_sail_mailbox()`：向 TX 通道写入消息。
    * `read_sail_mailbox()`：从 RX 通道读取消息。
    * `close_sail_mailbox()`：关闭 TX 和 RX 的邮箱通道。
  * 结构：
    * `struct SailClientDataType *pTxClientData`：用于发送消息的 TX 结构。
    * `struct SailClientDataType *pRxClientData`：用于接收消息的 RX 结构。
  * 邮箱测试应用程序：

    [邮箱测试应用程序：saildbg](https://docs.qualcomm.com/doc/80-70033-42/topic/test-commands.html#mailbox-test-applications-saildbg)
* sail\_console\_chan\`：
  * 位置：

    `sail-mailbox/unit_test_apps/sail_console_chan_app.c`
  * 邮箱测试应用程序：

    [邮箱测试应用程序：sail\_console\_chan\_app](https://docs.qualcomm.com/doc/80-70033-42/topic/test-commands.html#mailbox-test-applications-sail-console-chan-app)

## **RTSS 邮箱演示应用程序**

`sailmb_demo` 参考应用程序演示了运行 Linux 的 APSS 与运行 Free RTOS 的 RTSS 之间的双向邮箱通信。该应用程序从 APSS 向某个 RTSS CPU 核心发送消息，并接收该 RTSS CPU 核心的响应。

成功的消息交换可验证以下内容：

* RTSS 固件已在 DDR 中初始化共享邮箱结构。
* Linux 邮箱驱动已加载、映射共享内存，并完成与 RTSS 的硬件握手。
* APSS 应用程序可以向共享内存写入消息并触发发往 RTSS 的中断。
* RTSS 可以接收中断、读取消息、写入响应并触发发往 APSS 的中断。
* APSS 可以接收中断、读取响应并将其显示在控制台上。

该应用程序与四个 RTSS CPU 核心通信。每个核心使用一对专用的发送和接收通道。下表中的邮箱通道映射以 APSS 视角列出：

| **RTSS 核心** | **APSS 发送通道** | **APSS 接收通道** | **RTSS 任务** | **IPCC 信号** | **缓冲区容量** | **消息大小** |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| Core 0 | `/dev/sail/cz0` | `/dev/sail/cz1` | xCore0Task | 信号 13 | 10 条消息 | 每条消息 64 字节 |
| Core 1 | `/dev/sail/co0` | `/dev/sail/co1` | xCore1Task | 信号 14 | 10 条消息 | 每条消息 64 字节 |
| Core 2 | `/dev/sail/ct0` | `/dev/sail/ct1` | xCore2Task | 信号 15 | 10 条消息 | 每条消息 64 字节 |
| Core 3 | `/dev/sail/cth0` | `/dev/sail/cth1` | xCore3Task | 信号 16 | 10 条消息 | 每条消息 64 字节 |

要运行 RTSS 邮箱演示应用程序，请参阅[邮箱测试应用程序：sailmb\_demo](https://dragonwingdocs.qualcomm.com/System/FreeRTOS/RTSS-test-commands#sailmb_demo)。
