aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp2/usrp2_iface.cpp
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-05-01 15:42:32 -0700
committerJosh Blum <josh@joshknows.com>2011-05-01 15:42:32 -0700
commite75919bc9e1cb1b5f8f69b5a5aabed9b3a1a53d9 (patch)
tree861b82a27b20e715aa81138baf26f4acd54f9895 /host/lib/usrp/usrp2/usrp2_iface.cpp
parent11e856ebca352af1b0444aec6d57ea61c0b48037 (diff)
downloaduhd-e75919bc9e1cb1b5f8f69b5a5aabed9b3a1a53d9.tar.gz
uhd-e75919bc9e1cb1b5f8f69b5a5aabed9b3a1a53d9.tar.bz2
uhd-e75919bc9e1cb1b5f8f69b5a5aabed9b3a1a53d9.zip
usrp2: added the concept of device locking to usrp2/nseries devices
Each iface instance can lock itself to a particular device. When the device is locked, it cannot be discovered through find. Locking works by having a lock thread periodically update a register in the firmware that says when the device was last locked. The find routine can determine if a device is locked by checking the difference between the current time and this register.
Diffstat (limited to 'host/lib/usrp/usrp2/usrp2_iface.cpp')
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp97
1 files changed, 66 insertions, 31 deletions
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;
};
/***********************************************************************