diff options
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 97 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_regs.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_regs.hpp | 2 |
6 files changed, 82 insertions, 36 deletions
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ae098dba6..7705037dd 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -80,6 +80,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num)); } + //lock the device/motherboard to this process + _iface->lock_device(true); + //construct transports for dsp and async errors std::cout << "Making transport for DSP0..." << std::endl; device.dsp_xports.push_back(udp_zero_copy::make( diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 87a878b10..4bcc61444 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -26,7 +26,10 @@ #include <boost/assign/list_of.hpp> #include <boost/format.hpp> #include <boost/tokenizer.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> #include <algorithm> +#include <iostream> using namespace uhd; using namespace uhd::usrp; @@ -41,6 +44,9 @@ static const boost::uint32_t MIN_PROTO_COMPAT_I2C = 7; static const boost::uint32_t MIN_PROTO_COMPAT_REG = USRP2_FW_COMPAT_NUM; static const boost::uint32_t MIN_PROTO_COMPAT_UART = 7; +// Map for virtual firmware regs (not very big so we can keep it here for now) +#define U2_FW_REG_LOCK_TIME 0 + class usrp2_iface_impl : public usrp2_iface{ public: /*********************************************************************** @@ -62,21 +68,50 @@ public: _protocol_compat = ntohl(ctrl_data.proto_ver); mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_N100); - switch(this->get_rev()){ - case USRP2_REV3: - case USRP2_REV4: - regs = usrp2_get_regs(false); - break; - - case USRP_N200: - case USRP_N210: - regs = usrp2_get_regs(true); - break; - - case USRP_NXXX: //fallthough case is old register map (USRP2) - regs = usrp2_get_regs(false); - break; + regs = usrp2_get_regs(); //reg map identical across all boards + } + + ~usrp2_iface_impl(void){ + this->lock_device(false); + } + +/*********************************************************************** + * Device locking + **********************************************************************/ + + void lock_device(bool lock){ + if (lock){ + boost::barrier spawn_barrier(2); + _lock_thread_group.create_thread(boost::bind(&usrp2_iface_impl::lock_loop, this, boost::ref(spawn_barrier))); + spawn_barrier.wait(); } + else{ + _lock_thread_group.interrupt_all(); + _lock_thread_group.join_all(); + } + } + + bool is_device_locked(void){ + boost::uint32_t lock_secs = this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_LOCK_TIME); + boost::uint32_t curr_secs = this->peek32(this->regs.time64_secs_rb_imm); + return (curr_secs - lock_secs < 3); //if the difference is larger, assume not locked anymore + } + + void lock_loop(boost::barrier &spawn_barrier){ + spawn_barrier.wait(); + + try{ + while(true){ + //re-lock in loop + boost::uint32_t curr_secs = this->peek32(this->regs.time64_secs_rb_imm); + this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, curr_secs); + //sleep for a bit + boost::this_thread::sleep(boost::posix_time::milliseconds(1500)); + } + } catch(const boost::thread_interrupted &){} + + //unlock on exit + this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, 0); } /*********************************************************************** @@ -98,6 +133,21 @@ public: return this->get_reg<boost::uint16_t, USRP2_REG_ACTION_FPGA_PEEK16>(addr); } + template <class T, usrp2_reg_action_t action> + T get_reg(boost::uint32_t addr, T data = 0){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO); + out_data.data.reg_args.addr = htonl(addr); + out_data.data.reg_args.data = htonl(boost::uint32_t(data)); + out_data.data.reg_args.action = action; + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG); + UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE); + return T(ntohl(in_data.data.reg_args.data)); + } + /*********************************************************************** * SPI **********************************************************************/ @@ -302,23 +352,8 @@ private: boost::uint32_t _ctrl_seq_num; boost::uint32_t _protocol_compat; -/*********************************************************************** - * Private Templated Peek and Poke - **********************************************************************/ - template <class T, usrp2_reg_action_t action> - T get_reg(boost::uint32_t addr, T data = 0){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO); - out_data.data.reg_args.addr = htonl(addr); - out_data.data.reg_args.data = htonl(boost::uint32_t(data)); - out_data.data.reg_args.action = action; - - //send and recv - usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data, MIN_PROTO_COMPAT_REG); - UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE); - return T(ntohl(in_data.data.reg_args.data)); - } + //lock thread stuff + boost::thread_group _lock_thread_group; }; /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 08f3955f1..e4d1a166b 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -66,6 +66,12 @@ public: //! Get the canonical name for this device virtual const std::string get_cname(void) = 0; + //! Lock the device to this iface + virtual void lock_device(bool lock) = 0; + + //! Is this device locked? + virtual bool is_device_locked(void) = 0; + /*! * Register map selected from USRP2/USRP2+. */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 48443bba4..2d1f901d7 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -115,9 +115,11 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){ //Attempt to read the name from the EEPROM and perform filtering. //This operation can throw due to compatibility mismatch. try{ - mboard_eeprom_t mb_eeprom = usrp2_iface::make(udp_simple::make_connected( - new_addr["addr"], boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) - ))->mb_eeprom; + usrp2_iface::sptr iface = usrp2_iface::make(udp_simple::make_connected( + new_addr["addr"], BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) + )); + if (iface->is_device_locked()) continue; //ignore locked devices + mboard_eeprom_t mb_eeprom = iface->mb_eeprom; new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; } diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 57ae36857..240bc3bab 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -56,7 +56,7 @@ int sr_addr(int sr) { return SETTING_REGS_BASE + (4 * sr); } -usrp2_regs_t usrp2_get_regs(bool) { +usrp2_regs_t usrp2_get_regs(void) { usrp2_regs_t x; x.misc_ctrl_clock = sr_addr(0); x.misc_ctrl_serdes = sr_addr(1); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index b50f8b506..8390f065d 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -88,7 +88,7 @@ typedef struct { extern const usrp2_regs_t usrp2_regs; //the register definitions, set in usrp2_regs.cpp and usrp2p_regs.cpp -usrp2_regs_t usrp2_get_regs(bool); +usrp2_regs_t usrp2_get_regs(void); //////////////////////////////////////////////////// // Settings Bus, Slave #7, Not Byte Addressable! |