AnsweredAssumed Answered

FMCOMMS3 ADC DMA logging data rate

Question asked by notme on Jul 22, 2015
Latest reply on Jul 30, 2015 by mhennerich

Hi,

 

I'm using the zedboard with FMCOMMS3 with hdl_2014_r2 and NO_OS (2014_r2).

I am trying to log data from the FMCOMMS3 over ethernet using UDP.

 

I am queuing the DMA to constantly collect ADC data, and I use polling to transmit over UDP once a packet of data is collected.  I'm receiving exactly 4X less data than the fmcomms3 board should be producing.

 

Do you have any recommendations on things I can try to debug the problem?  I borrowed heavily from thread 40344

 

uint32_t adc_capture_submit(uint32_t size, uint32_t start_address)
{
          uint32_t reg_val;
          uint32_t transfer_id;
          uint32_t length;

          adc_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE);

          adc_dma_read(AXI_DMAC_REG_TRANSFER_ID, &transfer_id);
          adc_dma_read(AXI_DMAC_REG_IRQ_PENDING, &reg_val);
          adc_dma_write(AXI_DMAC_REG_IRQ_PENDING, reg_val);

          adc_dma_write(AXI_DMAC_REG_DEST_ADDRESS, start_address);
          adc_dma_write(AXI_DMAC_REG_DEST_STRIDE, 0x0);

          adc_dma_write(AXI_DMAC_REG_X_LENGTH, size - 1);
          adc_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0);

          adc_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1);
          /* Wait until the new transfer is queued. */
          do {

                    adc_dma_read(AXI_DMAC_REG_START_TRANSFER, &reg_val);
          }
          while(reg_val == 1);

          return transfer_id;
}


                    adc_dma_read(AXI_DMAC_REG_START_TRANSFER, &reg_val);
          }
          while(reg_val == 1);

          return transfer_id;
}

 

void adc_capture_wait(uint32_t transfer_id)
{
          uint32_t reg_val;

          /* Wait until the transfer with the ID transfer_id is completed. */
          do {
                    adc_dma_read(AXI_DMAC_REG_TRANSFER_DONE, &reg_val);
          }
          while((reg_val & (1 << transfer_id)) != (1 << transfer_id));
}

 

And in main,

const unsigned int BUFFER_ADDR[2] = {ADC_DDR_BASEADDR+HEADER_SIZE, ADC_DDR_BASEADDR + ADC_TRANSFER_SIZE + 2*HEADER_SIZE};
buffer_transfer_id[0] = adc_capture_submit(ADC_TRANSFER_SIZE, BUFFER_ADDR[0]);
buffer_transfer_id[1] = adc_capture_submit(ADC_TRANSFER_SIZE, BUFFER_ADDR[1]);

for(ever) {
    for (i = 0; i < 2; i++) {
        adc_capture_wait(buffer_transfer_id[i]);
        Xil_DCacheInvalidateRange(BUFFER_ADDR[i], ADC_TRANSFER_SIZE);
        send_data_to(BUFFER_ADDR[i]-HEADER_SIZE, ADC_TRANSFER_SIZE + HEADER_SIZE, &ipaddr, port);
        buffer_transfer_id[i] = adc_capture_submit(ADC_TRANSFER_SIZE, BUFFER_ADDR[i]);
    }
}
    }

 

void send_data_to (unsigned int address, unsigned int size, struct ip_addr *addr, u16_t port){

    struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_REF);
    p->payload = (void*) address; //data in payload is volatile, could cause problems
    ((uint32_t*)p->payload)[0] = 60 + (1 << 8);
    ((uint32_t*)(p->payload))[1] = packet_count++;
    udp_sendto(pcb, p, addr, port); //destination port
    xemacif_input(&server_netif);
    pbuf_free(p);
}

I set the sampling rate to 15Mhz.  ad9361_set_rx_sampling_freq(ad9361_phy, 15360000);

I am only using one channel, I'm checking for lost packets, and I'm getting around 112,000 packets of 8184 bytes in one minute, so 15Mbytes per second.  I'm expecting I and Q data of 16 bits a piece, at 15Mhz., so I'm expecting 4 times as much data.

 

Doubling the sampling frequency doubles the data I log, so I don't think there is a bottleneck.

Outcomes