From 5c6c179689ef76ccd25d09ac4faeb9a836a066c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 17:26:15 -0700 Subject: usrp-e100: add ability to set/get default master clock rate from EEPROM Mboard eeprom map class can parse the setting (4 byte float). The clock control will try to set the eeprom rate if present, otherwise or under failure condition, it sets the default. Updated docs, example, and provided helpful verbose. I would prefer that users burn the desired rate to the eeprom (and they may too). --- host/docs/usrp_e1xx.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'host/docs/usrp_e1xx.rst') diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index 2818a0a65..b2a6ff08c 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -20,7 +20,6 @@ Example device address string representations to specify non-standard FPGA image Changing the master clock rate ------------------------------------------------------------------------ The master clock rate of the USRP embedded feeds both the FPGA DSP and the codec chip. -UHD can dynamically reconfigure the clock rate though the set_master_clock_rate() API call. Hundreds of rates between 32MHz and 64MHz are available. A few notable rates are: @@ -36,8 +35,12 @@ To use the 61.44MHz clock rate, the USRP embedded will require two jumpers to be * J16 is a two pin header, remove the jumper (or leave it on pin1 only) * J15 is a three pin header, move the jumper to (pin1, pin2) -For the correct clock settings, call usrp->set_master_clock_rate(61.44e6) -before any other parameters are set in your application. +Then run the following commands to record the setting in the EEPROM: +:: + + cd /share/uhd/utils + ./usrp_burn_mb_eeprom --key=master_clock_rate --val=61.44e6 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Set other rates - uses internal VCO @@ -47,8 +50,11 @@ To use other clock rates, the jumpers will need to be in the default position. * J16 is a two pin header, move the jumper to (pin1, pin2) * J15 is a three pin header, move the jumper to (pin2, pin3) -For the correct clock settings, call usrp->set_master_clock_rate(rate) -before any other parameters are set in your application. +Then run the following commands to record the setting in the EEPROM: +:: + + cd /share/uhd/utils + ./usrp_burn_mb_eeprom --key=master_clock_rate --val= ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clock rate recovery - unbricking -- cgit v1.2.3 From 6f0a98ee2e9e2090c6bf7d56260cb95b0eb1fbb3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 18:21:29 -0700 Subject: USRP1: added support for setting clock rate from EEPROM Basically, same deal as the previous changeset but for USRP1. Modified previous changes so that the key is shorter (mcr = master_clock_rate) --- host/docs/usrp1.rst | 9 ++++++-- host/docs/usrp_e1xx.rst | 8 +++---- host/lib/usrp/mboard_eeprom.cpp | 42 +++++++++++++++++++++++++++++----- host/lib/usrp/usrp1/clock_ctrl.cpp | 14 ++++++++++++ host/lib/usrp/usrp1/mboard_impl.cpp | 4 ++++ host/lib/usrp/usrp_e100/clock_ctrl.cpp | 4 ++-- 6 files changed, 67 insertions(+), 14 deletions(-) (limited to 'host/docs/usrp_e1xx.rst') diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index f77a26e0a..97a8c3bb5 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -136,6 +136,11 @@ The USRP can be modified to accept an external clock reference instead of the 64 The new external clock needs to be a square wave between +7dBm and +15dBm -For the correct clock settings, call usrp->set_master_clock_rate(EXT_CLOCK_FREQUENCY) -before any other parameters are set in your application. +After the hardware modification, +the user should burn the setting into the EEPROM, +so UHD can initialize with the correct clock rate. +Run the following commands to record the setting into the EEPROM: +:: + cd /share/uhd/utils + ./usrp_burn_mb_eeprom --args= --key=mcr --val= diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index b2a6ff08c..036d2c02c 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -35,11 +35,11 @@ To use the 61.44MHz clock rate, the USRP embedded will require two jumpers to be * J16 is a two pin header, remove the jumper (or leave it on pin1 only) * J15 is a three pin header, move the jumper to (pin1, pin2) -Then run the following commands to record the setting in the EEPROM: +Then run the following commands to record the setting into the EEPROM: :: cd /share/uhd/utils - ./usrp_burn_mb_eeprom --key=master_clock_rate --val=61.44e6 + ./usrp_burn_mb_eeprom --key=mcr --val=61.44e6 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,11 +50,11 @@ To use other clock rates, the jumpers will need to be in the default position. * J16 is a two pin header, move the jumper to (pin1, pin2) * J15 is a three pin header, move the jumper to (pin2, pin3) -Then run the following commands to record the setting in the EEPROM: +Then run the following commands to record the setting into the EEPROM: :: cd /share/uhd/utils - ./usrp_burn_mb_eeprom --key=master_clock_rate --val= + ./usrp_burn_mb_eeprom --key=mcr --val= ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clock rate recovery - unbricking diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 03096691e..29bc5ee32 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -181,6 +181,7 @@ static const size_t B000_SERIAL_LEN = 8; static const uhd::dict USRP_B000_OFFSETS = boost::assign::map_list_of ("serial", 0xf8) ("name", 0xf8 - NAME_MAX_LEN) + ("mcr", 0xf8 - NAME_MAX_LEN - sizeof(boost::uint32_t)) ; static void load_b000(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -193,6 +194,21 @@ static void load_b000(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ mb_eeprom["name"] = bytes_to_string(iface.read_eeprom( B000_EEPROM_ADDR, USRP_B000_OFFSETS["name"], NAME_MAX_LEN )); + + //extract master clock rate as a 32-bit uint in Hz + boost::uint32_t master_clock_rate; + const byte_vector_t rate_bytes = iface.read_eeprom( + B000_EEPROM_ADDR, USRP_B000_OFFSETS["mcr"], sizeof(master_clock_rate) + ); + std::copy( + rate_bytes.begin(), rate_bytes.end(), //input + reinterpret_cast(&master_clock_rate) //output + ); + master_clock_rate = ntohl(master_clock_rate); + if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ + mb_eeprom["mcr"] = boost::lexical_cast(master_clock_rate); + } + else mb_eeprom["mcr"] = ""; } static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -207,6 +223,19 @@ static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ B000_EEPROM_ADDR, USRP_B000_OFFSETS["name"], string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) ); + + //store the master clock rate as a 32-bit uint in Hz + if (mb_eeprom.has_key("mcr")){ + boost::uint32_t master_clock_rate = boost::uint32_t(boost::lexical_cast(mb_eeprom["mcr"])); + master_clock_rate = htonl(master_clock_rate); + const byte_vector_t rate_bytes( + reinterpret_cast(&master_clock_rate), + reinterpret_cast(&master_clock_rate) + sizeof(master_clock_rate) + ); + iface.write_eeprom( + B000_EEPROM_ADDR, USRP_B000_OFFSETS["mcr"], rate_bytes + ); + } } /*********************************************************************** * Implementation of E100 load/store @@ -223,7 +252,7 @@ struct e100_eeprom_map{ unsigned char env_setting[64]; unsigned char serial[10]; unsigned char name[NAME_MAX_LEN]; - float master_clock_rate; + float mcr; }; template static const byte_vector_t to_bytes(const T &item){ @@ -259,15 +288,16 @@ static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ //extract the master clock rate float master_clock_rate = 0; const byte_vector_t rate_bytes = iface.read_eeprom( - E100_EEPROM_ADDR, offsetof(e100_eeprom_map, master_clock_rate), sizeof(master_clock_rate) + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), sizeof(master_clock_rate) ); std::copy( rate_bytes.begin(), rate_bytes.end(), //source reinterpret_cast(&master_clock_rate) //destination ); if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ - mb_eeprom["master_clock_rate"] = boost::lexical_cast(master_clock_rate); + mb_eeprom["mcr"] = boost::lexical_cast(master_clock_rate); } + else mb_eeprom["mcr"] = ""; } static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -304,14 +334,14 @@ static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ store_e100_string_xx(name); //store the master clock rate - if (mb_eeprom.has_key("master_clock_rate")){ - const float master_clock_rate = float(boost::lexical_cast(mb_eeprom["master_clock_rate"])); + if (mb_eeprom.has_key("mcr")){ + const float master_clock_rate = float(boost::lexical_cast(mb_eeprom["mcr"])); const byte_vector_t rate_bytes( reinterpret_cast(&master_clock_rate), reinterpret_cast(&master_clock_rate) + sizeof(master_clock_rate) ); iface.write_eeprom( - E100_EEPROM_ADDR, offsetof(e100_eeprom_map, master_clock_rate), rate_bytes + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), rate_bytes ); } } diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index df5353b54..154e6a316 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -16,6 +16,9 @@ // #include "clock_ctrl.hpp" +#include +#include +#include using namespace uhd; @@ -31,6 +34,17 @@ class usrp1_clock_ctrl_impl : public usrp1_clock_ctrl { public: usrp1_clock_ctrl_impl(usrp1_iface::sptr iface): _iface(iface){ this->set_master_clock_freq(default_master_clock_rate); + try{ + if (not _iface->mb_eeprom["mcr"].empty()){ + std::cout << "Read FPGA clock rate from EEPROM setting." << std::endl; + const double master_clock_rate = boost::lexical_cast(_iface->mb_eeprom["mcr"]); + std::cout << boost::format("Initializing FPGA clock to %fMHz...") % (master_clock_rate/1e6) << std::endl; + this->set_master_clock_freq(master_clock_rate); + } + } + catch(const std::exception &e){ + std::cerr << "Error setting FPGA clock rate from EEPROM: " << e.what() << std::endl; + } } void set_master_clock_freq(double freq){ diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 870956568..eecae3fa7 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -378,6 +378,10 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) return; case MBOARD_PROP_CLOCK_RATE: + std::cerr << "Helpful message:" << std::endl; + std::cerr << " I see that you are setting the master clock rate from the API." << std::endl; + std::cerr << " You may find it more convenient to burn this setting into the EEPROM." << std::endl; + std::cerr << " See the application notes for USRP1 for further instructions." << std::endl; _clock_ctrl->set_master_clock_freq(val.as()); return; diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 851ce29b0..2e3eb5cb9 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -187,9 +187,9 @@ public: //initialize the FPGA clock to something bool fpga_clock_initialized = false; try{ - if (_iface->mb_eeprom.has_key("master_clock_rate")){ + if (not _iface->mb_eeprom["mcr"].empty()){ std::cout << "Read FPGA clock rate from EEPROM setting." << std::endl; - const double master_clock_rate = boost::lexical_cast(_iface->mb_eeprom["master_clock_rate"]); + const double master_clock_rate = boost::lexical_cast(_iface->mb_eeprom["mcr"]); std::cout << 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; -- cgit v1.2.3