Post Go back to editing

AD799x libiio why does iio_device_create_buffer return null & EINVALID?

I'm in the process of integrating two AD7997 ADCs into a new carrier board for an NXP i.MX6.

The sysfs entries return values from in_voltage<x>_raw and it appears that communication to the AD7997s via I2C and IIO interface is working correctly in the Linux file system.

The problem comes when trying to obtain a buffer for each of the devices using Lib IIO in a C++ class - iio_device_create_buffer always returns NULL with errno=-EINVALID.

I think I must be doing something wrong in the device tree or module setup, although I've set up the device tree entries per the advice of the AD799X wiki entries.

Can anyone see my mistake?

Device Tree entries:

/ {
# ...
	reg_3v3_sw: regulator-3v3-sw {
		compatible = "regulator-fixed";
		regulator-name = "3.3V_SW";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		regulator-always-on;
	};
	#...
};

# ...

&i2c1 {
	status = "okay";

	/* AD7997, 8-channel, 10-bit ADC */
	ad7997_IC801@33 {
		compatible = "adi,ad7997";
		reg = <0x21>;
        vref-supply = <&reg_3v3_sw>;
        vcc-supply = <&reg_3v3_sw>;
	};
	ad7997_IC800@34 {
		compatible = "adi,ad7997";
		reg = <0x22>;
        vref-supply = <&reg_3v3_sw>;
        vcc-supply = <&reg_3v3_sw>;
	};
};

Kernel Modules loaded on Target:

ad799x                          28672  0
industrialio_triggered_buffer   16384  1 ad799x
kfifo_buf                       16384  1 industrialio_triggered_buffer

The contents of the iio:device1 in sysfs:

root@imx6:/sys/bus/iio/devices/iio:device1# find . -type f -print -exec cat {} \; >> ~/iio\:device1.log

./in_voltage6_raw
0
./scan_elements/in_voltage7_type
be:u10/16>>2
./scan_elements/in_voltage0_index
0
./scan_elements/in_voltage0_type
be:u10/16>>2
./scan_elements/in_voltage3_index
3
./scan_elements/in_voltage6_index
6
./scan_elements/in_voltage6_type
be:u10/16>>2
./scan_elements/in_voltage7_en
1
./scan_elements/in_voltage4_en
1
./scan_elements/in_voltage1_en
1
./scan_elements/in_voltage5_type
be:u10/16>>2
./scan_elements/in_timestamp_index
8
./scan_elements/in_voltage1_index
1
./scan_elements/in_voltage4_index
4
./scan_elements/in_timestamp_en
1
./scan_elements/in_voltage4_type
be:u10/16>>2
./scan_elements/in_voltage7_index
7
./scan_elements/in_voltage6_en
1
./scan_elements/in_voltage3_en
1
./scan_elements/in_voltage0_en
1
./scan_elements/in_voltage3_type
be:u10/16>>2
./scan_elements/in_voltage2_index
2
./scan_elements/in_timestamp_type
le:s64/64>>0
./scan_elements/in_voltage2_type
be:u10/16>>2
./scan_elements/in_voltage5_index
5
./scan_elements/in_voltage5_en
1
./scan_elements/in_voltage2_en
1
./scan_elements/in_voltage1_type
be:u10/16>>2
./in_voltage3_raw
308
./in_voltage7_raw
0
./power/runtime_suspended_time
0
./power/autosuspend_delay_ms
./power/runtime_active_time
0
./power/control
auto
./power/runtime_status
unsupported
./dev
249:1
./buffer/enable
0
./buffer/watermark
1
./buffer/length
3456
./in_voltage0_raw
0
./in_voltage4_raw
0
./in_voltage1_raw
994
./trigger/current_trigger
./in_voltage5_raw
172
./current_timestamp_clock
realtime

C++ function to populate buffer & channel list:

void IioDriver::populateDevList()
{
    /* iio_context* */ m_ctx = iio_create_default_context(); 
    LOG_DEBUG("IIODRIVER context name ", iio_context_get_name(ctx));
    if(errno) {
        LOG_DEBUG(std::string("CreateContext ") + std::strerror(errno) + std::to_string(errno));
        errno = 0;
    }
    
    int deviceCount = 0;     /* System has 2x AD7997 (I2C: IC801 = 0x21, IC 800 = 0x22) and 1x stmpe-adc (ignore this) */
    if (!m_ctx || (deviceCount = iio_context_get_devices_count(m_ctx)) < 2) 
        throw std::runtime_error("No IIO devices!");
    
    for(int dev_idx = 0; dev_idx< deviceCount; ++dev_idx) { 
        iio_device *dev = 0; //new iio_device; //nullptr;
        if((dev = iio_context_get_device(m_ctx, dev_idx)) == NULL) {
            LOG_ERROR(std::string("Skipping device - getDevice ") + std::strerror(errno) + std::to_string(errno));
            continue;
        }
                
        std::string name = iio_device_get_name(dev);
        if(!name.compare("AD7997")) {
            LOG_ERROR(name + " is not AD7997!");
            continue;
        }      
        
        std::vector<iio_channel*> channels; // Pointers to each channel for later processing
        std::vector<size_t> slot; // Used to map channel in another part of the driver
        unsigned int lastDev = iio_device_get_channels_count(dev); // OK
        for(unsigned int chn_idx = 0; chn_idx < lastDev; ++chn_idx) { // see what's available on a device...
            iio_channel *chn = nullptr;
            chn = iio_device_get_channel(dev, chn_idx);
            if(chn == nullptr)
                continue;
            if(iio_channel_is_scan_element(chn)) { // For now, just enable all the channels.
                iio_channel_enable(chn); // OK
            }
            channels.push_back(chn);
            slot.push_back(dev_idx * chn_idx); // Slot will be used to map ADC channels to MQTT topics in the correct order
        }
        
        ssize_t totalBufLen = iio_device_get_sample_size(dev) * m_buf_size * lastDev; // m_buf_size = 16
        iio_buffer* iiobuf = iio_device_create_buffer(dev, totalBufLen, 0); // FAILS: -EINVALID
        if(errno || (iiobuf == NULL)) {          
            LOG_ERROR(std::string("Got buffer error: ") + std::strerror(errno) + "(" + std::to_string(errno) + ")");
        }
        else {
            m_devList.push_back(Device(iiobuf, channels, slot));
            iio_buffer_refill(iiobuf); // Now retrigger the buffer to fill
            LOG_INFO("Assigned a buffer for " + name + " len  " + std::to_string(totalBufLen));
        }
    }
}

Parents
  • Hi,

    Your device has a "trigger/current_trigger", so it is safe to assume that it requires a trigger device.

    If you don't already have a trigger device, you can create a software one with the iio-trig-sysfs driver: iio-trig-sysfs driver [Analog Devices Wiki]

    This allows you to configure when exactly will the samples be read from the hardware: periodically with a timer, on a IRQ, manually from a script...

    Once your trigger is created you should have a iio:triggerX device listed in libiio. You can use the function iio_device_set_trigger( ) to bind the new trigger to your iio:device1 device. After that, you should be able to create a buffer.

    Cheers,

    -Paul

  • Thanks Paul,

    I had that thought too, so I made sure that a trigger was present:

    root@apalis-imx6:/sys/kernel/config/iio# lsmod
    Module                  Size  Used by
    iio_trig_hrtimer       16384  4
    industrialio_sw_trigger    16384  1 iio_trig_hrtimer
    industrialio_configfs    16384  2 industrialio_sw_trigger
    can_raw                20480  2
    can                    24576  1 can_raw
    bluetooth             327680  2
    usb_f_rndis            24576  2
    u_ether                20480  1 usb_f_rndis
    mxc_v4l2_capture       40960  0
    ipu_bg_overlay_sdc     16384  1 mxc_v4l2_capture
    ipu_still              16384  1 mxc_v4l2_capture
    ipu_prp_enc            16384  1 mxc_v4l2_capture
    ipu_csi_enc            16384  1 mxc_v4l2_capture
    ipu_fg_overlay_sdc     16384  1 mxc_v4l2_capture
    v4l2_int_device        16384  1 mxc_v4l2_capture
    ad799x                 28672  0
    industrialio_triggered_buffer    16384  1 ad799x
    kfifo_buf              16384  1 industrialio_triggered_buffer
    imx_sdma               28672  6
    virt_dma               16384  1 imx_sdma
    flexcan                24576  0
    can_dev                24576  1 flexcan
    libcomposite           53248  10 usb_f_rndis
    configfs               40960  6 industrialio_configfs,iio_trig_hrtimer,industrialio_sw_trigger,usb_f_rndis,libcomposite
    

    I updated my populate routine so that it loops through all devices to look for a trigger first. Once a trigger's found, the code loops through all attributes (for debug purposes) then looks for the two ad7997 devices, assigns a trigger to them and then attempts to get a buffer, like before.

    2022-02-07, 14:11:42.089361 <info> This trigger is: mytrig, id: trigger0
    2022-02-07, 14:11:42.091023 <info> Attribute sampling_frequency: 100
    2022-02-07, 14:11:42.091855 <info> End of attributes
    2022-02-07, 14:11:42.092895 <info> ad7997 id iio:device1 Trigger name mytrig
    2022-02-07, 14:11:42.094946 <error> ad7997 id iio:device1 Got buffer error: Invalid argument(22)
    2022-02-07, 14:11:42.097996 <info> ad7997 id iio:device2 Trigger name mytrig
    2022-02-07, 14:11:42.100100 <error> ad7997 id iio:device2 Got buffer error: Invalid argument(22)
    2022-02-07, 14:11:42.100817 <error> stmpe-adc is not AD7997!
    2022-02-07, 14:11:42.101593 <error> mytrig is not AD7997!
    

    Unfortunately, the error is still there and comes from inside local_open() (in local.c, line 956):

    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);

    The full gdb trace is below.

    Breakpoint 5, IioDriver::populateDevList (this=this@entry=0x4c3458) at /usr/src/debug/stupid/0.2-r0/stupid-0.2/src/driver/iiodriver.cpp:157
    157             ssize_t totalBufLen = iio_device_get_sample_size(dev) * m_buf_size * lastDev; // m_buf_size = 16
    (gdb) n
    158             iio_buffer* iiobuf = iio_device_create_buffer(dev, totalBufLen, 0); // FAILS: -EINVALID
    (gdb) s
    iio_device_create_buffer (dev=dev@entry=0x4c3560, samples_count=samples_count@entry=3456, cyclic=cyclic@entry=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/buffer.c:47
    47              unsigned int sample_size = iio_device_get_sample_size(dev);
    (gdb) n
    49              if (!sample_size || !samples_count)
    (gdb) n
    52              buf = malloc(sizeof(*buf));
    (gdb) n
    53              if (!buf) {
    (gdb) n
    58              buf->dev_sample_size = sample_size;
    (gdb) n
    59              buf->length = sample_size * samples_count;
    (gdb) n
    61              buf->mask = calloc(dev->words, sizeof(*buf->mask));
    (gdb) n
    62              if (!buf->mask) {
    (gdb) n
    71              memcpy(buf->mask, dev->mask, dev->words * sizeof(*buf->mask));
    (gdb) n
    73              ret = iio_device_open(dev, samples_count, cyclic);
    (gdb) s
    iio_device_open (dev=0x4c3560, samples_count=3456, cyclic=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/device.c:348
    348             for (i = 0; !has_channels && i < dev->words; i++)
    (gdb) n
    349                     has_channels = !!dev->mask[i];
    (gdb) n
    353             if (dev->ctx->ops->open)
    (gdb) n
    354                     return dev->ctx->ops->open(dev, samples_count, cyclic);
    (gdb) s
    local_open (dev=0x4c3560, samples_count=3456, cyclic=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:902
    902     {
    (gdb) n
    908             if (pdata->fd != -1)
    (gdb) n
    911             ret = local_write_dev_attr(dev, "buffer/enable", "0", 2, false);
    (gdb) s     
    local_write_dev_attr (dev=dev@entry=0x4c3560, attr=0x76e5edcc "buffer/enable", src=0x76e5e4d0 "0", len=len@entry=2, type=type@entry=IIO_ATTR_TYPE_DEVICE)
        at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:733
    733             if (!attr)
    (gdb) n
    736             switch (type) {
    (gdb) n
    738                             iio_snprintf(buf, sizeof(buf), "/sys/bus/iio/devices/%s/%s",
    (gdb) n
    753             f = fopen(buf, "we");
    (gdb) n
    754             if (!f)
    (gdb) n
    757             ret = fwrite(src, 1, len, f);
    (gdb) n
    758             fflush(f);
    (gdb) n
    759             if (ferror(f))
    (gdb) n
    761             fclose(f);
    (gdb) n
    762             return ret ? ret : -EIO;
    (gdb) n
    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:912
    912             if (ret < 0)
    (gdb) print ret
    $1 = 2
    (gdb) n
    915             iio_snprintf(buf, sizeof(buf), "%lu", (unsigned long) samples_count);
    (gdb) n
    916             ret = local_write_dev_attr(dev, "buffer/length",
    (gdb) n
    918             if (ret < 0)
    (gdb) print ret
    $2 = 5
    (gdb) n
    921             pdata->cancel_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    (gdb) n
    922             if (pdata->cancel_fd == -1)
    (gdb) n
    925             iio_snprintf(buf, sizeof(buf), "/dev/%s", dev->id);
    (gdb) n
    926             pdata->fd = open(buf, O_RDWR | O_CLOEXEC | O_NONBLOCK);
    (gdb) n
    927             if (pdata->fd == -1) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) display ret
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    951             pdata->cyclic = cyclic;
    1: ret = <optimized out>
    (gdb) n
    954             pdata->samples_count = samples_count;
    1: ret = <optimized out>
    (gdb) n
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) s
    enable_high_speed (dev=0x4c3560) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) s
    820             if (pdata->cyclic) {
    1: ret = <optimized out>
    (gdb) s
    824                     nb_blocks = pdata->max_nb_blocks;
    1: ret = <optimized out>
    (gdb) s
    828             pdata->blocks = calloc(nb_blocks, sizeof(*pdata->blocks));
    1: ret = <optimized out>
    (gdb) n
    829             if (!pdata->blocks)
    1: ret = <optimized out>
    (gdb) s
    832             pdata->addrs = calloc(nb_blocks, sizeof(*pdata->addrs));
    1: ret = <optimized out>
    (gdb) n
    833             if (!pdata->addrs) {
    1: ret = <optimized out>
    (gdb) n
    839             req.id = 0;
    1: ret = <optimized out>
    (gdb) n
    841             req.size = pdata->samples_count *
    1: ret = <optimized out>
    (gdb) n
    845             ret = ioctl_nointr(fd, BLOCK_ALLOC_IOCTL, &req);
    1: ret = <optimized out>
    (gdb) s
    ioctl_nointr (fd=fd@entry=5, request=3222301088, data=data@entry=0x7effec2c) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:124
    124                     ret = ioctl(fd, request, data);
    (gdb) s
    ioctl () at ../sysdeps/unix/syscall-template.S:78
    78      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
    (gdb) n
    79              ret
    (gdb) n
    __syscall_error () at ../sysdeps/unix/sysv/linux/arm/sysdep.S:30
    30              rsb r0, r0, $0
    (gdb) n
    40              mov     r1, r0
    (gdb) n
    41              GET_TLS (r2)
    (gdb) n
    42              ldr     r2, 1f
    (gdb) n
    44      2:      add     r2, r2, pc
    (gdb) n
    45              ldr     r2, [r2]
    (gdb) n
    49              str     r1, [r0, r2]
    (gdb) n
    50              mvn     r0, #0
    (gdb) n
    51              DO_RET(lr)
    (gdb) n
    enable_high_speed (dev=0x4c3560) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:846
    846             if (ret < 0) {
    1: ret = <optimized out>
    (gdb) n
    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) n
    957             if (ret < 0 && ret != -ENOSYS)
    1: ret = -22
    (gdb) n
    988             close(pdata->fd);
    1: ret = -22
    (gdb) n
    989             pdata->fd = -1;
    1: ret = -22
    (gdb) 

    Can you advise how I can check if something is missing or misconfigured on the kernel side?

Reply
  • Thanks Paul,

    I had that thought too, so I made sure that a trigger was present:

    root@apalis-imx6:/sys/kernel/config/iio# lsmod
    Module                  Size  Used by
    iio_trig_hrtimer       16384  4
    industrialio_sw_trigger    16384  1 iio_trig_hrtimer
    industrialio_configfs    16384  2 industrialio_sw_trigger
    can_raw                20480  2
    can                    24576  1 can_raw
    bluetooth             327680  2
    usb_f_rndis            24576  2
    u_ether                20480  1 usb_f_rndis
    mxc_v4l2_capture       40960  0
    ipu_bg_overlay_sdc     16384  1 mxc_v4l2_capture
    ipu_still              16384  1 mxc_v4l2_capture
    ipu_prp_enc            16384  1 mxc_v4l2_capture
    ipu_csi_enc            16384  1 mxc_v4l2_capture
    ipu_fg_overlay_sdc     16384  1 mxc_v4l2_capture
    v4l2_int_device        16384  1 mxc_v4l2_capture
    ad799x                 28672  0
    industrialio_triggered_buffer    16384  1 ad799x
    kfifo_buf              16384  1 industrialio_triggered_buffer
    imx_sdma               28672  6
    virt_dma               16384  1 imx_sdma
    flexcan                24576  0
    can_dev                24576  1 flexcan
    libcomposite           53248  10 usb_f_rndis
    configfs               40960  6 industrialio_configfs,iio_trig_hrtimer,industrialio_sw_trigger,usb_f_rndis,libcomposite
    

    I updated my populate routine so that it loops through all devices to look for a trigger first. Once a trigger's found, the code loops through all attributes (for debug purposes) then looks for the two ad7997 devices, assigns a trigger to them and then attempts to get a buffer, like before.

    2022-02-07, 14:11:42.089361 <info> This trigger is: mytrig, id: trigger0
    2022-02-07, 14:11:42.091023 <info> Attribute sampling_frequency: 100
    2022-02-07, 14:11:42.091855 <info> End of attributes
    2022-02-07, 14:11:42.092895 <info> ad7997 id iio:device1 Trigger name mytrig
    2022-02-07, 14:11:42.094946 <error> ad7997 id iio:device1 Got buffer error: Invalid argument(22)
    2022-02-07, 14:11:42.097996 <info> ad7997 id iio:device2 Trigger name mytrig
    2022-02-07, 14:11:42.100100 <error> ad7997 id iio:device2 Got buffer error: Invalid argument(22)
    2022-02-07, 14:11:42.100817 <error> stmpe-adc is not AD7997!
    2022-02-07, 14:11:42.101593 <error> mytrig is not AD7997!
    

    Unfortunately, the error is still there and comes from inside local_open() (in local.c, line 956):

    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);

    The full gdb trace is below.

    Breakpoint 5, IioDriver::populateDevList (this=this@entry=0x4c3458) at /usr/src/debug/stupid/0.2-r0/stupid-0.2/src/driver/iiodriver.cpp:157
    157             ssize_t totalBufLen = iio_device_get_sample_size(dev) * m_buf_size * lastDev; // m_buf_size = 16
    (gdb) n
    158             iio_buffer* iiobuf = iio_device_create_buffer(dev, totalBufLen, 0); // FAILS: -EINVALID
    (gdb) s
    iio_device_create_buffer (dev=dev@entry=0x4c3560, samples_count=samples_count@entry=3456, cyclic=cyclic@entry=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/buffer.c:47
    47              unsigned int sample_size = iio_device_get_sample_size(dev);
    (gdb) n
    49              if (!sample_size || !samples_count)
    (gdb) n
    52              buf = malloc(sizeof(*buf));
    (gdb) n
    53              if (!buf) {
    (gdb) n
    58              buf->dev_sample_size = sample_size;
    (gdb) n
    59              buf->length = sample_size * samples_count;
    (gdb) n
    61              buf->mask = calloc(dev->words, sizeof(*buf->mask));
    (gdb) n
    62              if (!buf->mask) {
    (gdb) n
    71              memcpy(buf->mask, dev->mask, dev->words * sizeof(*buf->mask));
    (gdb) n
    73              ret = iio_device_open(dev, samples_count, cyclic);
    (gdb) s
    iio_device_open (dev=0x4c3560, samples_count=3456, cyclic=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/device.c:348
    348             for (i = 0; !has_channels && i < dev->words; i++)
    (gdb) n
    349                     has_channels = !!dev->mask[i];
    (gdb) n
    353             if (dev->ctx->ops->open)
    (gdb) n
    354                     return dev->ctx->ops->open(dev, samples_count, cyclic);
    (gdb) s
    local_open (dev=0x4c3560, samples_count=3456, cyclic=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:902
    902     {
    (gdb) n
    908             if (pdata->fd != -1)
    (gdb) n
    911             ret = local_write_dev_attr(dev, "buffer/enable", "0", 2, false);
    (gdb) s     
    local_write_dev_attr (dev=dev@entry=0x4c3560, attr=0x76e5edcc "buffer/enable", src=0x76e5e4d0 "0", len=len@entry=2, type=type@entry=IIO_ATTR_TYPE_DEVICE)
        at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:733
    733             if (!attr)
    (gdb) n
    736             switch (type) {
    (gdb) n
    738                             iio_snprintf(buf, sizeof(buf), "/sys/bus/iio/devices/%s/%s",
    (gdb) n
    753             f = fopen(buf, "we");
    (gdb) n
    754             if (!f)
    (gdb) n
    757             ret = fwrite(src, 1, len, f);
    (gdb) n
    758             fflush(f);
    (gdb) n
    759             if (ferror(f))
    (gdb) n
    761             fclose(f);
    (gdb) n
    762             return ret ? ret : -EIO;
    (gdb) n
    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:912
    912             if (ret < 0)
    (gdb) print ret
    $1 = 2
    (gdb) n
    915             iio_snprintf(buf, sizeof(buf), "%lu", (unsigned long) samples_count);
    (gdb) n
    916             ret = local_write_dev_attr(dev, "buffer/length",
    (gdb) n
    918             if (ret < 0)
    (gdb) print ret
    $2 = 5
    (gdb) n
    921             pdata->cancel_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    (gdb) n
    922             if (pdata->cancel_fd == -1)
    (gdb) n
    925             iio_snprintf(buf, sizeof(buf), "/dev/%s", dev->id);
    (gdb) n
    926             pdata->fd = open(buf, O_RDWR | O_CLOEXEC | O_NONBLOCK);
    (gdb) n
    927             if (pdata->fd == -1) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    934                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    935                     if (chn->index >= 0 && !iio_channel_is_enabled(chn)) {
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    (gdb) n
    946                             if (ret < 0)
    (gdb) display ret
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    943                     struct iio_channel *chn = dev->channels[i];
    1: ret = <optimized out>
    (gdb) n
    944                     if (chn->index >= 0 && iio_channel_is_enabled(chn)) {
    1: ret = <optimized out>
    (gdb) n
    945                             ret = channel_write_state(chn, true);
    1: ret = <optimized out>
    (gdb) n
    946                             if (ret < 0)
    1: ret = 0
    (gdb) n
    951             pdata->cyclic = cyclic;
    1: ret = <optimized out>
    (gdb) n
    954             pdata->samples_count = samples_count;
    1: ret = <optimized out>
    (gdb) n
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) s
    enable_high_speed (dev=0x4c3560) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) s
    820             if (pdata->cyclic) {
    1: ret = <optimized out>
    (gdb) s
    824                     nb_blocks = pdata->max_nb_blocks;
    1: ret = <optimized out>
    (gdb) s
    828             pdata->blocks = calloc(nb_blocks, sizeof(*pdata->blocks));
    1: ret = <optimized out>
    (gdb) n
    829             if (!pdata->blocks)
    1: ret = <optimized out>
    (gdb) s
    832             pdata->addrs = calloc(nb_blocks, sizeof(*pdata->addrs));
    1: ret = <optimized out>
    (gdb) n
    833             if (!pdata->addrs) {
    1: ret = <optimized out>
    (gdb) n
    839             req.id = 0;
    1: ret = <optimized out>
    (gdb) n
    841             req.size = pdata->samples_count *
    1: ret = <optimized out>
    (gdb) n
    845             ret = ioctl_nointr(fd, BLOCK_ALLOC_IOCTL, &req);
    1: ret = <optimized out>
    (gdb) s
    ioctl_nointr (fd=fd@entry=5, request=3222301088, data=data@entry=0x7effec2c) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:124
    124                     ret = ioctl(fd, request, data);
    (gdb) s
    ioctl () at ../sysdeps/unix/syscall-template.S:78
    78      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
    (gdb) n
    79              ret
    (gdb) n
    __syscall_error () at ../sysdeps/unix/sysv/linux/arm/sysdep.S:30
    30              rsb r0, r0, $0
    (gdb) n
    40              mov     r1, r0
    (gdb) n
    41              GET_TLS (r2)
    (gdb) n
    42              ldr     r2, 1f
    (gdb) n
    44      2:      add     r2, r2, pc
    (gdb) n
    45              ldr     r2, [r2]
    (gdb) n
    49              str     r1, [r0, r2]
    (gdb) n
    50              mvn     r0, #0
    (gdb) n
    51              DO_RET(lr)
    (gdb) n
    enable_high_speed (dev=0x4c3560) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:846
    846             if (ret < 0) {
    1: ret = <optimized out>
    (gdb) n
    local_open (dev=0x4c3560, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    956             ret = enable_high_speed(dev);
    1: ret = <optimized out>
    (gdb) n
    957             if (ret < 0 && ret != -ENOSYS)
    1: ret = -22
    (gdb) n
    988             close(pdata->fd);
    1: ret = -22
    (gdb) n
    989             pdata->fd = -1;
    1: ret = -22
    (gdb) 

    Can you advise how I can check if something is missing or misconfigured on the kernel side?

Children
  • Can you check what in enable_high_speed( ) returns the -22 error code?

    -Paul

  • I just found this, while checking BLOCK_ALLOC_IOCTL:

    https://github.com/analogdevicesinc/libiio/issues/165#issue-314566841 Could this be the same issue?

    ---8<----8<----

    ret = ioctl_nointr(fd, BLOCK_ALLOC_IOCTL, &req); is the call, details below

    840             req.type = 0;
    841             req.size = pdata->samples_count *
    842                     iio_device_get_sample_size_mask(dev, dev->mask, dev->words);
    843             req.count = nb_blocks;
    844
    845             ret = ioctl_nointr(fd, BLOCK_ALLOC_IOCTL, &req); // int ioctl_nointr(int fd, unsigned long request, void *data) { do { ret = ioctl(fd, request, data); } while (ret == -1 && errno == EINTR); return ret; }
    846             if (ret < 0) {
    847                     ret = -errno;
    848                     goto err_freemem;
    849             }
    
    line 845 is the call.
    req = {type = 0, size = 82944, count = 4, id = 0}
    BLOCK_ALLOC_IOCTL = 0xc01069a0, 3222301088
    
    backtrace:
    #0  ioctl_nointr (fd=fd@entry=5, request=BLOCK_ALLOC_IOCTL, data=data@entry=0x7effec6c) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:124
    #1  0x76e599e0 in enable_high_speed (dev=0x4c3508) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:845
    #2  local_open (dev=0x4c3508, samples_count=3456, cyclic=<optimized out>) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/local.c:956
    #3  0x76e57c20 in iio_device_create_buffer (dev=dev@entry=0x4c3508, samples_count=samples_count@entry=3456, cyclic=cyclic@entry=false) at /usr/src/debug/libiio/0.14+gitAUTOINC+fa82974d8b-r0/git/buffer.c:73
    #4  0x004336da in IioDriver::populateDevList (this=this@entry=0x4c3400) at /usr/src/debug/stupid/0.2-r0/stupid-0.2/src/driver/iiodriver.cpp:161     <==== iio_buffer* iiobuf = iio_device_create_buffer(dev, totalBufLen, 0); // FAILS: -EINVALID
    

  • Hi,

    You are using a version of Libiio built on February 2018... 4 years ago.

    Before trying anything else, please update to the latest release (which is v0.23), or to the master branch from git.

    Cheers,

    -Paul

  • Hi Paul,

    I've updated. I was hesitant to update the lib as this is the one provided in the LTS build system for the board.

    Now updated to 0.23 from your github. Similar issue exists.

    ioctl_nointr (fd=7, request=27041, data=0x0) at /usr/src/debug/libiio/0.23+gitAUTOINC+92d6a35f3d-r0/git/local.c:114

    called from

    enable_high_speed (dev=0x4c3578) at /usr/src/debug/libiio/0.23+gitAUTOINC+92d6a35f3d-r0/git/local.c:955
    955             ret = enable_high_speed(dev);

  • Hi,

    What exactly happens now?

    The ioctl_nointr() call you pasted is the one in local.c:820 where it calls BLOCK_FREE_IOCTL (you can tell as it's the only one that passes data=NULL), and if it fails, -ENOSYS is returned, never -EINVAL. Then libiio will revert to using the slower read/write based API so it should always work independently on the value returned by this ioctl.

    Or does it actually succeed, and later the BLOCK_ALLOC_IOCTL returns -EINVAL?

    Note that these ioctls are only available if you are running ADI's kernel. If you are not, then they should return -ENOSYS already. I don't really understand where exactly this -22 error comes from, but knowing exactly what kernel you are running would help.

    -Paul

  • Hi Paul,

    I checked again today. Lesson learned - errno is set in during that IOCTL call but the overall call to iio_device_create_buffer is successful. The test in the following line was incorrect in that it tested the errno expecting 0, for success.

    iio_buffer* iiobuf = iio_device_create_buffer(dev, totalBufLen, 0); // FAILS: -EINVALID if(errno || (iiobuf == NULL)) { LOG_ERROR(std::string("Got buffer error: ") + std::strerror(errno) + "(" + std::to_string(errno) + ")"); }

    having changed that to

    if(!iiobuf && errno)... the call is found to be successful.

    Notes for the next guy:

    1. Make sure that the library is as up to date as possible

    2. Make sure that the device tree entry is complete

    3. Make sure that you have triggers for your devices, or use one from triggers - standalone (under Kernel Config -> Device Drivers -> Industrial I/O Support)

    4. Check that the timers are running under /sys/bus/iio/devices/triggerX

    5. Test for the *pointer* first, then the errno if pointer is NULL. Be aware that errno is not an indication of success.