在OpenAMP的应用程序中,经常看到地址被设置成RPMSG_ADDR_ANY。在通信过程中,为什么可以把源地址、目的地址设置成任意值?
这个宏的名字不够清楚,它的本意是让系统自动选择。如果设置源地址为RPMSG_ADDR_ANY,则系统自动选择一个空闲的源地址。如果设置目的地址为RPMSG_ADDR_ANY,则系统会自动发送一个查询消息,根据名称查询对方的地址,相当于TCP/IP中的域名解析。
查看代码,我们可以确认以上结论。第一个函数是rpmsg_create_ept(),提供源地址、目的地址后,它创建rpmsg endpoint(节点)。
下面代码显示,如果调用rpmsg_create_ept()时指定了源地址,会调用rpmsg_is_address_set设置源地址,相当于TCP/IP中的Bind。如果调用rpmsg_create_ept()时没有指定源地址,则会调用rpmsg_get_address(),自动从设备中没有使用的地址中取一个地址。
// rpmsg.c
int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev,
const char *name, uint32_t src, uint32_t dest,
rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb)
{
... ...
if (src != RPMSG_ADDR_ANY) {
status = rpmsg_is_address_set(rdev->bitmap,
RPMSG_ADDR_BMP_SIZE, src);
if (!status) {
/* Mark the address as used in the address bitmap. */
rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
src);
} else if (status > 0) {
status = RPMSG_SUCCESS;
goto ret_status;
} else {
goto ret_status;
}
} else {
addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);
}
... ...
return status;
}
// rpmsg.c
static uint32_t rpmsg_get_address(unsigned long *bitmap, int size)
{
unsigned int addr = RPMSG_ADDR_ANY;
unsigned int nextbit;
nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size);
if (nextbit < (uint32_t)size) {
addr = nextbit;
metal_bitmap_set_bit(bitmap, nextbit);
}
return addr;
}
如果调用rpmsg_create_ept()时没有指定目的地址,会调用rpmsg_send_ns_message()发送消息,之后就会返回。如果另外一侧返回消息后,会触发的调用rpmsg_virtio_rx_callback()。在rpmsg_virtio_rx_callback中,从消息中得到entpoint信息,检查其中的目的地址,如果目的地址是ANY,就会从消息中提取出远端地址,赋值给本地endpoint的目的地址。
// rpmsg.c int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, const char *name, uint32_t src, uint32_t dest, rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb) { ... ... if (!status && ept- > dest_addr == RPMSG_ADDR_ANY) { /* Send NS announcement to remote processor */ metal_mutex_release(&rdev- > lock); status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); metal_mutex_acquire(&rdev- > lock); if (status) rpmsg_unregister_endpoint(ept); } ... ... return status; } // rpmsg_virtio.c static void rpmsg_virtio_rx_callback(struct virtqueue *vq) { ... ... /* Process the received data from remote node */ rp_hdr = (struct rpmsg_hdr *)rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx); while (rp_hdr) { ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst); if (ept->dest_addr == RPMSG_ADDR_ANY) { /* * First message received from the remote side, * update channel destination address */ ept->dest_addr = rp_hdr->src; } status = ept->cb(ept, (void *)RPMSG_LOCATE_DATA(rp_hdr), rp_hdr->len, ept->addr, ept->priv); } ... ... }
编辑:hfy
-
TCP
+关注
关注
8文章
1418浏览量
83023 -
应用程序
+关注
关注
38文章
3342浏览量
59926
发布评论请先 登录
学生适合使用的SOLIDWORKS 云应用程序
V5.2.1 Menuconfig中,AMP如何配置呢?
【米尔-全志T536开发板试用体验】异核心开发
国产开发板—米尔全志T113-i如何实现ARM+RISC-V+DSP协同计算?
如何部署OpenVINO™工具套件应用程序?
在OpenVINO™中运行应用程序失败怎么解决?
AWTK-WEB 快速入门(5) - C 语言 WebSocket 应用程序
基于HPM_SDK_ENV开发应用程序的升级处理
AWTK-WEB 快速入门(4) - JS Http 应用程序

浅谈OpenAMP的应用程序中RPMSG_ADDR_ANY含义
评论