summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-06-06 10:21:45 +0100
committerJosh Blum <josh@joshknows.com>2011-06-06 10:21:45 +0100
commit8da2d8426e2a668b9fde31773a9e313a4ce1c2bb (patch)
tree4f047a32a431d24928992425c3f2d08bc06d001e
parentf239b8517b238923aacc161664857a7d7b830ab0 (diff)
downloaduhd-8da2d8426e2a668b9fde31773a9e313a4ce1c2bb.tar.gz
uhd-8da2d8426e2a668b9fde31773a9e313a4ce1c2bb.tar.bz2
uhd-8da2d8426e2a668b9fde31773a9e313a4ce1c2bb.zip
usrp-e100: bring up the clock as the first thing
We init the clock as the app wants it as the first thing we do. This greatly simplifies logic, no need to conditionally init. Clock config: perform soft reset, and removed ignore sync work Added open/close to iface so we can open and close w/o re-making. Other misc tweaks involving prints, etc...
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp21
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_iface.cpp38
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_iface.hpp14
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.cpp84
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.hpp20
5 files changed, 89 insertions, 88 deletions
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
index f1b29840a..742959ae3 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
@@ -172,6 +172,12 @@ public:
_chan_rate = 0.0;
_out_rate = 0.0;
+ //perform soft-reset
+ _ad9522_regs.soft_reset = 1;
+ this->send_reg(0x000);
+ this->latch_regs();
+ _ad9522_regs.soft_reset = 0;
+
//init the clock gen registers
//Note: out0 should already be clocking the FPGA or this isnt going to work
_ad9522_regs.sdo_active = ad9522_regs_t::SDO_ACTIVE_SDO_SDIO;
@@ -437,8 +443,6 @@ private:
}
void calibrate_now(void){
- set_ignore_sync_fpga_plus_codec(false); //want vco cal to sync
-
//vco calibration routine:
_ad9522_regs.vco_calibration_now = 0;
this->send_reg(0x18);
@@ -467,20 +471,9 @@ private:
_ad9522_regs.get_read_reg(addr), 24
);
_ad9522_regs.set_reg(addr, reg);
- if (_ad9522_regs.digital_lock_detect) goto finalize;
+ if (_ad9522_regs.digital_lock_detect) return;
}
UHD_MSG(error) << "USRP-E100 clock control: lock detection timeout" << std::endl;
- finalize:
-
- set_ignore_sync_fpga_plus_codec(true); //never loose sync between these two
- }
-
- void set_ignore_sync_fpga_plus_codec(bool enb){
- _ad9522_regs.divider0_ignore_sync = (enb)?1:0; // master FPGA clock ignores sync (always on, cannot be disabled by sync pulse)
- _ad9522_regs.divider1_ignore_sync = (enb)?1:0; // codec clock ignores sync (always on, cannot be disabled by sync pulse)
- this->send_reg(0x191);
- this->send_reg(0x194);
- this->latch_regs();
}
void soft_sync(void){
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
index a1a6cdb85..93c8cc7b5 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp
@@ -18,6 +18,7 @@
#include "usrp_e100_iface.hpp"
#include "usrp_e100_regs.hpp"
#include <uhd/exception.hpp>
+#include <uhd/utils/msg.hpp>
#include <sys/ioctl.h> //ioctl
#include <fcntl.h> //open, close
#include <linux/usrp_e.h> //ioctl structures and constants
@@ -100,12 +101,9 @@ public:
return _node_fd;
}
- /*******************************************************************
- * Structors
- ******************************************************************/
- usrp_e100_iface_impl(const std::string &node):
- _i2c_dev_iface(i2c_dev_iface("/dev/i2c-3"))
- {
+ void open(const std::string &node){
+ UHD_MSG(status) << "Opening device node " << node << "..." << std::endl;
+
//open the device node and check file descriptor
if ((_node_fd = ::open(node.c_str(), O_RDWR)) < 0){
throw uhd::io_error("Failed to open " + node);
@@ -114,18 +112,30 @@ public:
//check the module compatibility number
int module_compat_num = ::ioctl(_node_fd, USRP_E_GET_COMPAT_NUMBER, NULL);
if (module_compat_num != USRP_E_COMPAT_NUMBER){
- throw uhd::runtime_error(str(boost::format(
- "Expected module compatibility number 0x%x, but got 0x%x:\n"
- "The module build is not compatible with the host code build."
- ) % USRP_E_COMPAT_NUMBER % module_compat_num));
+ throw uhd::runtime_error(str(boost::format(
+ "Expected module compatibility number 0x%x, but got 0x%x:\n"
+ "The module build is not compatible with the host code build."
+ ) % USRP_E_COMPAT_NUMBER % module_compat_num));
+ }
+ }
+
+ void close(void){
+ ::close(_node_fd);
+ _node_fd = -1;
}
+ /*******************************************************************
+ * Structors
+ ******************************************************************/
+ usrp_e100_iface_impl(void):
+ _node_fd(-1),
+ _i2c_dev_iface(i2c_dev_iface("/dev/i2c-3"))
+ {
mb_eeprom = mboard_eeprom_t(get_i2c_dev_iface(), mboard_eeprom_t::MAP_E100);
}
~usrp_e100_iface_impl(void){
- //close the device node file descriptor
- ::close(_node_fd);
+ if (_node_fd >= 0) this->close();
}
/*******************************************************************
@@ -378,6 +388,6 @@ private:
/***********************************************************************
* Public Make Function
**********************************************************************/
-usrp_e100_iface::sptr usrp_e100_iface::make(const std::string &node){
- return sptr(new usrp_e100_iface_impl(node));
+usrp_e100_iface::sptr usrp_e100_iface::make(void){
+ return sptr(new usrp_e100_iface_impl());
}
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
index d9fe96db7..7df99cf4e 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.hpp
@@ -46,10 +46,9 @@ public:
/*!
* Make a new usrp-e interface with the control transport.
- * \param node the device node name
* \return a new usrp-e interface object
*/
- static sptr make(const std::string &node);
+ static sptr make(void);
/*!
* Get the underlying file descriptor.
@@ -58,6 +57,17 @@ public:
virtual int get_file_descriptor(void) = 0;
/*!
+ * Open a device node into this iface.
+ * \param node the device node name
+ */
+ virtual void open(const std::string &node) = 0;
+
+ /*!
+ * Close the open device node in this iface.
+ */
+ virtual void close(void) = 0;
+
+ /*!
* Perform an ioctl call on the device node file descriptor.
* This will throw when the internal ioctl call fails.
* \param request the control word
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
index 893e1eb45..6f80623be 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
@@ -54,7 +54,7 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){
new_addr["type"] = "usrp-e";
new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string();
try{
- usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]);
+ usrp_e100_iface::sptr iface = usrp_e100_iface::make();
new_addr["name"] = iface->mb_eeprom["name"];
new_addr["serial"] = iface->mb_eeprom["serial"];
}
@@ -88,59 +88,43 @@ static size_t hash_fpga_file(const std::string &file_path){
static device::sptr usrp_e100_make(const device_addr_t &device_addr){
//setup the main interface into fpga
- std::string node = device_addr["node"];
- UHD_MSG(status) << boost::format("Opening USRP-E on %s") % node << std::endl;
- usrp_e100_iface::sptr iface = usrp_e100_iface::make(node);
+ const std::string node = device_addr["node"];
+ usrp_e100_iface::sptr iface = usrp_e100_iface::make();
+ iface->open(node);
- //extract the fpga path for usrp-e
- std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", "usrp_e100_fpga_m2.bin"));
+ //setup clock control here to ensure that the FPGA has a good clock before we continue
+ const double master_clock_rate = device_addr.cast<double>("master_clock_rate", USRP_E_DEFAULT_CLOCK_RATE);
+ usrp_e100_clock_ctrl::sptr clock_ctrl = usrp_e100_clock_ctrl::make(iface, master_clock_rate);
- //compute a hash of the fpga file
+ //extract the fpga path for usrp-e and compute hash
+ const std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", USRP_E_FPGA_FILE_NAME));
const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image));
//When the hash does not match:
- // - unload the iface to free the node
- // - load the fpga configuration file
- // - re-open the iface on the node
+ // - close the device node
+ // - load the fpga bin file
+ // - re-open the device node
if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){
- iface.reset();
+ iface->close();
usrp_e100_load_fpga(usrp_e100_fpga_image);
- UHD_MSG(status) << boost::format("re-Opening USRP-E on %s") % node << std::endl;
- iface = usrp_e100_iface::make(node);
+ iface->open(node);
}
- //Perform wishbone readback tests:
- //If the tests fail, try to re-initialize the clock.
- //If the tests fail again, we just continue...
- for (size_t phase = 0; phase <= 1; phase++){
- bool test_fail = false;
- UHD_MSG(status) << "Performing wishbone readback test... " << std::flush;
- for (size_t i = 0; i < 100; i++){
- iface->poke32(UE_REG_SR_MISC_TEST32, file_hash);
- test_fail = iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash;
- if (test_fail) break; //exit loop on any failure
- }
- UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl;
-
- if (not test_fail) break; //no more tests, its good
-
- switch (phase){
- case 0:
- UHD_MSG(warning) << boost::format(
- "The FPGA may be clocked improperly.\n"
- "Attempting to re-initialize the clock...\n"
- );
- usrp_e100_clock_ctrl::make(iface, 64e6);
- break;
-
- case 1:
- UHD_MSG(error) << boost::format(
- "The FPGA is either clocked improperly\n"
- "or the FPGA build is not compatible.\n"
- );
- break;
- }
+ //Perform wishbone readback tests, these tests also write the hash
+ bool test_fail = false;
+ UHD_MSG(status) << "Performing wishbone readback test... " << std::flush;
+ for (size_t i = 0; i < 100; i++){
+ iface->poke32(UE_REG_SR_MISC_TEST32, file_hash);
+ test_fail = iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash;
+ if (test_fail) break; //exit loop on any failure
}
+ UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl;
+
+ if (test_fail) UHD_MSG(error) << boost::format(
+ "The FPGA is either clocked improperly\n"
+ "or the FPGA build is not compatible.\n"
+ "Subsequent errors may follow...\n"
+ );
//check that the compatibility is correct
const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
@@ -153,7 +137,7 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){
) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num));
}
- return device::sptr(new usrp_e100_impl(iface, device_addr));
+ return device::sptr(new usrp_e100_impl(device_addr, iface, clock_ctrl));
}
UHD_STATIC_BLOCK(register_usrp_e100_device){
@@ -164,20 +148,18 @@ UHD_STATIC_BLOCK(register_usrp_e100_device){
* Structors
**********************************************************************/
usrp_e100_impl::usrp_e100_impl(
+ const uhd::device_addr_t &device_addr,
usrp_e100_iface::sptr iface,
- const device_addr_t &device_addr
+ usrp_e100_clock_ctrl::sptr clock_ctrl
):
_iface(iface),
+ _clock_ctrl(clock_ctrl),
+ _codec_ctrl(usrp_e100_codec_ctrl::make(_iface)),
_data_xport(usrp_e100_make_mmap_zero_copy(_iface)),
_recv_frame_size(std::min(_data_xport->get_recv_frame_size(), size_t(device_addr.cast<double>("recv_frame_size", 1e9)))),
_send_frame_size(std::min(_data_xport->get_send_frame_size(), size_t(device_addr.cast<double>("send_frame_size", 1e9))))
{
- //setup interfaces into hardware
- const double master_clock_rate = device_addr.cast<double>("master_clock_rate", 64e6);
- _clock_ctrl = usrp_e100_clock_ctrl::make(_iface, master_clock_rate);
- _codec_ctrl = usrp_e100_codec_ctrl::make(_iface);
-
//initialize the mboard
mboard_init();
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
index 84703f828..820fcab6a 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
@@ -33,7 +33,9 @@
uhd::transport::zero_copy_if::sptr usrp_e100_make_mmap_zero_copy(usrp_e100_iface::sptr iface);
+static const std::string USRP_E_FPGA_FILE_NAME = "usrp_e100_fpga5.bin";
static const boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x05;
+static const double USRP_E_DEFAULT_CLOCK_RATE = 64e6;
//! load an fpga image from a bin file into the usrp-e fpga
extern void usrp_e100_load_fpga(const std::string &bin_file);
@@ -82,7 +84,11 @@ private:
class usrp_e100_impl : public uhd::device{
public:
//structors
- usrp_e100_impl(usrp_e100_iface::sptr, const uhd::device_addr_t &);
+ usrp_e100_impl(
+ const uhd::device_addr_t &,
+ usrp_e100_iface::sptr,
+ usrp_e100_clock_ctrl::sptr
+ );
~usrp_e100_impl(void);
//the io interface
@@ -96,6 +102,12 @@ private:
//interface to ioctls and file descriptor
usrp_e100_iface::sptr _iface;
+ //ad9522 clock control
+ usrp_e100_clock_ctrl::sptr _clock_ctrl;
+
+ //ad9862 codec control
+ usrp_e100_codec_ctrl::sptr _codec_ctrl;
+
//handle io stuff
uhd::transport::zero_copy_if::sptr _data_xport;
UHD_PIMPL_DECL(io_impl) _io_impl;
@@ -108,12 +120,6 @@ private:
//configuration shadows
uhd::clock_config_t _clock_config;
- //ad9522 clock control
- usrp_e100_clock_ctrl::sptr _clock_ctrl;
-
- //ad9862 codec control
- usrp_e100_codec_ctrl::sptr _codec_ctrl;
-
//device functions and settings
void get(const wax::obj &, wax::obj &);
void set(const wax::obj &, const wax::obj &);