From ea982f5f0d4b138f230638624c5e17fa3902706d Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Sat, 10 Oct 2015 14:30:27 -0700 Subject: usrp3: Fixed issue where ATR Idle could clobber GPIO out - gpio_atr_3000 will not blindly use the mask when writing the ATR and GPIO OUT values. The mask will be ANDed with the value in the ATR Disable register --- host/lib/usrp/cores/gpio_atr_3000.cpp | 27 ++++++++++++++++++++------- host/lib/usrp/cores/gpio_atr_3000.hpp | 4 +--- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'host/lib/usrp/cores') diff --git a/host/lib/usrp/cores/gpio_atr_3000.cpp b/host/lib/usrp/cores/gpio_atr_3000.cpp index d5f73988d..7f48abc69 100644 --- a/host/lib/usrp/cores/gpio_atr_3000.cpp +++ b/host/lib/usrp/cores/gpio_atr_3000.cpp @@ -82,7 +82,7 @@ public: _ddr_reg.flush(); } - virtual void set_atr_reg(const gpio_atr_reg_t atr, const boost::uint32_t value, const boost::uint32_t mask) + virtual void set_atr_reg(const gpio_atr_reg_t atr, const boost::uint32_t value, const boost::uint32_t mask = MASK_SET_ALL) { //Set the value of the specified ATR register. For bits with ATR Disable set to 1, //the IDLE register will hold the output state @@ -96,10 +96,23 @@ public: case ATR_REG_FULL_DUPLEX: reg = &_atr_fdx_reg; break; default: reg = &_atr_idle_reg; break; } - reg->set_with_mask(value, mask); + //For protection we only write to bits that have the mode ATR by masking the user + //specified "mask" with ~atr_disable. + reg->set_with_mask(value, mask & (~_atr_disable_reg.get(masked_reg_t::REGISTER))); reg->flush(); } + virtual void set_gpio_out(const boost::uint32_t value, const boost::uint32_t mask = MASK_SET_ALL) { + //Set the value of the specified GPIO output register. + //This setting will only get applied to all bits in the "mask" that are 1. All other + //bits will retain their old value. + + //For protection we only write to bits that have the mode GPIO by masking the user + //specified "mask" with atr_disable. + _atr_idle_reg.set_with_mask(value, mask & _atr_disable_reg.get(masked_reg_t::REGISTER)); + _atr_idle_reg.flush(); + } + virtual boost::uint32_t read_gpio() { //Read the state of the GPIO pins @@ -128,23 +141,23 @@ public: break; case GPIO_OUT: //Only set bits that are driven statically - set_atr_reg(ATR_REG_IDLE, value, _atr_disable_reg.get(masked_reg_t::REGISTER)); + set_atr_reg(ATR_REG_IDLE, value); break; case GPIO_ATR_0X: //Only set bits that are driven by the ATR engine - set_atr_reg(ATR_REG_IDLE, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); + set_atr_reg(ATR_REG_IDLE, value); break; case GPIO_ATR_RX: //Only set bits that are driven by the ATR engine - set_atr_reg(ATR_REG_RX_ONLY, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); + set_atr_reg(ATR_REG_RX_ONLY, value); break; case GPIO_ATR_TX: //Only set bits that are driven by the ATR engine - set_atr_reg(ATR_REG_TX_ONLY, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); + set_atr_reg(ATR_REG_TX_ONLY, value); break; case GPIO_ATR_XX: //Only set bits that are driven by the ATR engine - set_atr_reg(ATR_REG_FULL_DUPLEX, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); + set_atr_reg(ATR_REG_FULL_DUPLEX, value); break; default: UHD_THROW_INVALID_CODE_PATH(); diff --git a/host/lib/usrp/cores/gpio_atr_3000.hpp b/host/lib/usrp/cores/gpio_atr_3000.hpp index 28ec360ca..b30cd3b85 100644 --- a/host/lib/usrp/cores/gpio_atr_3000.hpp +++ b/host/lib/usrp/cores/gpio_atr_3000.hpp @@ -86,9 +86,7 @@ public: * \param value the value to write * \param mask only writes to the bits where mask is non-zero */ - inline void set_gpio_out(const boost::uint32_t value, const boost::uint32_t mask = MASK_SET_ALL) { - set_atr_reg(ATR_REG_IDLE, value, mask); - } + virtual void set_gpio_out(const boost::uint32_t value, const boost::uint32_t mask = MASK_SET_ALL) = 0; /*! * Read the state of the GPIO pins -- cgit v1.2.3