【分享】OpenAMP的RPMSG_ADDR_ANY含義


 

 

在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);

	}
	
	... ...
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM