AnsweredAssumed Answered

No-OS software, AD9364

Question asked by GeoffreyM on Aug 15, 2017

I would like to point out a bug. The driver initialization, ad9361_init, allocates space for the various structures required, using malloc(). Once the driver is initialized, a pointer attached to these. If, for any reason, initialialization fails, the space is released using free() and the pointer untouched. However, in main.c, the result of ad9361_init is not tested, the function being called as (void), although not explicitly cast as such. Subsequently the code makes further function calls which dereference the pointer, causing a fatal error. The dynamic deallocation of memory based on the failure of something fully expected to be there seems harsh grounds for its destruction, its surviving, albeit dysfunctional, form being useful in determining the reason for its unexpected crankiness. Godwin's law beckons, I shall desist. :-)


I noticed this because, having dutifully set, in config.h,

#define AD9361_DEVICE               0 /* set it 1 if AD9361 device is used, 0 otherwise */ #define AD9364_DEVICE               1 /* set it 1 if AD9364 device is used, 0 otherwise */ #define AD9363A_DEVICE               0 /* set it 1 if AD9363A device is used, 0 otherwise */

...this giving the appearance of being sufficient, I noticed that the number of channels in the hdl was still set to 4 when the autotune function executed, causing it to fail. It is also necessary to set:

     0,          //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable main.c


rather mad, because in ad9361_init, there is the following:

     if (AD9364_DEVICE) {           phy->pdata->rx2tx2 = false;           phy->pdata->rx1tx1_mode_use_rx_num = 1;           phy->pdata->rx1tx1_mode_use_tx_num = 1;      }

The trouble is, it's in the wrong place, the channel count having already been set about 20 lines earlier:

#ifndef AXI_ADC_NOT_PRESENT      phy->adc_conv->chip_info = &axiadc_chip_info_tbl[phy->pdata->rx2tx2 ? ID_AD9361 : ID_AD9364]; #endif


Easily found with the debugger, but probably worth fixing.


Anyhow, compliments! Apart from these niggles, having created your IP using the recommended makefile method, a recommendation I would endorse, and a little piece of IP to generate the required IOBUF instantiations for the GPIO ports on the block diagram, rather than, as in your project, and indeed as offered by Xilinx as a solution, hidden at the level of the outermost wrapper[1], everything worked out of the box.


The DMA interfaces appear to be AXI4-stream compatible, valid being tready on the DAC side and tvalid on the ADC side, non-stallable, of course. Has anyone else tried this? If not, I guess the interface would be fairly simple. From the hdl, on the DAC side, data is expected whenever valid (tready to the AXI4 source) is asserted. This corresponds with AXI4 (tready & tvalid) as long as the source always has data available. Similarly, on the ADC side, valid (tvalid to the sink) is asserted in the same time slot as the data, the sink needing to be ready to accept. Must be a common requirement, things like COFDM needing much parallel computation only really possible in logic, making DMA transfer at the endpoints of a chain of encoding and decoding functions. My intention is to use stream FIFO's, together with intermediate clock converters. The reason for the latter being the tendency for people to define asynchronous clocks as easy multiples of each other. Being of slightly different sources, but highly accurate, their edges drift through timing windows at a snail's pace, and are quite good demonstrators of metastability.


Best regards



[1] which, as a prevaricator in the face of more important tasks, I made general in scope, allowing any configuration of 1 to 64 ports of arbitrary width, showing the selected GPIO bits correctly-indexed on the output ports, configurable for safety as INOUT, IN only or OUT only, sad, I know, but free together with the hdl source and tcl to create the customisation GUI to anyone interested, usual disclaimer of responsibility. It should be known Xilinx recommend a different solution, in which you provide a template IOBUF at wrapper level, which is substituted and can be upgraded to their latest device automatically, which may have a different name. For instance, the ad_iobuf instantiated in the AD project used in the demo is never used, it becomes a standard IOBUF. A special case, it is not intended to be used, but I would personally like to know when this sort of thing happens. GPIO is quite messy, you leave pippo_i, pippo_o and pippo_t unconnected  and they connect to pippo_p at a level beyond the scope of the bd.