diff options
| -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 &); | 
