AnsweredAssumed Answered

Unable to create iio_buffer

Question asked by daxez12 on Dec 1, 2017
Latest reply on Dec 5, 2017 by daxez12

Hi, I'm doing a modified version of device_sink block from gr-iio in GNU Radio. I'm working with the ad-fmcomms1-ebz and get this error while trying to connect remotely to the board:

Traceback (most recent call last):
  File "/home/daniel/Documentos/top_block.py", line 116, in <module>
    main()
  File "/home/daniel/Documentos/top_block.py", line 104, in main
    tb = top_block_cls()
  File "/home/daniel/Documentos/top_block.py", line 67, in __init__
    self.fmcomms1_fmcomms1_sink_0 = fmcomms1.fmcomms1_sink('192.1.135.87', 2400000000, 2084000, 20000000, ['voltage0','voltage1'], 0x8000, 1 - 1), cyclic
  File "/usr/local/lib/python2.7/dist-packages/fmcomms1/fmcomms1_swig.py", line 554, in make
    return _fmcomms1_swig.fmcomms1_sink_make(*args, **kwargs)
RuntimeError: Unable to create buffer: -22

 

 

 This is the code I'm implementing, it still very unclean but I think it should work:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

 

#include <gnuradio/io_signature.h>
#include "fmcomms1_sink_impl.h"
#include "fmcomms1_source_impl.h"

 

#include <cstdio>

 

namespace gr {
  namespace fmcomms1 {

 

    fmcomms1_sink::sptr
    fmcomms1_sink::make(const std::string &uri, unsigned long frequency,
          unsigned long samplerate, unsigned long bandwidth,
          const std::vector<std::string> &channels,
          unsigned int buffer_size,
          unsigned int interpolation,
          bool cyclic)
    {
      return gnuradio::get_initial_sptr
        (new fmcomms1_sink_impl(fmcomms1_source_impl::get_context(uri), true,
                      frequency, samplerate, bandwidth,
                      channels, buffer_size, interpolation, cyclic));
    }

 

    fmcomms1_sink::sptr
    fmcomms1_sink::make_from(struct iio_context *ctx,
          unsigned long frequency, unsigned long samplerate,
          unsigned long bandwidth,
          const std::vector<std::string> &channels,
          unsigned int buffer_size,
          unsigned int interpolation,
          bool cyclic)
    {
      return gnuradio::get_initial_sptr
        (new fmcomms1_sink_impl(ctx, false, frequency, samplerate,
                      bandwidth, channels, buffer_size, interpolation));
    }

 

    /* Función para establecer los parámetros de los dispositivos de transmisión */
    void
    fmcomms1_sink_impl::set_params(unsigned long frequency,
              unsigned long samplerate, unsigned long bandwidth)
    {
      std::vector<std::string> params_dev, params_phy, params_vga;

 

      // Parámetros del dispositivo de transmisión
      params_dev.push_back("out_altvoltage0_frequency_resolution="+
              boost::to_string(frequency));

 

      // Parámetros del dispositivo DAC
      params_phy.push_back("out_voltage0_calibbias="+
              boost::to_string(bandwidth));
      params_phy.push_back("out_voltage1_calibbias="+
              boost::to_string(bandwidth));

 


      // Parámetros del dispositivo vga
      params_vga.push_back("out_altvoltage0_ZD_OUTPUT_frequency="+
              boost::to_string(frequency));
      params_vga.push_back("out_altvoltage0_ZD_OUTPUT_phase="+
              boost::to_string(bandwidth));

 

      fmcomms1_source_impl::set_parameters(this->vga, params_vga);
      fmcomms1_source_impl::set_parameters(this->phy, params_phy);
      fmcomms1_source_impl::set_parameters(this->dev, params_dev);

 

    }

 

    /*
     * The private constructor
     */
    fmcomms1_sink_impl::fmcomms1_sink_impl(struct iio_context *ctx,
          bool destroy_ctx, unsigned long frequency,
          unsigned long samplerate, unsigned long bandwidth,
          const std::vector<std::string> &channels,
          unsigned int buffer_size,
          unsigned int interpolation, bool cyclic)
      : gr::sync_block("fmcomms1_sink",
              gr::io_signature::make(1, -1, sizeof(short)),
              gr::io_signature::make(0, 0, 0)),
      ctx(ctx),
      interpolation(interpolation),
      buffer_size(buffer_size),
      destroy_ctx(destroy_ctx)
    {
      unsigned int nb_channels, i;

 

      /* Set minimum input size*/
      set_output_multiple(buffer_size /(interpolation + 1));

 

      if (!ctx)
        throw std::runtime_error("Unable to create context");

 

      dev = iio_context_find_device(ctx, "cf-ad9122-core-lpc");
      phy = iio_context_find_device(ctx, "adf4351-tx-lpc");
      vga = iio_context_find_device(ctx, "ad9523-lpc");

 

      if(!dev || !phy || !vga)
      {
        if (destroy_ctx)
          iio_context_destroy(ctx);
        throw std::runtime_error("Device not found");
      }

 


      //** Opcional, puede ir en la interfaz del bloque **//
      
      // Canal del dispositivo phy de la tarjeta-
      struct iio_channel *chn0 = iio_device_find_channel(phy, "altvoltage0", true);

 

      // Canal 0 del vga
      struct iio_channel *chn1 = iio_device_find_channel(vga, "altvoltage0", true);

 

      // Canal 1 del vga
      //struct iio_channel *chn2 = iio_device_find_channel(vga, "voltage1", true);

 

      struct iio_channel *chn3 = iio_device_find_channel(dev, "voltage0", true);
      struct iio_channel *chn4 = iio_device_find_channel(dev, "voltage1", true);

 

      //Activación de los canales
      iio_channel_enable(chn0);
      iio_channel_enable(chn1);
      //iio_channel_enable(chn2);

 

      //** Activación de los canales del dispositivo de recepción **//
      // Primero se desactivan todos, si están activados
      // nb_channels = iio_device_get_channels_count(dev);
      // for (i = 0; i < nb_channels; i++)
      //   iio_channel_disable(iio_device_get_channel(dev, i));

 

      // if (channels.empty())
      // {
      //   for (i = 0; i < nb_channels; i++)
      //   {
      //     struct iio_channel *chn = iio_device_get_channel(dev, i);

 

      //     iio_channel_enable(chn);
      //     channel_list.push_back(chn);
      //   }
      // } else {
      //   for (std::vector<std::string>::const_iterator it =
      //        channels.begin(); it != channels.end(); ++it)
      //   {
      //     struct iio_channel *chn =
      //         iio_device_find_channel(dev, it->c_str(), false);

 

      //     if (!chn)
      //     {
      //       if (destroy_ctx)
      //         iio_context_destroy(ctx);

 

      //       throw std::runtime_error("Channel not found");
      //     }

 

      //     iio_channel_enable(chn);
      //     channel_list.push_back(chn);
      //   }
      // }

 

      //channel_list.push_back(chn);
      set_params(frequency, samplerate, bandwidth);
      
      buf = iio_device_create_buffer(dev, buffer_size, cyclic);

 

      if(!buf)
        throw std::runtime_error("Unable to create buffer: " + boost::to_string(-errno));

 

    }

 

    /*
     * Our virtual destructor.
     */
    fmcomms1_sink_impl::~fmcomms1_sink_impl()
    {
      iio_buffer_destroy(buf);
      if (destroy_ctx)
        iio_context_destroy(ctx);
    }

 

    void
    fmcomms1_sink_impl::channel_write(const struct iio_channel *chn,
        const void *src, size_t len)
    {
      uintptr_t dst_ptr, src_ptr = (uintptr_t) src, end = src_ptr + len;
      unsigned int length = iio_channel_get_data_format(chn)->length / 8;
      uintptr_t buf_end = (uintptr_t) iio_buffer_end(buf);
      ptrdiff_t buf_step = iio_buffer_step(buf) * (interpolation + 1);

 

      for (dst_ptr = (uintptr_t) iio_buffer_first(buf, chn);
            dst_ptr < buf_end && src_ptr + length <= end;
            dst_ptr += buf_step, src_ptr += length)

 

        iio_channel_convert_inverse(chn,
          (void *) dst_ptr, (const void *) src_ptr);

 

    }

 

    int
    fmcomms1_sink_impl::work(int noutput_items,
        gr_vector_const_void_star &input_items,
        gr_vector_void_star &output_items)
    {
      int ret;

 

      if (interpolation >= 1)
      {
        ptrdiff_t len = (intptr_t) iio_buffer_end(buf) -
                          (intptr_t) iio_buffer_start(buf);

 

        memset(iio_buffer_start(buf), 0, len);
      }

 

      for (unsigned int i = 0; i < input_items.size(); i++)
        channel_write(channel_list[i], input_items[i],
                noutput_items * sizeof(short));

 

      ret = iio_buffer_push(buf);

 

      if (ret < 0)
      {
        char buf[256];
        iio_strerror(-ret, buf, sizeof(buf));
        std::string error(buf);

 

        throw std::runtime_error("Unable to push buffer: " + error);
      }

 

      consume_each(buffer_size / (interpolation + 1));
      return 0;
    }

 

    void
    fmcomms1_sink_impl::forecast(int noutput_items,
              gr_vector_int &ninput_items_required)
    {
      for (unsigned int i = 0; i < ninput_items_required.size(); i++)
        ninput_items_required[i] = noutput_items;
    }

 

  } /* namespace fmcomms1 */
} /* namespace gr */

 

The question became when I tried to use th original block from gr-iio and get this warning: thread[thread-per-block[4]: <block device_sink (1)>]: Unable to push buffer: Device or resource busy

 

I don't think it's necessarily related because -22 errno it's about bad arguments, but get me suspicious about the device's disponibility or configuration in the board. I did the update_tools.sh too and get the same result in both tests, so I'm wandering if it could be some problem with my code or it is something with the card. The card is on a Zedboard ZC706.

 

Best regards, Daniel.

Outcomes