cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Anonymous
Not applicable
2,538 Views

Address of shared buffers provided by RPMSG driver in Linux- FreeRTOS AMP system on ZYNQ zc702evk target

Environment:

  • Xilinx Zynq zc702evk Platform
  • Petalinux v2013-10
  • Linux-FreeRTOS AMP System , ug978-petalinux-zynq-amp


Problem Description:
In Linux-FreeRTOS AMP system, Linux RPMSG driver provides buffers for consumption by the FreeRTOS. The physical address of buffers provided by the Linux is not used as such by the FreeRTOS, instead FreeRTOS application masks Most Significant Byte of the address before accessing the memory.


The Linux RPMSG bus driver puts buffers in the vring descriptors of Virtqueue , which are supposed to carry the physical address, then why is the address not used by the FreeRTOS application without modification. In fact, buffer address provided by the Linux RPMSG driver does not even present in the shared memory region, and therefore masking is required to get the correct data from the memory.


So the question is, why addresses of buffers posted by the Linux do not reflect actual physical address in memory?

See the FreeRTOS application code snippet below, which does this address masking;

/* Function to receive message from Linux from rxvring. */
void read_message(void)
{
    struct vring_used volatile *ring_rx_used = (void *)RING_RX_USED;
    unsigned int index = ring_rx_used->idx % VRING_SIZE;

    struct vring_desc volatile *ring_rx = (void *)RING_RX;
    
    //-------------------------    WHYYYYYYYYYYYYYYYYYYYY --------------------------------
    //WHY VRING ADDR MASK IS REQUIRED , AS VRING DESC ARE SUPPOSED TO CARRY PHYSICAL ADDRESS
    //---------------------------------------------------------------------------------------
    
    
    struct rpmsg_hdr *hdr = (struct rpmsg_hdr *)(ring_rx[index].addr &
            VRING_ADDR_MASK);

    /* Update index */
    ring_rx_used->ring[index].id = index;
    ring_rx_used->ring[index].len = PACKET_LEN_MAX;
    ring_rx_used->idx += 1; // last index 0 keep increasing

    /* Create a req structure to pass to handler */
    struct remoteproc_request req;
    req.__hdr = hdr;
    req.state = *(unsigned int *)hdr->data;

    if (rxcallback_handler != NULL) {
        rxcallback_handler(&req, hdr->data, hdr->len);
    }

    Xil_L1DCacheFlush();
    return;
}

Thanks in advance for any help.

Tags (4)
0 Kudos
0 Replies