diff options
| -rw-r--r-- | host/docs/usrp_e1xx.rst | 15 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.cpp | 21 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/fpga_downloader.cpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_iface.cpp | 141 | ||||
| -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 | 64 | ||||
| -rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.hpp | 22 | ||||
| -rw-r--r-- | host/usrp_e_utils/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/usrp_e_utils/clkgen_config.hpp | 305 | ||||
| -rw-r--r-- | host/usrp_e_utils/usrp-e-utility.cpp | 72 | 
10 files changed, 196 insertions, 471 deletions
| diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index fcaa57716..4ac9d133a 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -53,21 +53,6 @@ Example:      uhd_usrp_probe --args="master_clock_rate=52e6" -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Clock rate recovery - unbricking -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It is possible to set a clock rate such that the UHD can no longer communicate with the FPGA. -When this occurs, it is necessary to use the usrp-e-utility to recover the clock generator. -The recovery utility works by loading a special pass-through FPGA image so the computer -can talk directly to the clock generator over a SPI interface. - -Run the following commands to restore the clock generator to a usable state: -:: - -    cd <install-path>/share/uhd/usrp_e_utilities -    ./usrp-e-utility --fpga=../images/usrp_e100_pt_fpga.bin --reclk - -  ------------------------------------------------------------------------  Clock Synchronization  ------------------------------------------------------------------------ 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/fpga_downloader.cpp b/host/lib/usrp/usrp_e100/fpga_downloader.cpp index a7449d3b1..b8420796f 100644 --- a/host/lib/usrp/usrp_e100/fpga_downloader.cpp +++ b/host/lib/usrp/usrp_e100/fpga_downloader.cpp @@ -254,9 +254,9 @@ void usrp_e100_load_fpga(const std::string &bin_file){  	UHD_MSG(status) << "Loading FPGA image: " << bin_file << "... " << std::flush; -	if(std::system("/sbin/rmmod usrp_e") != 0){ -		UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not unload usrp_e module" << std::endl; -	} +//	if(std::system("/sbin/rmmod usrp_e") != 0){ +//		UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not unload usrp_e module" << std::endl; +//	}  	prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); @@ -264,9 +264,9 @@ void usrp_e100_load_fpga(const std::string &bin_file){  	send_file_to_fpga(bin_file, gpio_init_b, gpio_done); -	if(std::system("/sbin/modprobe usrp_e") != 0){ -		UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not load usrp_e module" << std::endl; -	} +//	if(std::system("/sbin/modprobe usrp_e") != 0){ +//		UHD_MSG(warning) << "USRP-E100 FPGA downloader: could not load usrp_e module" << std::endl; +//	}  } diff --git a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp index 55446da63..93c8cc7b5 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_iface.cpp @@ -18,14 +18,17 @@  #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 +#include <boost/thread/thread.hpp> //sleep  #include <boost/format.hpp>  #include <boost/thread/mutex.hpp>  #include <linux/i2c-dev.h>  #include <linux/i2c.h> -#include <stdexcept> +#include <iostream> +#include <fstream>  using namespace uhd;  using namespace uhd::usrp; @@ -98,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); @@ -112,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();      }      /******************************************************************* @@ -245,6 +257,10 @@ public:          size_t num_bits,          bool readback      ){ +        if (which_slave == UE_SPI_SS_AD9522) return bitbang_spi( +            bits, num_bits, readback +        ); +          //load data struct          usrp_e_spi data;          data.readback = (readback)? UE_SPI_TXRX : UE_SPI_TXONLY; @@ -263,11 +279,101 @@ public:          //unload the data          return data.data;      } -     + +    boost::uint32_t bitbang_spi( +        boost::uint32_t bits, +        size_t num_bits, +        bool readback +    ){ +        boost::uint32_t rb_bits = 0; + +        _spi_bitbanger.spi_sen_gpio_write(0); + +        for (size_t i = 0; i < num_bits; i++){ +            _spi_bitbanger.spi_sclk_gpio_write(0); +            _spi_bitbanger.spi_mosi_gpio_write((bits >> (num_bits-i-1)) & 0x1); +            boost::this_thread::sleep(boost::posix_time::microseconds(10)); +            if (readback) rb_bits = (rb_bits << 1) | _spi_bitbanger.spi_miso_gpio_read(); +            _spi_bitbanger.spi_sclk_gpio_write(1); +            boost::this_thread::sleep(boost::posix_time::microseconds(10)); +        } + +        _spi_bitbanger.spi_sen_gpio_write(1); +        boost::this_thread::sleep(boost::posix_time::microseconds(100)); + +        return rb_bits; +    } + +    class bitbang_spi_guts{ +    public: +        bitbang_spi_guts(void){ +            //setup gpio pin directions +            this->set_gpio_direction(spi_sclk_gpio, "out"); +            this->set_gpio_direction(spi_sen_gpio, "out"); +            this->set_gpio_direction(spi_mosi_gpio, "out"); +            this->set_gpio_direction(spi_miso_gpio, "in"); + +            //open the gpio pin values +            _spi_sclk_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sclk_gpio).c_str()); +            _spi_sen_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_sen_gpio).c_str()); +            _spi_mosi_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_mosi_gpio).c_str()); +            _spi_miso_gpio_value.open(str(boost::format("/sys/class/gpio/gpio%d/value") % spi_miso_gpio).c_str()); +        } + +        ~bitbang_spi_guts(void){ +            this->set_gpio_direction(spi_sclk_gpio, "in"); +            this->set_gpio_direction(spi_sen_gpio, "in"); +            this->set_gpio_direction(spi_mosi_gpio, "in"); +        } + +        void spi_sclk_gpio_write(int val){ +            _spi_sclk_gpio_value << val << std::endl << std::flush; +        } + +        void spi_sen_gpio_write(int val){ +            _spi_sen_gpio_value << val << std::endl << std::flush; +        } + +        void spi_mosi_gpio_write(int val){ +            _spi_mosi_gpio_value << val << std::endl << std::flush; +        } + +        int spi_miso_gpio_read(void){ +            std::string val; +            std::getline(_spi_miso_gpio_value, val); +            _spi_miso_gpio_value.seekg(0); +            return int(val.at(0) - '0') & 0x1; +        } + +    private: +        enum{ +            spi_sclk_gpio = 65, +            spi_sen_gpio = 186, +            spi_mosi_gpio = 145, +            spi_miso_gpio = 147, +        }; + +        void set_gpio_direction(int gpio_num, const std::string &dir){ +            std::ofstream export_file("/sys/class/gpio/export"); +            export_file << gpio_num << std::endl << std::flush; +            export_file.close(); + +            std::ofstream dir_file(str(boost::format("/sys/class/gpio/gpio%d/direction") % gpio_num).c_str()); +            dir_file << dir << std::endl << std::flush; +            dir_file.close(); +        } + +        std::ofstream _spi_sclk_gpio_value, _spi_sen_gpio_value, _spi_mosi_gpio_value; +        std::ifstream _spi_miso_gpio_value; +    }; + +    /******************************************************************* +     * UART +     ******************************************************************/      void write_uart(boost::uint8_t, const std::string &) {          throw uhd::not_implemented_error("Unhandled command write_uart()");      } -     +      std::string read_uart(boost::uint8_t) {          throw uhd::not_implemented_error("Unhandled command read_uart()");      } @@ -276,11 +382,12 @@ private:      int _node_fd;      i2c_dev_iface _i2c_dev_iface;      boost::mutex _ctrl_mutex; +    bitbang_spi_guts _spi_bitbanger;  };  /***********************************************************************   * 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 5b039aafc..36db810a8 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,39 +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.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); -        sleep(1); ///\todo do this better one day. -        UHD_MSG(status) << boost::format("re-Opening USRP-E on %s") % node << std::endl; -        iface = usrp_e100_iface::make(node); +        iface->open(node);      } -    //store the hash into the FPGA register -    iface->poke32(UE_REG_SR_MISC_TEST32, file_hash); - -    //check that the hash can be readback correctly -    if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ -        UHD_MSG(error) << boost::format( -            "The FPGA hash readback failed!\n" -            "The FPGA is either clocked improperly\n" -            "or the FPGA build is not compatible.\n" -        ); +    //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); @@ -133,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){ @@ -144,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 1c17863fb..0c6087a85 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 boost::uint16_t USRP_E_FPGA_COMPAT_NUM = 0x04; +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; @@ -109,12 +121,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 &); diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index e7d6ae4b8..5f244a216 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -28,7 +28,6 @@ IF(ENABLE_USRP_E_UTILS)      INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/lib/ic_reg_maps)      SET(usrp_e_utils_sources -        usrp-e-utility.cpp          usrp-e-loopback.c          usrp-e-timed.c          usrp-e-wb-test.cpp diff --git a/host/usrp_e_utils/clkgen_config.hpp b/host/usrp_e_utils/clkgen_config.hpp deleted file mode 100644 index f39f8bb19..000000000 --- a/host/usrp_e_utils/clkgen_config.hpp +++ /dev/null @@ -1,305 +0,0 @@ -// -// Copyright 2011 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/>. -// - -#ifndef USRP_E_UTILS_CLKGEN_CONFIG_HPP -#define USRP_E_UTILS_CLKGEN_CONFIG_HPP - -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> -#include <cstdlib> - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <linux/spi/spidev.h> - -namespace usrp_e_clkgen_config_utility{ - -// Programming data for clock gen chip -static const unsigned int config_data[] = { -	0x000024, -	0x023201, -	0x000081, -	0x000400, -	0x00104c, -	0x001101, -	0x001200, -	0x001300, -	0x001414, -	0x001500, -	0x001604, -	0x001704, -	0x001807, -	0x001900, -	//0x001a00,//for debug -	0x001a32, -	0x001b12, -	0x001c44, -	0x001d00, -	0x001e00, -	0x00f062, -	0x00f162, -	0x00f262, -	0x00f362, -	0x00f462, -	0x00f562, -	0x00f662, -	0x00f762, -	0x00f862, -	0x00f962, -	0x00fa62, -	0x00fb62, -	0x00fc00, -	0x00fd00, -	0x019021, -	0x019100, -	0x019200, -	0x019321, -	0x019400, -	0x019500, -	0x019611, -	0x019700, -	0x019800, -	0x019900, -	0x019a00, -	0x019b00, -	0x01e003, -	0x01e102, -	0x023000, -	0x023201, -	0x0b0201, -	0x0b0300, -	0x001fff, -	0x0a0000, -	0x0a0100, -	0x0a0200, -	0x0a0302, -	0x0a0400, -	0x0a0504, -	0x0a060e, -	0x0a0700, -	0x0a0810, -	0x0a090e, -	0x0a0a00, -	0x0a0bf0, -	0x0a0c0b, -	0x0a0d01, -	0x0a0e90, -	0x0a0f01, -	0x0a1001, -	0x0a11e0, -	0x0a1201, -	0x0a1302, -	0x0a1430, -	0x0a1580, -	0x0a16ff, -	0x023201, -	0x0b0301, -	0x023201, -}; - - -const unsigned int CLKGEN_SELECT = 145; - - -enum gpio_direction {IN, OUT}; - -class gpio { -	public: - -	gpio(unsigned int gpio_num, gpio_direction pin_direction, bool close_action); -	~gpio(); - -	bool get_value(); -	void set_value(bool state); - -	private: - -	unsigned int gpio_num; - -	std::stringstream base_path; -	std::fstream value_file; -	std::fstream direction_file; -	bool close_action; // True set to input and release, false do nothing -}; - -class spidev { -	public: - -	spidev(std::string dev_name); -	~spidev(); - -	void send(char *wbuf, char *rbuf, unsigned int nbytes); - -	private: - -	int fd; - -}; - -gpio::gpio(unsigned int _gpio_num, gpio_direction pin_direction, bool close_action) -:close_action(close_action) -{ -	std::fstream export_file; - -	gpio_num = _gpio_num; - -	export_file.open("/sys/class/gpio/export", std::ios::out); -	if (!export_file.is_open())  ///\todo Poor error handling -		std::cout << "Failed to open gpio export file." << std::endl; - -	export_file << gpio_num << std::endl; - -	base_path << "/sys/class/gpio/gpio" << gpio_num << std::flush; - -	std::string direction_file_name; - -	direction_file_name = base_path.str() + "/direction"; - -	direction_file.open(direction_file_name.c_str());  -	if (!direction_file.is_open()) -		std::cout << "Failed to open direction file." << std::endl; -	if (pin_direction == OUT) -		direction_file << "out" << std::endl; -	else -		direction_file << "in" << std::endl; - -	std::string value_file_name; - -	value_file_name = base_path.str() + "/value"; - -	value_file.open(value_file_name.c_str(), std::ios_base::in | std::ios_base::out); -	if (!value_file.is_open()) -		std::cout << "Failed to open value file." << std::endl; -} - -bool gpio::get_value() -{ - -	std::string val; - -	std::getline(value_file, val); -	value_file.seekg(0); - -	if (val == "0") -		return false; -	else if (val == "1") -		return true; -	else -		std::cout << "Data read from value file|" << val << "|" << std::endl; - -	return false; -} - -void gpio::set_value(bool state) -{ - -	if (state) -		value_file << "1" << std::endl; -	else -		value_file << "0" << std::endl; -} - -gpio::~gpio() -{ -	if (close_action) { -		std::fstream unexport_file; - -		direction_file << "in" << std::endl; - -		unexport_file.open("/sys/class/gpio/unexport", std::ios::out); -		if (!unexport_file.is_open())  ///\todo Poor error handling -			std::cout << "Failed to open gpio export file." << std::endl; - -		unexport_file << gpio_num << std::endl; -		 -	 } - -} - -spidev::spidev(std::string fname) -{ -	int ret; -	int mode = 0; -	int speed = 12000; -	int bits = 24; - -	fd = open(fname.c_str(), O_RDWR); - -	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); -	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); -	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); -} -	 - -spidev::~spidev() -{ -	close(fd); -} - -void spidev::send(char *buf, char *rbuf, unsigned int nbytes) -{ -	int ret; - -	struct spi_ioc_transfer tr; -	tr.tx_buf = (unsigned long) buf; -	tr.rx_buf = (unsigned long) rbuf; -	tr.len = nbytes; -	tr.delay_usecs = 0; -	tr.speed_hz = 12000; -	tr.bits_per_word = 24; - -	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); - -} - -static void send_config_to_clkgen(gpio &chip_select, const unsigned int data[], unsigned int data_size) -{ -	spidev spi("/dev/spidev1.0"); -	unsigned int rbuf; - -	for (unsigned int i = 0; i < data_size; i++) { - -		//std::cout << "sending " << std::hex << data[i] << std::endl; -		chip_select.set_value(0); -		spi.send((char *)&data[i], (char *)&rbuf, 4); -		chip_select.set_value(1); -		unsigned int addr = (data[i] >> 8) & 0xfff; -		if (addr == 0x232 || addr == 0x000){ -			std::cout << "." << std::flush; -			sleep(1); -		} -	}; -	std::cout << std::endl; -} - -}//namespace usrp_e_clkgen_config_utility - -//int main(int argc, char *argv[]) -static void clock_genconfig_main(void) -{ -	using namespace usrp_e_clkgen_config_utility; -	gpio clkgen_select(CLKGEN_SELECT, OUT, true); - -	send_config_to_clkgen(clkgen_select, config_data, sizeof(config_data)/sizeof(config_data[0])); -} - -#endif /*USRP_E_UTILS_CLKGEN_CONFIG_HPP*/ diff --git a/host/usrp_e_utils/usrp-e-utility.cpp b/host/usrp_e_utils/usrp-e-utility.cpp deleted file mode 100644 index 47a2c0900..000000000 --- a/host/usrp_e_utils/usrp-e-utility.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright 2011 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 <boost/program_options.hpp> -#include <boost/format.hpp> -#include <stdexcept> -#include <iostream> - -#include "fpga_downloader.cpp" -#include "clkgen_config.hpp" - -namespace po = boost::program_options; - -int UHD_SAFE_MAIN(int argc, char *argv[]){ - -    //variables to be set by po -    std::string fpga_path; - -    //setup the program options -    po::options_description desc("Allowed options"); -    desc.add_options() -        ("help", "help message") -        ("fpga", po::value<std::string>(&fpga_path), "loads the specified FPGA file") -        ("reclk",                                    "runs the clock recovery") -    ; -    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("UHD USRP-E Utility %s") % desc << std::endl; -        return ~0; -    } - -    bool loaded_fpga_image = false; -    if (vm.count("fpga") != 0){ -        std::cout << "USRP-E Utility loading the FPGA..." << std::endl << std::endl; -        usrp_e100_load_fpga(fpga_path); -        loaded_fpga_image = true; -        sleep(1); -    } - -    if (vm.count("reclk") != 0){ -        std::cout << "USRP-E Utility running the clock recovery..." << std::flush; -        //if an image was not loaded or specified, we load pass-through -        if (fpga_path.empty()) throw std::runtime_error( -            "Please specify the path to the pass-though FPGA image for your device.\n" -            "  usrp-e-utility --reclk --fpga=/usr/share/uhd/images/usrp_e1xx_pt_fpga.bin" -        ); -        clock_genconfig_main(); -    } - -    std::cout << "Done!" << std::endl; - -    return 0; -} | 
