diff options
author | Josh Blum <josh@joshknows.com> | 2011-06-06 10:21:45 +0100 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2011-06-06 10:21:45 +0100 |
commit | 8da2d8426e2a668b9fde31773a9e313a4ce1c2bb (patch) | |
tree | 4f047a32a431d24928992425c3f2d08bc06d001e /host/lib | |
parent | f239b8517b238923aacc161664857a7d7b830ab0 (diff) | |
download | uhd-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...
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.cpp | 21 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 38 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.hpp | 14 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 84 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 20 |
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 &); |