aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp_e100
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-05-16 12:08:23 -0700
committerJosh Blum <josh@joshknows.com>2011-05-16 12:08:23 -0700
commit22097e81dc54c895ed411c74c1829721e3a1ce5e (patch)
tree8cc9ca6d8bb0432b9562fc19636eca3421b21100 /host/lib/usrp/usrp_e100
parent13be023531fa1be8d43b999c3ea5ab477f101fdc (diff)
parentea5ce50a465e714c63196f52df97fb3e927e701c (diff)
downloaduhd-22097e81dc54c895ed411c74c1829721e3a1ce5e.tar.gz
uhd-22097e81dc54c895ed411c74c1829721e3a1ce5e.tar.bz2
uhd-22097e81dc54c895ed411c74c1829721e3a1ce5e.zip
Merge branch 'master' into release_work
Diffstat (limited to 'host/lib/usrp/usrp_e100')
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp62
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.hpp3
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp3
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.cpp73
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp12
5 files changed, 78 insertions, 75 deletions
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
index 65162dbeb..49ce0c742 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
@@ -37,7 +37,6 @@ using namespace uhd;
**********************************************************************/
static const bool ENABLE_THE_TEST_OUT = true;
static const double REFERENCE_INPUT_RATE = 10e6;
-static const double DEFAULT_OUTPUT_RATE = 64e6;
/***********************************************************************
* Helpers
@@ -168,7 +167,7 @@ static clock_settings_type get_clock_settings(double rate){
**********************************************************************/
class usrp_e100_clock_ctrl_impl : public usrp_e100_clock_ctrl{
public:
- usrp_e100_clock_ctrl_impl(usrp_e100_iface::sptr iface){
+ usrp_e100_clock_ctrl_impl(usrp_e100_iface::sptr iface, double master_clock_rate){
_iface = iface;
_chan_rate = 0.0;
_out_rate = 0.0;
@@ -181,27 +180,13 @@ public:
_ad9522_regs.ld_pin_control = 0x00; //dld
_ad9522_regs.refmon_pin_control = 0x12; //show ref2
_ad9522_regs.lock_detect_counter = ad9522_regs_t::LOCK_DETECT_COUNTER_16CYC;
+ _ad9522_regs.divider0_ignore_sync = 1; // master FPGA clock ignores sync (always on, cannot be disabled by sync pulse)
this->use_internal_ref();
- //initialize the FPGA clock to something
- bool fpga_clock_initialized = false;
- try{
- if (not _iface->mb_eeprom["mcr"].empty()){
- UHD_MSG(status) << "Read FPGA clock rate from EEPROM setting." << std::endl;
- const double master_clock_rate = boost::lexical_cast<double>(_iface->mb_eeprom["mcr"]);
- UHD_MSG(status) << boost::format("Initializing FPGA clock to %fMHz...") % (master_clock_rate/1e6) << std::endl;
- this->set_fpga_clock_rate(master_clock_rate);
- fpga_clock_initialized = true;
- }
- }
- catch(const std::exception &e){
- UHD_MSG(error) << "Error setting FPGA clock rate from EEPROM: " << e.what() << std::endl;
- }
- if (not fpga_clock_initialized){ //was not set... use the default rate
- UHD_MSG(status) << boost::format("Initializing FPGA clock to %fMHz...") % (DEFAULT_OUTPUT_RATE/1e6) << std::endl;
- this->set_fpga_clock_rate(DEFAULT_OUTPUT_RATE);
- }
+ //initialize the FPGA clock rate
+ UHD_MSG(status) << boost::format("Initializing FPGA clock to %fMHz...") % (master_clock_rate/1e6) << std::endl;
+ this->set_fpga_clock_rate(master_clock_rate);
this->enable_test_clock(ENABLE_THE_TEST_OUT);
this->enable_rx_dboard_clock(false);
@@ -358,7 +343,7 @@ public:
);
this->send_reg(0x199);
this->send_reg(0x19a);
- this->latch_regs();
+ this->soft_sync();
}
double get_rx_clock_rate(void){
@@ -393,7 +378,7 @@ public:
);
this->send_reg(0x196);
this->send_reg(0x197);
- this->latch_regs();
+ this->soft_sync();
}
double get_tx_clock_rate(void){
@@ -409,6 +394,7 @@ public:
_ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF2;
_ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL;
this->send_reg(0x01C);
+ this->latch_regs();
}
void use_external_ref(void) {
@@ -417,6 +403,7 @@ public:
_ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1;
_ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_MANUAL;
this->send_reg(0x01C);
+ this->latch_regs();
}
void use_auto_ref(void) {
@@ -424,6 +411,8 @@ public:
_ad9522_regs.enable_ref1 = 1;
_ad9522_regs.select_ref = ad9522_regs_t::SELECT_REF_REF1;
_ad9522_regs.enb_auto_ref_switchover = ad9522_regs_t::ENB_AUTO_REF_SWITCHOVER_AUTO;
+ this->send_reg(0x01C);
+ this->latch_regs();
}
private:
@@ -459,15 +448,36 @@ private:
//wait for calibration done:
static const boost::uint8_t addr = 0x01F;
for (size_t ms10 = 0; ms10 < 100; ms10++){
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
boost::uint32_t reg = _iface->read_spi(
UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE,
_ad9522_regs.get_read_reg(addr), 24
);
_ad9522_regs.set_reg(addr, reg);
- if (_ad9522_regs.vco_calibration_finished) return;
- boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ if (_ad9522_regs.vco_calibration_finished) goto wait_for_ld;
}
UHD_MSG(error) << "USRP-E100 clock control: VCO calibration timeout" << std::endl;
+ wait_for_ld:
+ //wait for digital lock detect:
+ for (size_t ms10 = 0; ms10 < 100; ms10++){
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ boost::uint32_t reg = _iface->read_spi(
+ UE_SPI_SS_AD9522, spi_config_t::EDGE_RISE,
+ _ad9522_regs.get_read_reg(addr), 24
+ );
+ _ad9522_regs.set_reg(addr, reg);
+ if (_ad9522_regs.digital_lock_detect) return;
+ }
+ UHD_MSG(error) << "USRP-E100 clock control: lock detection timeout" << std::endl;
+ }
+
+ void soft_sync(void){
+ _ad9522_regs.soft_sync = 1;
+ this->send_reg(0x230);
+ this->latch_regs();
+ _ad9522_regs.soft_sync = 0;
+ this->send_reg(0x230);
+ this->latch_regs();
}
void send_all_regs(void){
@@ -492,6 +502,6 @@ private:
/***********************************************************************
* Clock Control Make
**********************************************************************/
-usrp_e100_clock_ctrl::sptr usrp_e100_clock_ctrl::make(usrp_e100_iface::sptr iface){
- return sptr(new usrp_e100_clock_ctrl_impl(iface));
+usrp_e100_clock_ctrl::sptr usrp_e100_clock_ctrl::make(usrp_e100_iface::sptr iface, double master_clock_rate){
+ return sptr(new usrp_e100_clock_ctrl_impl(iface, master_clock_rate));
}
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.hpp b/host/lib/usrp/usrp_e100/clock_ctrl.hpp
index 507f914f3..6f16bc6ed 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.hpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.hpp
@@ -35,9 +35,10 @@ public:
/*!
* Make a new clock control object.
* \param iface the usrp_e100 iface object
+ * \param master clock rate the FPGA rate
* \return the clock control object
*/
- static sptr make(usrp_e100_iface::sptr iface);
+ static sptr make(usrp_e100_iface::sptr iface, double master_clock_rate);
/*!
* Set the rate of the fpga clock line.
diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp
index d31662eb5..b2533e7ee 100644
--- a/host/lib/usrp/usrp_e100/mboard_impl.cpp
+++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp
@@ -209,7 +209,8 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_CLOCK_RATE:
UHD_MSG(warning)
<< "I see that you are setting the master clock rate from the API.\n"
- << "You may find it more convenient to burn this setting into the EEPROM.\n"
+ << "You may want to pass this into the device address as mcr=<rate>.\n"
+ << "This way, the clock rate is guaranteed to be initialized first.\n"
<< "See the application notes for USRP-E1XX for further instructions.\n"
;
_clock_ctrl->set_fpga_clock_rate(val.as<double>());
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
index 4247746ab..e9e9b6e20 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp
@@ -76,6 +76,15 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){
/***********************************************************************
* Make
**********************************************************************/
+static size_t hash_fpga_file(const std::string &file_path){
+ size_t hash = 0;
+ std::ifstream file(file_path.c_str());
+ if (not file.good()) throw uhd::io_error("cannot open fpga file for read: " + file_path);
+ while (file.good()) boost::hash_combine(hash, file.get());
+ file.close();
+ return hash;
+}
+
static device::sptr usrp_e100_make(const device_addr_t &device_addr){
//setup the main interface into fpga
@@ -83,55 +92,44 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){
UHD_MSG(status) << boost::format("Opening USRP-E on %s") % node << std::endl;
usrp_e100_iface::sptr iface = usrp_e100_iface::make(node);
- //------------------------------------------------------------------
- //-- Handle the FPGA loading...
- //-- The image can be confimed as already loaded when:
- //-- 1) The compatibility number matches.
- //-- 2) The hash in the hash-file matches.
- //------------------------------------------------------------------
- static const char *hash_file_path = "/tmp/usrp_e100_hash";
-
//extract the fpga path for usrp-e
- std::string usrp_e100_fpga_image = find_image_path(
- device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin"
- );
-
- //calculate a hash of the fpga file
- size_t fpga_hash = 0;
- {
- std::ifstream file(usrp_e100_fpga_image.c_str());
- if (not file.good()) throw uhd::io_error(
- "cannot open fpga file for read: " + usrp_e100_fpga_image
- );
- do{
- boost::hash_combine(fpga_hash, file.get());
- } while (file.good());
- file.close();
- }
+ std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", "usrp_e100_fpga.bin"));
- //read the compatibility number
- boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
+ //compute a hash of the fpga file
+ const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image));
- //read the hash in the hash-file
- size_t loaded_hash = 0;
- try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){}
-
- //if not loaded: load the fpga image and write the hash-file
- if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM or loaded_hash != fpga_hash){
+ //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
+ if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){
iface.reset();
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);
- try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){}
+ }
+
+ //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"
+ );
}
//check that the compatibility is correct
- fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
+ const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM){
throw uhd::runtime_error(str(boost::format(
- "Expected fpga compatibility number 0x%x, but got 0x%x:\n"
- "The fpga build is not compatible with the host code build."
+ "\nPlease update the FPGA image for your device.\n"
+ "See the application notes for USRP E-Series for instructions.\n"
+ "Expected FPGA compatibility number 0x%x, but got 0x%x:\n"
+ "The FPGA build is not compatible with the host code build."
) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num));
}
@@ -156,7 +154,8 @@ usrp_e100_impl::usrp_e100_impl(
{
//setup interfaces into hardware
- _clock_ctrl = usrp_e100_clock_ctrl::make(_iface);
+ 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
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
index 26774aeda..bb421507a 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_mmap_zero_copy.cpp
@@ -51,14 +51,10 @@ public:
sptr get_new(void){
if (fp_verbose) UHD_LOGV(always) << " make_recv_buff: " << get_size() << std::endl;
_info->flags = RB_USER_PROCESS; //claim the frame
- return sptr(this, &usrp_e100_mmap_zero_copy_mrb::fake_deleter);
+ return make_managed_buffer(this);
}
private:
- static void fake_deleter(void *obj){
- static_cast<usrp_e100_mmap_zero_copy_mrb *>(obj)->release();
- }
-
const void *get_buff(void) const{return _mem;}
size_t get_size(void) const{return _info->len;}
@@ -90,14 +86,10 @@ public:
sptr get_new(void){
if (fp_verbose) UHD_LOGV(always) << " make_send_buff: " << get_size() << std::endl;
_info->flags = RB_USER_PROCESS; //claim the frame
- return sptr(this, &usrp_e100_mmap_zero_copy_msb::fake_deleter);
+ return make_managed_buffer(this);
}
private:
- static void fake_deleter(void *obj){
- static_cast<usrp_e100_mmap_zero_copy_msb *>(obj)->commit(0);
- }
-
void *get_buff(void) const{return _mem;}
size_t get_size(void) const{return _len;}