在OpenAMP的應(yīng)用程序中,經(jīng)??吹降刂繁辉O(shè)置成RPMSG_ADDR_ANY。在通信過程中,為什么可以把源地址、目的地址設(shè)置成任意值?
這個(gè)宏的名字不夠清楚,它的本意是讓系統(tǒng)自動選擇。如果設(shè)置源地址為RPMSG_ADDR_ANY,則系統(tǒng)自動選擇一個(gè)空閑的源地址。如果設(shè)置目的地址為RPMSG_ADDR_ANY,則系統(tǒng)會自動發(fā)送一個(gè)查詢消息,根據(jù)名稱查詢對方的地址,相當(dāng)于TCP/IP中的域名解析。
查看代碼,我們可以確認(rèn)以上結(jié)論。第一個(gè)函數(shù)是rpmsg_create_ept(),提供源地址、目的地址后,它創(chuàng)建rpmsg endpoint(節(jié)點(diǎn))。
下面代碼顯示,如果調(diào)用rpmsg_create_ept()時(shí)指定了源地址,會調(diào)用rpmsg_is_address_set設(shè)置源地址,相當(dāng)于TCP/IP中的Bind。如果調(diào)用rpmsg_create_ept()時(shí)沒有指定源地址,則會調(diào)用rpmsg_get_address(),自動從設(shè)備中沒有使用的地址中取一個(gè)地址。
// 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;
}
如果調(diào)用rpmsg_create_ept()時(shí)沒有指定目的地址,會調(diào)用rpmsg_send_ns_message()發(fā)送消息,之后就會返回。如果另外一側(cè)返回消息后,會觸發(fā)的調(diào)用rpmsg_virtio_rx_callback()。在rpmsg_virtio_rx_callback中,從消息中得到entpoint信息,檢查其中的目的地址,如果目的地址是ANY,就會從消息中提取出遠(yuǎn)端地址,賦值給本地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
+關(guān)注
關(guān)注
8文章
1434瀏覽量
83782 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3346瀏覽量
60426
發(fā)布評論請先 登錄
想在引導(dǎo)加載程序中運(yùn)行時(shí)擦除和寫入應(yīng)用程序,否需要配置 PreTaskHook 中第二張圖片中提到的內(nèi)核 MPU?
TMS320F28xxx DSP:從內(nèi)部閃存運(yùn)行應(yīng)用程序的全面指南
構(gòu)建示例應(yīng)用程序MCSPTR2AK396的問題求解
RDMA設(shè)計(jì)56:如何設(shè)計(jì)基于RDMA的應(yīng)用程序
如何構(gòu)建藍(lán)牙應(yīng)用程序?
詳細(xì)解釋Keil-MDK中Code、RO-data、RW-data、ZI-data的含義
基于RT-Thread的RPMsg-Lite異構(gòu)多核通信原理分析 | 技術(shù)集結(jié)
深入了解API:詳解應(yīng)用程序接口的作用和原理
如何在應(yīng)用程序調(diào)試期間分析棧和堆使用情況
學(xué)生適合使用的SOLIDWORKS 云應(yīng)用程序
淺談OpenAMP的應(yīng)用程序中RPMSG_ADDR_ANY含義
評論