【STM32H757XIH6 双核系列】IPC 进程间通信 —— CM7 printf 重定向到 OpenAMP 发送

1. 引言

在阅读此文章前,请快速浏览上一篇从零配置 OpenAMP 的文章:
【STM32H757XIH6 双核】IPC 进程间通信 —— OpenAMP 多核异构处理器间通信框架配置

本文以 CM7 通过 OpenAMP 转发 printf 输出给 CM4,再由 CM4 通过串口输出为例。反向转发的原理相同,只需交换发送核与接收核,并确保接收核的 printf 最终输出到串口。

本文的输出链路为:

CM7 printf → CM7 _write → OpenAMP / RPMsg → CM4 接收回调 → CM4 printf → 串口

前提:两核已经完成上一篇文章中的 OpenAMP 配置,能够建立端点并收发消息;CM4 的 printf 已重定向到串口。不要再将 CM4 用于输出接收消息的 printf 转发回 CM7,以免形成循环转发。

2. CM7 printf 重定向

以下示例适用于 GCC 工具链。将 _write() 放在能够访问 CM7 端点变量 s_ept 的源文件中,用于覆盖 syscalls.c 中的弱定义。如果 CM7 已有串口重定向使用的非弱定义 _write(),需要替换或移除原实现,避免重复定义。

/*
 * 覆盖 syscalls.c 中的弱定义,将 CM7 的 printf 发送到 CM4。
 */
int _write(int file, char *ptr, int len)
{
  (void)file;
  int total_len = len;

  if (!is_rpmsg_ept_ready(&s_ept))
  {
    /*
     * 端点尚未就绪时,主动丢弃本次输出。
     * 避免启动日志等待通信建立而阻塞初始化。
     */
    return len;
  }

  while (len > 0)
  {
    int send_len = len;

    /*
     * 按 128 字节分片,适配当前配置的单条消息有效载荷容量。
     * 128 字节是本示例选取的长度,不是 OpenAMP 固定的最大长度。
     */
    if (send_len > 128)
    {
      send_len = 128;
    }

    if (rpmsg_send(&s_ept, ptr, send_len) < 0)
    {
      return -1;
    }

    ptr += send_len;
    len -= send_len;
  }

  return total_len;
}

rpmsg_send() 成功时返回发送的字节数,失败时返回负值,因此应使用 < 0 判断失败。_write() 全部发送成功后则返回原始请求长度,不能返回 0。

端点未就绪时,本示例直接返回 len,表示向标准库报告本次输出已处理;实际日志已被丢弃,不会在端点就绪后补发。因此,只有端点就绪后产生的日志才能通过这条链路转发。

3. CM4 回调函数修改

发送端每条消息最多包含 128 字节,接收端使用 129 字节缓冲区,额外留出一个字节存放字符串结束符,避免截断正常分片。此处用于接收 printf 文本,不用于输出任意二进制数据。

static int cm4_rx_callback(struct rpmsg_endpoint *rp_chnl,
                           void *data,
                           size_t len,
                           uint32_t src,
                           void *priv)
{
  char msg[129];

  memset(msg, 0, sizeof(msg));

  (void)rp_chnl;
  (void)src;
  (void)priv;

  if (len >= sizeof(msg))
  {
    len = sizeof(msg) - 1;
  }

  memcpy(msg, data, len);
  msg[len] = '\0';

  printf("%s", msg);

  return RPMSG_SUCCESS;
}

4. 测试结果

下图展示了初始化阶段的日志输出,可用于观察基本转发效果;仅凭这些输出,还不能确认长文本分片是否完整。

使用时有两点需要注意:

  1. 连续大量打印时,如果接收端处理不及时,发送缓冲区可能耗尽,导致 rpmsg_send() 等待可用缓冲区,表现为程序长时间停在发送函数中。本示例可适当降低打印频率或增加打印间隔,同时确保接收端持续处理 OpenAMP 消息。
  2. 建议在日志开头添加 CM4: 或 CM7:,便于区分日志来源。

修正代码后,建议再输出一段超过 128 字节的文本,检查接收端内容是否完整、顺序是否正确,以验证分片发送与接收。该测试需要实际运行后确认,不能仅根据下面的截图判断通过。

image

博客导航

博客导航

posted @ 2026-09-02 15:26  膝盖中箭卫兵  阅读(20)  评论(0)    收藏  举报
ORCID iD icon https://orcid.org/0000-0001-5102-772X