Post Go back to editing

FMCOMMS5 & ZC706 NO-OS

Hi,


I'm using the fmcomms5 with the zc706 board. I downloaded from the github repository the vhd (2021.r1) and the no-os(2021.r1). https://github.com/analogdevicesinc/hdl/releases/tag/2021_r1 , https://github.com/analogdevicesinc/no-os/tree/2021_R1 . 
My first task is to receive and transmit a sine wave. 
In reception, I have not encountered any problems. I follow the examples and I'm able to receive from all the two chips both channels and I can save and see the received signals both in a buffer (adc_buffer) and in DDR. 

Now I would like to know how I can transmit custom data save in DDR. I tried to follow the same order and procedure used in the reception but it doesn't work. 

To follow a summary of the functions called and the order of the main.c with the relative problems encountered.

  • chip 1 Initialization : 

	default_init_param.spi_param.extra = &xil_spi_param;
	default_init_param.spi_param.platform_ops = &xil_spi_ops;
// NOTE: The user has to choose the GPIO numbers according to desired
// carrier board.
	default_init_param.gpio_resetb.number = GPIO_RESET_PIN;
	default_init_param.gpio_sync.number = GPIO_SYNC_PIN;
	default_init_param.gpio_cal_sw1.number = GPIO_CAL_SW1_PIN;
	default_init_param.gpio_cal_sw2.number = GPIO_CAL_SW2_PIN;
	default_init_param.rx1rx2_phase_inversion_en = 1;
	default_init_param.xo_disable_use_ext_refclk_enable = 1;
	default_init_param.rx_synthesizer_frequency_hz = rx_carrier_freq1;
	default_init_param.tx_synthesizer_frequency_hz = tx_carrier_freq1;


	ad9361_init(&ad9361_phy, &default_init_param);

	ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config);
	ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config);
 

  • chip 2 Initialization : 
  • axi_dmac_init(&rx_dmac, &rx_dmac_init);
  • axi_dmac_init(&tx_dmac, &rx_dmac_init);
  • At this point I change the parameter for the first and second chip for my task (change tx and rx sampling freq, bandwidth...)

  • Now I have done

axi_adc_init(&ad9361_phy->rx_adc,&rx_adc_init);
axi_adc_init(&ad9361_phy_b->rx_adc,&rx_adc_init);

axi_dac_init(&ad9361_phy->tx_dac, &tx_dac_init);
axi_dac_init(&ad9361_phy_b->tx_dac, &tx_dac_init);

axi_dac_set_datasel(ad9361_phy->tx_dac, -1, AXI_DAC_DATA_SEL_DMA);
axi_dac_set_datasel(ad9361_phy_b->tx_dac, -1, AXI_DAC_DATA_SEL_DMA);

I saved my custom sine wave in DDR and then I try to transmit:

unsigned long long *puntatore_DDR_DAC= (unsigned long long*)0xA000000;

				for(int i = 0; i< 1024 ;i++){
					*(puntatore_DDR_DAC+i) = my_sinelut_iq[i];
				}

				//check_dac_init = axi_dac_init(&ad9361_phy_b->tx_dac, &tx_dac_init);
				//printf("\n\ncheck dac init = %ld\n\n",check_dac_init);
				//axi_dac_set_datasel(ad9361_phy_b->tx_dac, -1, AXI_DAC_DATA_SEL_DMA);

				struct axi_dma_transfer trasmissione = {
						// Number of bytes to write/read
						.size = 1600,
						// Transfer done flag
						.transfer_done = 0,
						// Signal transfer mode
						.cyclic = CYCLIC,
						// Address of data source
						.src_addr = (uintptr_t)DAC_DDR_BASEADDR,
						// Address of data destination
						.dest_addr = 0
					};
				/* Transfer the data. */
				axi_dmac_transfer_start(tx_dmac, &trasmissione);

				axi_dmac_transfer_wait_completion(rx_dmac, 500);

				/* Flush cache data. */
				//Xil_DCacheInvalidateRange((uintptr_t)DAC_DDR_BASEADDR,sizeof(my_sinelut_iq));
				Xil_DCacheInvalidateRange((uintptr_t)DAC_DDR_BASEADDR,1600);

My questions are:

Q1:

is the sequence of the called function correct? I have a problem because it seems that the first chip dac initialization does not work, I can see nothing from the first chip. I can see a wrong transmission when I change the order in main.c as follow:
- initialization chip 1
-axi_dac_init() chip 1
-axi_dac_set_datasel chip 1
-initialization chip 2
-axi_dac_init() chip 2
-axi_dac_set_datasel chip 2
-axi_dmac_init  for tx core
-axi_dmac_init  for rx core

Q2:

the transmitted signal using the main.c sequence of Q1 is not the sine wave that I expect and I save it in DDR. someone can help me to understand how to use correctly the function in order to save and transmit a simple sine wave saved in DDR?
I'm using the DAC_DDR_BASEADDR and I want to transmit a signal saved from that base address

Thank you all 
Best regards.

Top Replies

  • Moved to Microcontroller no-OS Drivers forum.

  • This thread is moved already to the proper forum.

    Regards,
    Iulia

  • This is the screenshot of my question and the section where is posted. Is this right?

    If it is not the correct could you send me the correct one?

    Best regards.

  • Hi  ,

    Q1. The initialization sequence in main.c of the ad9361 project is listed below. The used settings are:

    #define XILINX_PLATFORM
    #define FMCOMMS5
    #define ADC_DMA_EXAMPLE
    #define ADC_DMA_IRQ_EXAMPLE
    #define DAC_DMA_EXAMPLE
     (other settings unchanged in app_config.h, hw setup: FMCOMMS5+ZC706)

    1. init chip 1

    2. init chip 2

    3. init tx_axi_dmac

    4. init rx_axi_dmac

    5. init axi_dac and axi_adc for chip 2 and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    6. init axi_dac and axi_adc for chip 1and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    7. load custom data for axi_dac for chip 1 (in sample project this is sine_lut_iq)

    Then, you can create a write_transfer and initiate it like below:

    	struct axi_dma_transfer transfer = {
    		// Number of bytes to write/read
    		.size = sizeof(sine_lut_iq),
    		// Transfer done flag
    		.transfer_done = 0,
    		// Signal transfer mode
    		.cyclic = CYCLIC,
    		// Address of data source
    		.src_addr = (uintptr_t)dac_buffer,
    		// Address of data destination
    		.dest_addr = 0
    	};
    
    	/* Transfer the data. */
    	axi_dmac_transfer_start(tx_dmac, &transfer);
    
    	/* Flush cache data. */
    	Xil_DCacheInvalidateRange((uintptr_t)dac_buffer, sizeof(sine_lut_iq));
    
    	no_os_mdelay(1000);

    For reading the data, you can use the following code sequence:

    struct axi_dma_transfer read_transfer = {
    	// Number of bytes to write/read
    	.size = 2048 * AD9361_ADC_DAC_BYTES_PER_SAMPLE *
    			(ad9361_phy_b->tx_dac->num_channels + ad9361_phy->tx_dac->num_channels),
    	// Transfer done flag
    	.transfer_done = 0,
    	// Signal transfer mode
    	.cyclic = NO,
    	// Address of data source
    	.src_addr = 0,
    	// Address of data destination
    	.dest_addr = (uintptr_t)ADC_DDR_BASEADDR
    };
    
    /* Read the data from the ADC DMA. */
    axi_dmac_transfer_start(rx_dmac, &read_transfer);
    
    /* Wait until transfer finishes */
    status = axi_dmac_transfer_wait_completion(rx_dmac, 500);
    if(status < 0)
    	return status;
    
    Xil_DCacheInvalidateRange((uintptr_t)ADC_DDR_BASEADDR, 2048 * AD9361_ADC_DAC_BYTES_PER_SAMPLE *
    		(ad9361_phy_b->tx_dac->num_channels + ad9361_phy->tx_dac->num_channels));

    You can retrieve the data received in the memory with the following command, launched from the no-OS folder:

    xsct legacy/scripts/xilinx_capture.tcl ZYNQ_PS7 0x800000 16384 8 16

    This will generate 8 csv files, one for each channel.

    By calling the following two functions, you can enable the internal loopback, and then you will have on Rx exactly what you place on Tx:

    ad9361_bist_loopback(ad9361_phy, 1);
    ad9361_bist_loopback(ad9361_phy_b, 1);

    Q2. The transmitted data is interleaved and you should construct the data to send accordingly. You should take a look at the following thread:

    https://ez.analog.com/microcontroller-no-os-drivers/f/q-a/556507/when-to-use-axi_dmac_transfer-vs-axi_dmac_transfer_nonblocking/453453

    Please let us know if you have further questions. The no-OS sample project for ad9361 will be updated accordingly.

    Regards,

    George

  • Hi  

    thank you for your reply. 
    When I use the order 

    1. init chip 1

    2. init chip 2

    3. init tx_axi_dmac

    4. init rx_axi_dmac

    5. init axi_dac and axi_adc for chip 2 and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    6. init axi_dac and axi_adc for chip 1and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    I notice that only the second chip transmits the signal. but when I use this order:

    1. init chip 1

    2. init axi_dac and axi_adc for chip 1 and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    3. init chip 2

    4. init axi_dac and axi_adc for chip 2 and select data source as AXI_DAC_DATA_SEL_DMA for tx_dac

    5.  init tx_axi_dmac

    6. init rx_axi_dmac

    both chips seem to transmit correctly. Is this possible? 

    Regards.
    Riccardo

  • Hi  ,

    You can have a look here: https://github.com/analogdevicesinc/no-OS/pull/1567

    It was tested with the settings specified in my previous reply.

    It is possible that some of the initialization do not work as expected in the first case.

    Regards,

    George

  • thank you so much  
    I'll try to modify the initialization and I'll send feedback if it works. 

    Regards,

    Riccardo

  • Hi,  ,
    I'm still working on this project, I changed GitHub repository and I started working on the master branch. 
    I built the project, the no-os and  vhd
    used settings 

    #define XILINX_PLATFORM
    #define FMCOMMS5
    #define ADC_DMA_EXAMPLE
    #define DAC_DMA_EXAMPLE

    and I looped back tx and rx channels (first chip with first chip and second with the second)

    • I connected tx channels to the spectrum analyzer and I can see the transmitted sine wave 
    • when I debug the DDR from the base address I can see only the received signals of the first chip and the second chip is stuck

    could you help me?  I don't change the c files. is the original.

    regards,
    Riccardo

  • Hi ,

    Does this happen consistently (second chip stuck)?

    An option would be to check that the sync pin works correctly and that multi-chip synchronization is performed correctly.

    Regards,

    George