summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/b200
diff options
context:
space:
mode:
authorMichael West <michael.west@ettus.com>2013-11-20 11:57:38 -0800
committerMichael West <michael.west@ettus.com>2013-11-20 11:57:38 -0800
commit1fe3db82d6d292a186fe26e728dfdf68db4db056 (patch)
tree55e4aecf11f2387cde6486dbb671aaa6bdebe470 /host/lib/usrp/b200
parenta0bae5347bd542b6f84601f8f0c8c70137ea44d1 (diff)
parent58f4af976d64765c2402e1ce00ee78f4aae51881 (diff)
downloaduhd-1fe3db82d6d292a186fe26e728dfdf68db4db056.tar.gz
uhd-1fe3db82d6d292a186fe26e728dfdf68db4db056.tar.bz2
uhd-1fe3db82d6d292a186fe26e728dfdf68db4db056.zip
Merged in branch master
Diffstat (limited to 'host/lib/usrp/b200')
-rw-r--r--host/lib/usrp/b200/b200_iface.cpp42
-rw-r--r--host/lib/usrp/b200/b200_iface.hpp16
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp21
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp8
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp32
5 files changed, 89 insertions, 30 deletions
diff --git a/host/lib/usrp/b200/b200_iface.cpp b/host/lib/usrp/b200/b200_iface.cpp
index 457b380b6..e0809998e 100644
--- a/host/lib/usrp/b200/b200_iface.cpp
+++ b/host/lib/usrp/b200/b200_iface.cpp
@@ -69,6 +69,11 @@ const static boost::uint8_t FX3_STATE_RUNNING = 0x04;
const static boost::uint8_t FX3_STATE_UNCONFIGURED = 0x05;
const static boost::uint8_t FX3_STATE_ERROR = 0x06;
+const static int VREQ_MAX_SIZE_USB2 = 64;
+const static int VREQ_MAX_SIZE_USB3 = 512;
+const static int VREQ_DEFAULT_SIZE = VREQ_MAX_SIZE_USB2;
+const static int VREQ_MAX_SIZE = VREQ_MAX_SIZE_USB3;
+
typedef boost::uint32_t hash_type;
@@ -243,10 +248,12 @@ public:
size_t num_bytes
){
byte_vector_t recv_bytes(num_bytes);
- fx3_control_read(B200_VREQ_EEPROM_READ,
+ int bytes_read = fx3_control_read(B200_VREQ_EEPROM_READ,
0, offset | (boost::uint16_t(addr) << 8),
(unsigned char*) &recv_bytes[0],
num_bytes);
+ if (bytes_read != num_bytes)
+ throw uhd::io_error("Failed to read data from EEPROM.");
return recv_bytes;
}
@@ -492,10 +499,24 @@ public:
hash_type hash = generate_hash(filename);
hash_type loaded_hash; usrp_get_fpga_hash(loaded_hash);
if (hash == loaded_hash) return 0;
-
- unsigned char out_buff[64];
- memset(out_buff, 0x00, sizeof(out_buff));
- fx3_control_write(B200_VREQ_FPGA_CONFIG, 0, 0, out_buff, 1, 1000);
+
+ // Establish default largest possible control request transfer size based on operating USB speed
+ int transfer_size = VREQ_DEFAULT_SIZE;
+ int current_usb_speed = get_usb_speed();
+ if (current_usb_speed == 3)
+ transfer_size = VREQ_MAX_SIZE_USB3;
+ else if (current_usb_speed != 2)
+ throw uhd::io_error("load_fpga: get_usb_speed returned invalid USB speed (not 2 or 3).");
+
+ UHD_ASSERT_THROW(transfer_size <= VREQ_MAX_SIZE);
+
+ unsigned char out_buff[VREQ_MAX_SIZE];
+
+ // Request loopback read, which will indicate the firmware's current control request buffer size
+ int nread = fx3_control_read(B200_VREQ_LOOP, 0, 0, out_buff, sizeof(out_buff), 1000);
+ if (nread <= 0)
+ throw uhd::io_error("load_fpga: unable to complete firmware loopback request.");
+ transfer_size = std::min(transfer_size, nread); // Select the smaller value
size_t file_size = 0;
{
@@ -510,6 +531,9 @@ public:
throw uhd::io_error("load_fpga: cannot open FPGA input file.");
}
+ memset(out_buff, 0x00, sizeof(out_buff));
+ fx3_control_write(B200_VREQ_FPGA_CONFIG, 0, 0, out_buff, 1, 1000);
+
wait_count = 0;
do {
fx3_state = get_fx3_status();
@@ -543,14 +567,18 @@ public:
size_t bytes_sent = 0;
while(!file.eof()) {
- file.read((char *) out_buff, sizeof(out_buff));
+ file.read((char *) out_buff, transfer_size);
const std::streamsize n = file.gcount();
if(n == 0) continue;
boost::uint16_t transfer_count = boost::uint16_t(n);
/* Send the data to the device. */
- fx3_control_write(B200_VREQ_FPGA_DATA, 0, 0, out_buff, transfer_count, 5000);
+ int nwritten = fx3_control_write(B200_VREQ_FPGA_DATA, 0, 0, out_buff, transfer_count, 5000);
+ if (nwritten <= 0)
+ throw uhd::io_error("load_fpga: cannot write bitstream to FX3.");
+ else if (nwritten != transfer_count)
+ throw uhd::io_error("load_fpga: short write while transferring bitstream to FX3.");
if (load_img_msg)
{
diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp
index 1247d1f86..5b6eeede4 100644
--- a/host/lib/usrp/b200/b200_iface.hpp
+++ b/host/lib/usrp/b200/b200_iface.hpp
@@ -25,7 +25,17 @@
#include <boost/utility.hpp>
#include "ad9361_ctrl.hpp"
-class b200_iface: boost::noncopyable, public virtual uhd::i2c_iface,
+const static boost::uint16_t B200_VENDOR_ID = 0x2500;
+const static boost::uint16_t B200_PRODUCT_ID = 0x0020;
+const static boost::uint16_t FX3_VID = 0x04b4;
+const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;
+const static boost::uint16_t FX3_REENUM_PID = 0x00f0;
+
+static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex";
+static const std::string B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin";
+static const std::string B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin";
+
+class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface,
public ad9361_ctrl_iface_type {
public:
typedef boost::shared_ptr<b200_iface> sptr;
@@ -64,6 +74,10 @@ public:
//! send SPI through the FX3
virtual void transact_spi( unsigned char *tx_data, size_t num_tx_bits, \
unsigned char *rx_data, size_t num_rx_bits) = 0;
+
+ virtual void write_eeprom(boost::uint16_t addr, boost::uint16_t offset, const uhd::byte_vector_t &bytes) = 0;
+
+ virtual uhd::byte_vector_t read_eeprom(boost::uint16_t addr, boost::uint16_t offset, size_t num_bytes) = 0;
};
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 0da388b93..132b1198d 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -37,10 +37,6 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::transport;
-const boost::uint16_t B200_VENDOR_ID = 0x2500;
-const boost::uint16_t B200_PRODUCT_ID = 0x0020;
-const boost::uint16_t INIT_PRODUCT_ID = 0x00f0;
-
static const boost::posix_time::milliseconds REENUMERATION_TIMEOUT_MS(3000);
//! mapping of frontend to radio perif index
@@ -99,7 +95,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)
catch(const uhd::exception &){continue;} //ignore claimed
//check if fw was already loaded
- if (handle->get_manufacturer() != "Ettus Research LLC")
+ if (!(handle->firmware_loaded()))
{
b200_iface::make(control)->load_firmware(b200_fw_image);
}
@@ -160,8 +156,15 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
const fs_path mb_path = "/mboards/0";
//try to match the given device address with something on the USB bus
+ uint16_t vid = B200_VENDOR_ID;
+ uint16_t pid = B200_PRODUCT_ID;
+ if (device_addr.has_key("vid"))
+ sscanf(device_addr.get("vid").c_str(), "%x", &vid);
+ if (device_addr.has_key("pid"))
+ sscanf(device_addr.get("pid").c_str(), "%x", &pid);
+
std::vector<usb_device_handle::sptr> device_list =
- usb_device_handle::get_device_list(B200_VENDOR_ID, B200_PRODUCT_ID);
+ usb_device_handle::get_device_list(vid, pid);
//locate the matching handle in the device list
usb_device_handle::sptr handle;
@@ -252,7 +255,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
////////////////////////////////////////////////////////////////////
_async_task_data.reset(new AsyncTaskData());
_async_task_data->async_md.reset(new async_md_type(1000/*messages deep*/));
- _async_task = uhd::task::make(boost::bind(&b200_impl::handle_async_task, this, _ctrl_transport, _async_task_data));
+ _async_task = uhd::msg_task::make(boost::bind(&b200_impl::handle_async_task, this, _ctrl_transport, _async_task_data));
////////////////////////////////////////////////////////////////////
// Local control endpoint
@@ -474,7 +477,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
b200_impl::~b200_impl(void)
{
- UHD_SAFE_CALL
+ UHD_SAFE_CALL
(
_async_task.reset();
)
@@ -612,7 +615,7 @@ void b200_impl::setup_radio(const size_t dspno)
/***********************************************************************
* loopback tests
**********************************************************************/
-
+
void b200_impl::register_loopback_self_test(wb_iface::sptr iface)
{
bool test_fail = false;
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index eced4a539..362c45347 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -44,10 +44,6 @@
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/weak_ptr.hpp>
#include "recv_packet_demuxer_3000.hpp"
-
-static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex";
-static const std::string B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin";
-static const std::string B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin";
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x03;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00;
static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x02;
@@ -120,7 +116,7 @@ struct b200_impl : public uhd::device
boost::weak_ptr<uhd::tx_streamer> _tx_streamer;
//async ctrl + msgs
- uhd::task::sptr _async_task;
+ uhd::msg_task::sptr _async_task;
typedef uhd::transport::bounded_buffer<uhd::async_metadata_t> async_md_type;
struct AsyncTaskData
{
@@ -130,7 +126,7 @@ struct b200_impl : public uhd::device
b200_uart::sptr gpsdo_uart;
};
boost::shared_ptr<AsyncTaskData> _async_task_data;
- void handle_async_task(uhd::transport::zero_copy_if::sptr, boost::shared_ptr<AsyncTaskData>);
+ boost::optional<uhd::msg_task::msg_type_t> handle_async_task(uhd::transport::zero_copy_if::sptr, boost::shared_ptr<AsyncTaskData>);
void register_loopback_self_test(uhd::wb_iface::sptr iface);
void codec_loopback_self_test(uhd::wb_iface::sptr iface);
diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp
index d643ef855..4fe90bd4a 100644
--- a/host/lib/usrp/b200/b200_io_impl.cpp
+++ b/host/lib/usrp/b200/b200_io_impl.cpp
@@ -139,27 +139,44 @@ bool b200_impl::recv_async_msg(
return _async_task_data->async_md->pop_with_timed_wait(async_metadata, timeout);
}
-void b200_impl::handle_async_task(
+/*
+ * This method is constantly called in a msg_task loop.
+ * Incoming messages are dispatched in to the hosts radio_ctrl_cores.
+ * The radio_ctrl_core queues are accessed via a weak_ptr to them, stored in AsyncTaskData.
+ * During shutdown the radio_ctrl_core dtor's are called.
+ * An empty peek32(0) is sent out to flush pending async messages.
+ * The response to those messages can't be delivered to the ctrl_core queues anymore
+ * because the shared pointer corresponding to the weak_ptrs is no longer valid.
+ * Those stranded messages are put into a dump_queue implemented in msg_task.
+ * A radio_ctrl_core can search for missing messages there.
+ */
+boost::optional<uhd::msg_task::msg_type_t> b200_impl::handle_async_task(
uhd::transport::zero_copy_if::sptr xport,
boost::shared_ptr<AsyncTaskData> data
)
{
managed_recv_buffer::sptr buff = xport->get_recv_buff();
- if (not buff or buff->size() < 8) return;
+ if (not buff or buff->size() < 8)
+ return NULL;
+
const boost::uint32_t sid = uhd::wtohx(buff->cast<const boost::uint32_t *>()[1]);
- switch (sid)
- {
+ switch (sid) {
//if the packet is a control response
case B200_RESP0_MSG_SID:
case B200_RESP1_MSG_SID:
case B200_LOCAL_RESP_SID:
{
- radio_ctrl_core_3000::sptr ctrl;
+ radio_ctrl_core_3000::sptr ctrl;
if (sid == B200_RESP0_MSG_SID) ctrl = data->radio_ctrl[0].lock();
if (sid == B200_RESP1_MSG_SID) ctrl = data->radio_ctrl[1].lock();
if (sid == B200_LOCAL_RESP_SID) ctrl = data->local_ctrl.lock();
- if (ctrl) ctrl->push_response(buff->cast<const boost::uint32_t *>());
+ if (ctrl){
+ ctrl->push_response(buff->cast<const boost::uint32_t *>());
+ }
+ else{
+ return std::make_pair(sid, uhd::msg_task::buff_to_vector(buff->cast<boost::uint8_t *>(), buff->size() ) );
+ }
break;
}
@@ -204,6 +221,7 @@ void b200_impl::handle_async_task(
default:
UHD_MSG(error) << "Got a ctrl packet with unknown SID " << sid << std::endl;
}
+ return NULL;
}
/***********************************************************************
@@ -231,7 +249,7 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
+ //+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
- sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;