analogdevicesinc/libiio

buffer auto disables some time after calling iio_buffer_enable() with windows client

catkira opened this issue · 12 comments

I have some a custom HDL core connected to the FPGA ad9361 core. I need to enable the DAC channel so that my samples get played out on the DAC. I do this by creating a bufffer, then creating a dummy block (which never gets used) and then calling iio_buffer_enable().

The problem is that after a while, about 30s the buffer auto disables itself. Is this a bug or feature?
I noticed that I have to create a block before calling iio_buffer_enable(), therefore I am creating this dummy block. Is there a cleaner way to just enable a DAC channel, maybe by writing directly to a register or so?

(I am using libiio 1.0 on both sides)

I think that if you remove the check in iio_buffer_enable(), you should be able to enable the buffer without creating a block beforehand. In theory this should be fine; Libiio should allow you to create blocks after the buffer has been enabled.

As for the auto-disable... it is definitely not a feature. The buffer is disabled when the iio_buffer is destroyed in local.c, so can you check if the buffer gets destroyed after 30 seconds?

I think that if you remove the check in iio_buffer_enable(), you should be able to enable the buffer without creating a block beforehand. In theory this should be fine; Libiio should allow you to create blocks after the buffer has been enabled.

patching libiio is not a soltuion for me, because I don't want to maintain my own version of libiio ^^

As for the auto-disable... it is definitely not a feature. The buffer is disabled when the iio_buffer is destroyed in local.c, so can you check if the buffer gets destroyed after 30 seconds?

I don't close the buffer in any way. Is there a debug feature that allows me to observe whether the buffer is still enabled from outside? Or can I poll the buffer enabled status?

I did a bit debugging, after around 30s axi_dmac_terminate_all() gets called, so I think the buffer gets destroyed from somewhere.

Also when I do cat enable in /sys/bus/iio/devices/iio:device2/buffer I get a 0 after 30s.

But I figured I can enable the DAC output by just doing echo 1 > enable in /sys/bus/iio/devices/iio:device2/buffer and then it stays enabled indefinitely. So I will just set this iio attribute instead of calling iio_buffer_enable(). That solves it for me, but I still wonder why the buffer gets destroyed after a while.

I think that if you remove the check in iio_buffer_enable(), you should be able to enable the buffer without creating a block beforehand. In theory this should be fine; Libiio should allow you to create blocks after the buffer has been enabled.

patching libiio is not a soltuion for me, because I don't want to maintain my own version of libiio ^^

That's not what I was suggesting. We can probably remove this check in Libiio.

I did a bit debugging, after around 30s axi_dmac_terminate_all() gets called, so I think the buffer gets destroyed from somewhere.

Also when I do cat enable in /sys/bus/iio/devices/iio:device2/buffer I get a 0 after 30s.

But I figured I can enable the DAC output by just doing echo 1 > enable in /sys/bus/iio/devices/iio:device2/buffer and then it stays enabled indefinitely. So I will just set this iio attribute instead of calling iio_buffer_enable(). That solves it for me, but I still wonder why the buffer gets destroyed after a while.

Well, that's a solution I guess, but it would be better to figure out what's going on.

ok, I can try to make a minima example tomorrow.

I think it's realy like I described. I create a buffer, create a block, enable the buffer
and then after about 30s the buffer gets disabled. I noticed that the function axi_dmac_terminate_all() inside dma-axi-dmac.c gets called. It gets probably called via libiio's iio_buffer_cancel() or iio_buffer_destroy()

Did your app set a 30-seconds timeout somewhere? That sounds like a strange value. Libiio typically uses a 1 second timeout value for the local backend, and a 5 seconds timeout value for the network and USB backends.

The 30s timeout only happens when the remote client is a windows machine - very strange. As workaround I tried to set the "enable" attribute of the buffer via iio_device_buffer_attr_write_longlong() but it did not work, because "enable" is apparently not a normal attribute, iio_attr also does not show it:
image
but I can enable it directly via command line with:
image
Is there a reason why libiio does not allow to set the enable attribute?

I did not implement the new attr API yet, if it is possible with the new API I will change my code to use the new API.

Is there a reason why libiio does not allow to set the enable attribute?

It is considered a "protected attribute", because it is used internally by Libiio; On version v0.25 and before, it is set when you call iio_device_create_buffer and you didn't really have a way to change it manually.

I did not implement the new attr API yet, if it is possible with the new API I will change my code to use the new API.

The new API does allow you to do that, yes. Creating a iio_buffer in the new API does not auto-enable streaming, and you can call iio_buffer_enable or iio_buffer_disable.
(You will get a "cannot enable buffer before creating blocks" error but we can get rid of that if there is a use-case where you want to enable the buffer without creating any iio_blocks first.)

Yes I am calling iio_buffer_enable() already and I create a dummy block to get around this error message. But this approach has the "auto-disable after 30s" problem :)

Yes I am calling iio_buffer_enable() already and I create a dummy block to get around this error message. But this approach has the "auto-disable after 30s" problem :)

Ok, you said that setting the "enable" manually did not work, I understood that it was still giving you the 30s timeout issue. Is it not the case then?

Ok, you said that setting the "enable" manually did not work, I understood that it was still giving you the 30s timeout issue. Is it not the case then?

yes it still gives me the 30s timeout when I do it from my Windows-WSL system, but the timeout is not there when I do it from my native linux system.