diff options
| -rw-r--r-- | host/LICENSE | 4 | ||||
| -rw-r--r-- | host/include/uhd/transport/nirio/nirio_fifo.h | 6 | ||||
| -rw-r--r-- | host/include/uhd/transport/nirio/nirio_fifo.ipp | 234 | ||||
| -rw-r--r-- | host/include/uhd/transport/nirio/nirio_quirks.h | 4 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_io_impl.cpp | 35 | 
5 files changed, 173 insertions, 110 deletions
| diff --git a/host/LICENSE b/host/LICENSE index 9aa03b39b..b91233b22 100644 --- a/host/LICENSE +++ b/host/LICENSE @@ -1,3 +1,7 @@ +This LICENSE file applies only to this directory and all subdirectories. Other +top-level directories in the UHD(tm) Software distribution are not necessarily +covered by this license. +  This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation, either version 3 of the License, or diff --git a/host/include/uhd/transport/nirio/nirio_fifo.h b/host/include/uhd/transport/nirio/nirio_fifo.h index f7abb396f..fc1de245d 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.h +++ b/host/include/uhd/transport/nirio/nirio_fifo.h @@ -104,16 +104,20 @@ public:          uint32_t& num_remaining);  private:    //Methods -    bool _is_initialized();      datatype_info_t _get_datatype_info();      nirio_status _get_transfer_count(uint64_t& transfer_count);      nirio_status _ensure_transfer_completed(uint32_t timeout_ms);  private:    //Members +    enum fifo_state_t { +        UNMAPPED, MAPPED, STARTED +    }; +      std::string                    _name;      fifo_direction_t               _fifo_direction;      uint32_t                       _fifo_channel;      datatype_info_t                _datatype_info; +    fifo_state_t                   _state;      size_t                         _acquired_pending;      nirio_driver_iface::rio_mmap_t _mem_map;      boost::recursive_mutex         _mutex; diff --git a/host/include/uhd/transport/nirio/nirio_fifo.ipp b/host/include/uhd/transport/nirio/nirio_fifo.ipp index 80a0c2a89..437e3a1fc 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.ipp +++ b/host/include/uhd/transport/nirio/nirio_fifo.ipp @@ -31,6 +31,7 @@ nirio_fifo<data_t>::nirio_fifo(      _fifo_direction(direction),      _fifo_channel(fifo_instance),      _datatype_info(_get_datatype_info()), +    _state(UNMAPPED),      _acquired_pending(0),      _mem_map(),      _riok_proxy_ptr(&riok_proxy), @@ -61,28 +62,37 @@ nirio_status nirio_fifo<data_t>::initialize(      if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized;      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; +    if (_state == UNMAPPED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    //Forcefully stop the fifo if it is running -    in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        //Forcefully stop the fifo if it is running +        in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; +        in.params.fifo.channel = _fifo_channel; +        _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out));    //Cleanup operation. Ignore status. -    in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::CONFIGURE; +        //Configure the FIFO now that we know it is stopped +        in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::CONFIGURE; +        in.params.fifo.channel = _fifo_channel; +        in.params.fifo.op.config.requestedDepth = static_cast<uint32_t>(requested_depth); +        in.params.fifo.op.config.requiresActuals = 1; +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    in.params.fifo.channel = _fifo_channel; -    in.params.fifo.op.config.requestedDepth = static_cast<uint32_t>(requested_depth); -    in.params.fifo.op.config.requiresActuals = 1; +        if (nirio_status_fatal(status)) return status; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    if (nirio_status_fatal(status)) return status; +        actual_depth = out.params.fifo.op.config.actualDepth; +        actual_size = out.params.fifo.op.config.actualSize; -    actual_depth = out.params.fifo.op.config.actualDepth; -    actual_size = out.params.fifo.op.config.actualSize; +        status = _riok_proxy_ptr->map_fifo_memory(_fifo_channel, actual_size, _mem_map); -    status = _riok_proxy_ptr->map_fifo_memory(_fifo_channel, actual_size, _mem_map); +        if (nirio_status_not_fatal(status)) { +            _state = MAPPED; +        } +    } else { +        status = NiRio_Status_SoftwareFault; +    }      return status;  } @@ -90,9 +100,13 @@ template <typename data_t>  void nirio_fifo<data_t>::finalize()  {      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    if (!_mem_map.is_null()) { -        stop(); + +    //If the FIFO is started, the stop will change the state to MAPPED. +    stop(); + +    if (_state == MAPPED) {          _riok_proxy_ptr->unmap_fifo_memory(_mem_map); +        _state = UNMAPPED;    //Assume teardown succeeded      }  } @@ -104,16 +118,25 @@ nirio_status nirio_fifo<data_t>::start()      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; +    if (_state == STARTED) { +        //Do nothing. Already started. +    } else if (_state == MAPPED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::START; +        in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::START; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    if (nirio_status_not_fatal(status)) { -        _acquired_pending = 0; -        _expected_xfer_count = 0; +        in.params.fifo.channel = _fifo_channel; + +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        if (nirio_status_not_fatal(status)) { +            _state = STARTED; +            _acquired_pending = 0; +            _expected_xfer_count = 0; +        } +    } else { +        status = NiRio_Status_ResourceNotInitialized;      }      return status;  } @@ -125,15 +148,22 @@ nirio_status nirio_fifo<data_t>::stop()      if (!_riok_proxy_ptr) return NiRio_Status_ResourceNotInitialized;      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    if (_acquired_pending > 0) release(_acquired_pending); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; +    if (_state == STARTED) { +        if (_acquired_pending > 0) release(_acquired_pending); + +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; +        in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::STOP; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        in.params.fifo.channel = _fifo_channel; + +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + +        _state = MAPPED;    //Assume teardown succeeded +    }      return status;  } @@ -151,36 +181,40 @@ nirio_status nirio_fifo<data_t>::acquire(      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    uint32_t stuffed[2]; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    init_syncop_out_params(out, stuffed, sizeof(stuffed)); - -    in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::WAIT; - -    in.params.fifo.channel                   = _fifo_channel; -    in.params.fifo.op.wait.elementsRequested = static_cast<uint32_t>(elements_requested); -    in.params.fifo.op.wait.scalarType        = static_cast<uint32_t>(_datatype_info.scalar_type); -    in.params.fifo.op.wait.bitWidth          = _datatype_info.width * 8; -    in.params.fifo.op.wait.output            = _fifo_direction == OUTPUT_FIFO; -    in.params.fifo.op.wait.timeout           = timeout; - -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); - -    if (nirio_status_not_fatal(status)) { -        elements = static_cast<data_t*>(out.params.fifo.op.wait.elements.pointer); -        elements_acquired = stuffed[0]; -        elements_remaining = stuffed[1]; -        _acquired_pending = elements_acquired; - -        if (UHD_NIRIO_RX_FIFO_XFER_CHECK_EN && -            _riok_proxy_ptr->get_rio_quirks().rx_fifo_xfer_check_en() && -            get_direction() == INPUT_FIFO -        ) { -            _expected_xfer_count += static_cast<uint64_t>(elements_requested * sizeof(data_t)); -            status = _ensure_transfer_completed(timeout); +    if (_state == STARTED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        uint32_t stuffed[2]; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; +        init_syncop_out_params(out, stuffed, sizeof(stuffed)); + +        in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::WAIT; + +        in.params.fifo.channel                   = _fifo_channel; +        in.params.fifo.op.wait.elementsRequested = static_cast<uint32_t>(elements_requested); +        in.params.fifo.op.wait.scalarType        = static_cast<uint32_t>(_datatype_info.scalar_type); +        in.params.fifo.op.wait.bitWidth          = _datatype_info.width * 8; +        in.params.fifo.op.wait.output            = _fifo_direction == OUTPUT_FIFO; +        in.params.fifo.op.wait.timeout           = timeout; + +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); + +        if (nirio_status_not_fatal(status)) { +            elements = static_cast<data_t*>(out.params.fifo.op.wait.elements.pointer); +            elements_acquired = stuffed[0]; +            elements_remaining = stuffed[1]; +            _acquired_pending = elements_acquired; + +            if (UHD_NIRIO_RX_FIFO_XFER_CHECK_EN && +                _riok_proxy_ptr->get_rio_quirks().rx_fifo_xfer_check_en() && +                get_direction() == INPUT_FIFO +            ) { +                _expected_xfer_count += static_cast<uint64_t>(elements_requested * sizeof(data_t)); +                status = _ensure_transfer_completed(timeout); +            }          } +    } else { +        status = NiRio_Status_ResourceNotInitialized;      }      return status; @@ -194,17 +228,21 @@ nirio_status nirio_fifo<data_t>::release(const size_t elements)      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; +    if (_state == STARTED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::GRANT; +        in.function    = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::GRANT; -    in.params.fifo.channel           = _fifo_channel; -    in.params.fifo.op.grant.elements = static_cast<uint32_t>(elements); +        in.params.fifo.channel           = _fifo_channel; +        in.params.fifo.op.grant.elements = static_cast<uint32_t>(elements); -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    _acquired_pending = 0; +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        _acquired_pending = 0; +    } else { +        status = NiRio_Status_ResourceNotInitialized; +    }      return status;  } @@ -222,23 +260,27 @@ nirio_status nirio_fifo<data_t>::read(      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    init_syncop_out_params(out, buf, num_elements * _datatype_info.width); +    if (_state == STARTED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; +        init_syncop_out_params(out, buf, num_elements * _datatype_info.width); -    in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::READ; +        in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::READ; -    in.params.fifo.channel = _fifo_channel; -    in.params.fifo.op.readWithDataType.timeout = timeout; -    in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); -    in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; +        in.params.fifo.channel = _fifo_channel; +        in.params.fifo.op.readWithDataType.timeout = timeout; +        in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); +        in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { -        num_read = out.params.fifo.op.read.numberRead; -        num_remaining = out.params.fifo.op.read.numberRemaining; +        if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { +            num_read = out.params.fifo.op.read.numberRead; +            num_remaining = out.params.fifo.op.read.numberRemaining; +        } +    } else { +        status = NiRio_Status_ResourceNotInitialized;      }      return status; @@ -256,22 +298,26 @@ nirio_status nirio_fifo<data_t>::write(      boost::unique_lock<boost::recursive_mutex> lock(_mutex); -    nirio_driver_iface::nirio_syncop_in_params_t in = {}; -    init_syncop_in_params(in, buf, num_elements * _datatype_info.width); -    nirio_driver_iface::nirio_syncop_out_params_t out = {}; +    if (_state == STARTED) { +        nirio_driver_iface::nirio_syncop_in_params_t in = {}; +        init_syncop_in_params(in, buf, num_elements * _datatype_info.width); +        nirio_driver_iface::nirio_syncop_out_params_t out = {}; -    in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; -    in.subfunction = nirio_driver_iface::NIRIO_FIFO::WRITE; +        in.function = nirio_driver_iface::NIRIO_FUNC::FIFO; +        in.subfunction = nirio_driver_iface::NIRIO_FIFO::WRITE; -    in.params.fifo.channel = _fifo_channel; -    in.params.fifo.op.writeWithDataType.timeout = timeout; -    in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); -    in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; +        in.params.fifo.channel = _fifo_channel; +        in.params.fifo.op.writeWithDataType.timeout = timeout; +        in.params.fifo.op.readWithDataType.scalarType = static_cast<uint32_t>(_datatype_info.scalar_type); +        in.params.fifo.op.readWithDataType.bitWidth = _datatype_info.width * 8; -    status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); +        status = _riok_proxy_ptr->sync_operation(&in, sizeof(in), &out, sizeof(out)); -    if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { -        num_remaining = out.params.fifo.op.write.numberRemaining; +        if (nirio_status_not_fatal(status) || status == NiRio_Status_FifoTimeout) { +            num_remaining = out.params.fifo.op.write.numberRemaining; +        } +    } else { +        status = NiRio_Status_ResourceNotInitialized;      }      return status; diff --git a/host/include/uhd/transport/nirio/nirio_quirks.h b/host/include/uhd/transport/nirio/nirio_quirks.h index 326eeeb8c..ed4f72e7f 100644 --- a/host/include/uhd/transport/nirio/nirio_quirks.h +++ b/host/include/uhd/transport/nirio/nirio_quirks.h @@ -24,8 +24,8 @@  //Quirk#1: We need to verify RX zero-copy data transfers from the RIO  //         driver if we are in full duplex mode. -//         This option allows disabling this quirk by compiling it out. -#define UHD_NIRIO_RX_FIFO_XFER_CHECK_EN 1 +//         This option allows enabling this quirk. +#define UHD_NIRIO_RX_FIFO_XFER_CHECK_EN 0  namespace uhd { namespace niusrprio { diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index 09ed1d705..9263c9b44 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -242,6 +242,8 @@ struct x300_tx_fc_guts_t      boost::shared_ptr<x300_impl::async_md_type> old_async_queue;  }; +#define X300_ASYNC_EVENT_CODE_FLOW_CTRL 0 +  static size_t get_tx_flow_control_window(size_t frame_size, const device_addr_t& tx_args)  {      double hw_buff_size = tx_args.cast<double>("send_buff_size", X300_TX_HW_BUFF_SIZE); @@ -283,23 +285,28 @@ static void handle_tx_async_msgs(boost::shared_ptr<x300_tx_fc_guts_t> guts, zero          return;      } -    //catch the flow control packets and react -    if (endian_conv(packet_buff[if_packet_info.num_header_words32+0]) == 0) -    { -        const size_t seq = endian_conv(packet_buff[if_packet_info.num_header_words32+1]); -        guts->seq_queue.push_with_haste(seq); -        return; -    } -      //fill in the async metadata      async_metadata_t metadata;      load_metadata_from_buff(          endian_conv, metadata, if_packet_info, packet_buff,          clock->get_master_clock_rate(), guts->stream_channel); -    guts->async_queue->push_with_pop_on_full(metadata); -    metadata.channel = guts->device_channel; -    guts->old_async_queue->push_with_pop_on_full(metadata); -    standard_async_msg_prints(metadata); + +    //The FC response and the burst ack are two indicators that the radio +    //consumed packets. Use them to update the FC metadata +    if (metadata.event_code == X300_ASYNC_EVENT_CODE_FLOW_CTRL or +        metadata.event_code == async_metadata_t::EVENT_CODE_BURST_ACK +    ) { +        const size_t seq = metadata.user_payload[0]; +        guts->seq_queue.push_with_pop_on_full(seq); +    } + +    //FC responses don't propagate up to the user so filter them here +    if (metadata.event_code != X300_ASYNC_EVENT_CODE_FLOW_CTRL) { +        guts->async_queue->push_with_pop_on_full(metadata); +        metadata.channel = guts->device_channel; +        guts->old_async_queue->push_with_pop_on_full(metadata); +        standard_async_msg_prints(metadata); +    }  }  static managed_send_buffer::sptr get_tx_buff_with_flowctrl( @@ -319,7 +326,9 @@ static managed_send_buffer::sptr get_tx_buff_with_flowctrl(      }      managed_send_buffer::sptr buff = xport->get_send_buff(timeout); -    if (buff) guts->last_seq_out++; //update seq, this will actually be a send +    if (buff) { +        guts->last_seq_out++; //update seq, this will actually be a send +    }      return buff;  } | 
