zoukankan      html  css  js  c++  java
  • 【分享】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);
    
    	}
    	
    	... ...
    }
    

     

  • 相关阅读:
    Django错误笔记1
    Django学习笔记1 启动及配置一个Django项目
    ubuntu 安装mysqldb
    二叉树 总结
    序列二叉树和反序列 (不是自己做的)
    二叉树的路径
    二叉搜索树的后续遍历
    二叉树层序遍历
    栈的压入 弹出序列
    包含 min的栈
  • 原文地址:https://www.cnblogs.com/hankfu/p/13255193.html
Copyright © 2011-2022 走看看