aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-08-31 16:44:30 -0700
committerNick Foster <nick@nerdnetworks.org>2010-08-31 16:44:30 -0700
commitb96088b692a5c44974919ee36e253b6ea8c51972 (patch)
tree5200ca3a1b589a83aca06e91c559154ddea82249 /host
parentad55e25aeb273fb7278c6d5175cd0df01fc90924 (diff)
downloaduhd-b96088b692a5c44974919ee36e253b6ea8c51972.tar.gz
uhd-b96088b692a5c44974919ee36e253b6ea8c51972.tar.bz2
uhd-b96088b692a5c44974919ee36e253b6ea8c51972.zip
EEPROM burning in UHD. Changed some USB device handle stuff. Added usrp_init_eeprom.cpp. Hacked up the firmware makefile to behave and to generate .bin EEPROM images instead of IHX.
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/transport/usb_device_handle.hpp4
-rw-r--r--host/lib/transport/libusb1_base.cpp52
-rw-r--r--host/lib/transport/libusb1_base.hpp10
-rw-r--r--host/lib/transport/libusb1_device_handle.cpp18
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp11
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.cpp63
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.hpp31
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.cpp21
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp34
-rw-r--r--host/utils/CMakeLists.txt4
-rw-r--r--host/utils/usrp_init_eeprom.cpp69
11 files changed, 227 insertions, 90 deletions
diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp
index 78c78f6b5..c3eb72b00 100644
--- a/host/include/uhd/transport/usb_device_handle.hpp
+++ b/host/include/uhd/transport/usb_device_handle.hpp
@@ -68,9 +68,9 @@ public:
/*!
* Return a vector of USB devices on this host
- * \return a vector of USB device handles
+ * \return a vector of USB device handles that match vid and pid
*/
- static UHD_API std::vector<usb_device_handle::sptr> get_device_list();
+ static UHD_API std::vector<usb_device_handle::sptr> get_device_list(boost::uint16_t vid, boost::uint16_t pid);
}; //namespace usb
diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp
index 92dcd969f..e21c39aa3 100644
--- a/host/lib/transport/libusb1_base.cpp
+++ b/host/lib/transport/libusb1_base.cpp
@@ -24,22 +24,6 @@ using namespace uhd::transport;
/**********************************************************
* Helper Methods
**********************************************************/
-/*
- * Check for FSF device
- * Compare the device's descriptor Vendor ID
- * \param dev pointer to libusb_device
- * \return true if Vendor ID matches 0xfffe
- */
-bool check_fsf_device(libusb_device *dev)
-{
- libusb_device_descriptor desc;
-
- if (libusb_get_device_descriptor(dev, &desc) < 0) {
- UHD_ASSERT_THROW("USB: failed to get device descriptor");
- }
-
- return desc.idVendor == 0xfffe;
-}
/**********************************************************
* libusb namespace
@@ -52,37 +36,16 @@ void libusb::init(libusb_context **ctx, int debug_level)
libusb_set_debug(*ctx, debug_level);
}
-std::vector<libusb_device *> libusb::get_fsf_device_list(libusb_context *ctx)
-{
- libusb_device **libusb_dev_list;
- std::vector<libusb_device *> fsf_dev_list;
-
- ssize_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list);
-
- //find the FSF devices
- for (ssize_t i = 0; i < dev_cnt; i++) {
- libusb_device *dev = libusb_dev_list[i];
-
- if (check_fsf_device(dev))
- fsf_dev_list.push_back(dev);
- else
- libusb_unref_device(dev);
- }
-
- libusb_free_device_list(libusb_dev_list, 0);
-
- return fsf_dev_list;
-}
-
libusb_device_handle *libusb::open_device(libusb_context *ctx,
usb_device_handle::sptr handle)
{
libusb_device_handle *dev_handle = NULL;
- std::vector<libusb_device *> fsf_dev_list = get_fsf_device_list(ctx);
+ libusb_device **libusb_dev_list;
+ size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list);
//find and open the USB device
- for (size_t i = 0; i < fsf_dev_list.size(); i++) {
- libusb_device *dev = fsf_dev_list[i];
+ for (size_t i = 0; i < dev_cnt; i++) {
+ libusb_device *dev = libusb_dev_list[i];
if (compare_device(dev, handle)) {
libusb_open(dev, &dev_handle);
@@ -96,7 +59,8 @@ libusb_device_handle *libusb::open_device(libusb_context *ctx,
return dev_handle;
}
-
+//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match
+//doing this so it doesn't try to open the device if it's not ours
bool libusb::compare_device(libusb_device *dev,
usb_device_handle::sptr handle)
{
@@ -108,12 +72,12 @@ bool libusb::compare_device(libusb_device *dev,
libusb_device_descriptor libusb_desc;
if (libusb_get_device_descriptor(dev, &libusb_desc) < 0)
return false;
- if (serial != get_serial(dev))
- return false;
if (vendor_id != libusb_desc.idVendor)
return false;
if (product_id != libusb_desc.idProduct)
return false;
+ if (serial != get_serial(dev))
+ return false;
if (device_addr != libusb_get_device_address(dev))
return false;
diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp
index 442f89ded..abe5e22a2 100644
--- a/host/lib/transport/libusb1_base.hpp
+++ b/host/lib/transport/libusb1_base.hpp
@@ -42,16 +42,6 @@ namespace libusb {
void init(libusb_context **ctx, int debug_level);
/*
- * Get a list of Free Software Foundation devices (Vendor ID 0xfffe)
- * As opposed to the public USB device handle interface, which returns
- * generic identifiers, this call returns device pointers speficic
- * to libusb.
- * \param ctx the libusb context used for init
- * \return a vector of libusb devices
- */
- std::vector<libusb_device *> get_fsf_device_list(libusb_context *ctx);
-
- /*
* Open the device specified by a generic handle
* Find the libusb_device cooresponding to the generic handle
* and open it for I/O, which returns a libusb_device_handle
diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp
index 5d9d8faf0..43d0f0e26 100644
--- a/host/lib/transport/libusb1_device_handle.cpp
+++ b/host/lib/transport/libusb1_device_handle.cpp
@@ -17,6 +17,7 @@
#include "libusb1_base.hpp"
#include <uhd/utils/assert.hpp>
+#include <iostream>
using namespace uhd::transport;
@@ -91,19 +92,24 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev)
device_addr));
}
-std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list()
+std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid)
{
libusb_context *ctx = NULL;
- std::vector<libusb_device *> libusb_device_list;
+ libusb_device** libusb_device_list;
std::vector<usb_device_handle::sptr> device_handle_list;
+ libusb_device_descriptor desc;
libusb::init(&ctx, libusb_debug_level);
- libusb_device_list = libusb::get_fsf_device_list(ctx);
-
- for (size_t i = 0; i < libusb_device_list.size(); i++) {
+ size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list);
+ for (size_t i = 0; i < dev_size; i++) {
libusb_device *dev = libusb_device_list[i];
- device_handle_list.push_back(make_usb_device_handle(dev));
+ if(libusb_get_device_descriptor(dev, &desc) < 0) {
+ UHD_ASSERT_THROW("USB: failed to get device descriptor");
+ }
+ if(desc.idVendor == vid && desc.idProduct == pid) {
+ device_handle_list.push_back(make_usb_device_handle(dev));
+ }
}
libusb_exit(ctx);
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
index 75129c32f..1409855cb 100644
--- a/host/lib/usrp/usrp1/mboard_impl.cpp
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -25,6 +25,7 @@
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/utils/warning.hpp>
#include <uhd/utils/assert.hpp>
+#include <uhd/utils/images.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
@@ -318,6 +319,16 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
**********************************************************************/
void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
{
+ if(key.type() == typeid(std::string)) {
+ if(key.as<std::string>() == "load_eeprom") {
+ std::string usrp1_fpga_image = val.as<std::string>();
+ std::cout << "USRP1 EEPROM image: " << usrp1_fpga_image << std::endl;
+ _ctrl_transport->usrp_load_eeprom(val.as<std::string>());
+ }
+
+ return;
+ }
+
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
index 98226b738..451129ef5 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
@@ -25,6 +25,7 @@
#include <sstream>
#include <string>
#include <vector>
+#include <cstring>
using namespace uhd;
@@ -203,7 +204,7 @@ public:
return -1;
}
}
- //type 0x00 is end
+ //type 0x01 is end
else if (type == 0x01) {
usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0,
&reset_n, 1);
@@ -283,6 +284,55 @@ public:
return 0;
}
+ int usrp_load_eeprom(std::string filestring)
+ {
+ const char *filename = filestring.c_str();
+ const uint16_t i2c_addr = 0x50;
+
+ //FIXME: verify types
+ int len;
+ unsigned int addr;
+ unsigned char data[256];
+ unsigned char sendbuf[17];
+
+ int ret;
+ std::ifstream file;
+ file.open(filename, std::ifstream::in);
+
+ if (!file.good()) {
+ std::cerr << "cannot open EEPROM input file" << std::endl;
+ return -1;
+ }
+
+ file.read((char *)data, 256);
+ len = file.gcount();
+
+ if(len == 256) {
+ std::cerr << "error: image size too large" << std::endl;
+ file.close();
+ return -1;
+ }
+
+ const int pagesize = 16;
+ addr = 0;
+ while(len > 0) {
+ sendbuf[0] = addr;
+ memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len);
+ ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1);
+ if (ret < 0) {
+ std::cerr << "error: usrp_i2c_write failed: ";
+ std::cerr << ret << std::endl;
+ file.close();
+ return -1;
+ }
+ addr += pagesize;
+ len -= pagesize;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+ file.close();
+ return 0;
+ }
+
int usrp_set_led(int led_num, bool on)
{
@@ -371,6 +421,17 @@ public:
return usrp_control_write(request, value, index, 0, 0);
}
+ int usrp_i2c_write(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len)
+ {
+ return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len);
+ }
+
+ int usrp_i2c_read(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len)
+ {
+ return usrp_control_read(VRQ_I2C_READ, i2c_addr, 0, buf, len);
+ }
+
+
private:
uhd::transport::usb_control::sptr _ctrl_transport;
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
index deedec4e8..a02d9f96c 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
@@ -50,6 +50,13 @@ public:
virtual int usrp_load_fpga(std::string filename) = 0;
/*!
+ * Load USB descriptor file in Intel HEX format into EEPROM
+ * \param filename name of EEPROM image
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_load_eeprom(std::string filestring) = 0;
+
+ /*!
* Set led usrp
* \param led_num which LED to control (0 or 1)
* \param on turn LED on or off
@@ -127,6 +134,30 @@ public:
unsigned char *buff,
boost::uint16_t length) = 0;
+ /*!
+ * Perform an I2C write
+ * \param i2c_addr I2C device address
+ * \param buf data to be written
+ * \param len length of data in bytes
+ * \return number of bytes written or error
+ */
+
+ virtual int usrp_i2c_write(boost::uint16_t i2c_addr,
+ unsigned char *buf,
+ boost::uint16_t len) = 0;
+
+ /*!
+ * Perform an I2C read
+ * \param i2c_addr I2C device address
+ * \param buf data to be read
+ * \param len length of data in bytes
+ * \return number of bytes read or error
+ */
+
+ virtual int usrp_i2c_read(boost::uint16_t i2c_addr,
+ unsigned char *buf,
+ boost::uint16_t len) = 0;
+
};
#endif /* INCLUDED_USRP_CTRL_HPP */
diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp
index 8756a21c9..4bc18dd16 100644
--- a/host/lib/usrp/usrp1/usrp1_iface.cpp
+++ b/host/lib/usrp/usrp1/usrp1_iface.cpp
@@ -109,18 +109,19 @@ public:
******************************************************************/
static const size_t max_i2c_data_bytes = 64;
+ //TODO: make this handle EEPROM page sizes. right now you can't write over a 16-byte boundary.
+ //to accomplish this you'll have to have addr offset as a separate parameter.
+
void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes)
{
UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes);
unsigned char buff[max_i2c_data_bytes];
- std::copy(bytes.begin(), bytes.end(), buff);
+ std::copy(bytes.begin(), bytes.end(), buff);
- int ret = _ctrl_transport->usrp_control_write(VRQ_I2C_WRITE,
- addr & 0xff,
- 0,
- buff,
- bytes.size());
+ int ret = _ctrl_transport->usrp_i2c_write(addr & 0xff,
+ buff,
+ bytes.size());
// TODO throw and catch i2c failures during eeprom read
if (iface_debug && (ret < 0))
@@ -132,11 +133,9 @@ public:
UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes);
unsigned char buff[max_i2c_data_bytes];
- int ret = _ctrl_transport->usrp_control_read(VRQ_I2C_READ,
- addr & 0xff,
- 0,
- buff,
- num_bytes);
+ int ret = _ctrl_transport->usrp_i2c_read(addr & 0xff,
+ buff,
+ num_bytes);
// TODO throw and catch i2c failures during eeprom read
if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes))) {
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 3c3306525..8ad148274 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -34,6 +34,11 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::transport;
+const boost::uint16_t USRP1_VENDOR_ID = 0xfffe;
+const boost::uint16_t USRP1_PRODUCT_ID = 0x0002;
+const boost::uint16_t FX2_VENDOR_ID = 0x04b4;
+const boost::uint16_t FX2_PRODUCT_ID = 0x8613;
+
const std::vector<usrp1_impl::dboard_slot_t> usrp1_impl::_dboard_slots = boost::assign::list_of
(usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B)
;
@@ -54,33 +59,32 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
);
std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl;
+ boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID;
+ boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID;
+
//see what we got on the USB bus
std::vector<usb_device_handle::sptr> device_list =
- usb_device_handle::get_device_list();
+ usb_device_handle::get_device_list(vid, pid);
+
+ if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found
//find the usrps and load firmware
BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
- if (handle->get_vendor_id() == 0xfffe &&
- handle->get_product_id() == 0x0002) {
-
usb_control::sptr ctrl_transport = usb_control::make(handle);
usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport);
usrp_ctrl->usrp_load_firmware(usrp1_fw_image);
- }
}
- //get descriptors again with serial number
- device_list = usb_device_handle::get_device_list();
+ //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware
+ vid = USRP1_VENDOR_ID;
+ pid = USRP1_PRODUCT_ID;
+ device_list = usb_device_handle::get_device_list(vid, pid);
BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
- if (handle->get_vendor_id() == 0xfffe &&
- handle->get_product_id() == 0x0002) {
-
device_addr_t new_addr;
new_addr["type"] = "usrp1";
new_addr["serial"] = handle->get_serial();
usrp1_addrs.push_back(new_addr);
- }
}
return usrp1_addrs;
@@ -99,17 +103,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr)
//try to match the given device address with something on the USB bus
std::vector<usb_device_handle::sptr> device_list =
- usb_device_handle::get_device_list();
+ usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID);
//create data and control transports
usb_zero_copy::sptr data_transport;
usrp_ctrl::sptr usrp_ctrl;
- BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
- if (handle->get_vendor_id() == 0xfffe &&
- handle->get_product_id() == 0x0002 &&
- handle->get_serial() == device_addr["serial"]) {
+ BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
+ if (handle->get_serial() == device_addr["serial"]) {
usb_control::sptr ctrl_transport = usb_control::make(handle);
usrp_ctrl = usrp_ctrl::make(ctrl_transport);
usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index c349a9018..9d788b06c 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -39,9 +39,13 @@ TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd)
ADD_EXECUTABLE(usrp_burn_db_eeprom usrp_burn_db_eeprom.cpp)
TARGET_LINK_LIBRARIES(usrp_burn_db_eeprom uhd)
+ADD_EXECUTABLE(usrp_init_eeprom usrp_init_eeprom.cpp)
+TARGET_LINK_LIBRARIES(usrp_init_eeprom uhd)
+
INSTALL(TARGETS
usrp2_addr_burner
usrp_burn_db_eeprom
+ usrp_init_eeprom
RUNTIME DESTINATION ${PKG_DATA_DIR}/utils
)
diff --git a/host/utils/usrp_init_eeprom.cpp b/host/utils/usrp_init_eeprom.cpp
new file mode 100644
index 000000000..28c7c5745
--- /dev/null
+++ b/host/utils/usrp_init_eeprom.cpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/device.hpp>
+#include <uhd/usrp/device_props.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("image", po::value<std::string>(), "IHX image file")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("USRP EEPROM initialization %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //load the options into the address
+ uhd::device_addr_t device_addr;
+ device_addr["type"] = "usrp1";
+ device_addr["uninit"] = "yeah"; //tell find to look for an uninitialized FX2
+
+ //find and create a control transport to do the writing.
+
+ uhd::device_addrs_t found_addrs = uhd::device::find(device_addr);
+
+ if (found_addrs.size() == 0){
+ std::cerr << "No uninitialized USRP devices found" << std::endl;
+ return ~0;
+ }
+
+ for (size_t i = 0; i < found_addrs.size(); i++){
+ std::cout << "Writing EEPROM data..." << std::endl;
+ //uhd::device_addrs_t devs = uhd::device::find(found_addrs[i]);
+ uhd::device::sptr dev = uhd::device::make(found_addrs[i]);
+ wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD];
+ mb[std::string("load_eeprom")] = vm["image"].as<std::string>();
+ }
+
+
+ std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
+ return 0;
+}