最新版的uhd/host中提供了对GPIO操作的接口,在multi_usrp.cpp中如下定义:
void set_gpio_attr(const std::string &bank, const std::string &attr, const boost::uint32_t value, const boost::uint32_t mask, const size_t mboard)
{
if (_tree->exists(mb_root(mboard) / "gpio" / bank))
{
const boost::uint32_t current = _tree->access<boost::uint32_t>(mb_root(mboard) / "gpio" / bank / attr).get();
const boost::uint32_t new_value = (current & ~mask) | (value & mask);
_tree->access<boost::uint32_t>(mb_root(mboard) / "gpio" / bank / attr).set(new_value);
return;
}
if (bank.size() > 2 and bank[1] == 'X')
{
const std::string name = bank.substr(2);
const dboard_iface::unit_t unit = (bank[0] == 'R')? dboard_iface::UNIT_RX : dboard_iface::UNIT_TX;
dboard_iface::sptr iface = _tree->access<dboard_iface::sptr>(mb_root(mboard) / "dboards" / name / "iface").get();
if (attr == "CTRL") iface->set_pin_ctrl(unit, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "DDR") iface->set_gpio_ddr(unit, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "OUT") iface->set_gpio_out(unit, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "ATR_0X") iface->set_atr_reg(unit, dboard_iface::ATR_REG_IDLE, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "ATR_RX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_RX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "ATR_TX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_TX_ONLY, boost::uint16_t(value), boost::uint16_t(mask));
if (attr == "ATR_XX") iface->set_atr_reg(unit, dboard_iface::ATR_REG_FULL_DUPLEX, boost::uint16_t(value), boost::uint16_t(mask));
}
}
简单解释一下:
第一个if语句:如果在设备的属性树中存在路径“_tree->exists(mb_root(mboard) / "gpio" / bank”,则通过set()方法将新值写入到bank的attr寄存器中;
第二个if语句:如果所给的字符串bank多于两个字符并且第二个字符为‘X’(一般为TX或RX等),则通过上述的几个函数将值写入相应的寄存器中。
课题所选用的母板为N210,其属性树中不存在代码中的路径“ _tree->access<dboard_iface::sptr>(mb_root(mboard) / "dboards" / name / "iface")”,故直接使用时,set_gpio_attr()实际不进行任何操作,同理读寄存器时读出的结果全为0.
参考usrp2_impl.cpp中创建子板接口时的描述:
// create dboard control objects
//read the dboard eeprom to extract the dboard ids
dboard_eeprom_t rx_db_eeprom, tx_db_eeprom, gdb_eeprom;
rx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB);
tx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB);
gdb_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);
//disable rx dc offset if LFRX
if (rx_db_eeprom.id == 0x000f) _tree->access<bool>(rx_fe_path / "dc_offset" / "enable").set(false);
//create the properties and register subscribers
_tree->create<dboard_eeprom_t>(mb_path / "dboards/A/rx_eeprom")
.set(rx_db_eeprom)
.subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "rx", _1));
_tree->create<dboard_eeprom_t>(mb_path / "dboards/A/tx_eeprom")
.set(tx_db_eeprom)
.subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "tx", _1));
_tree->create<dboard_eeprom_t>(mb_path / "dboards/A/gdb_eeprom")
.set(gdb_eeprom)
.subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "gdb", _1));
//create a new dboard interface and manager
_mbc[mb].dboard_iface = make_usrp2_dboard_iface(_mbc[mb].wbiface, _mbc[mb].iface/*i2c*/, _mbc[mb].spiface, _mbc[mb].clock);
_tree->create<dboard_iface::sptr>(mb_path / "dboards/A/iface").set(_mbc[mb].dboard_iface);
_mbc[mb].dboard_manager = dboard_manager::make(
rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id,
_mbc[mb].dboard_iface, _tree->subtree(mb_path / "dboards/A")
);
//bind frontend corrections to the dboard freq props
const fs_path db_tx_fe_path = mb_path / "dboards" / "A" / "tx_frontends";
BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)){
_tree->access<double>(db_tx_fe_path / name / "freq" / "value")
.subscribe(boost::bind(&usrp2_impl::set_tx_fe_corrections, this, mb, _1));
}
const fs_path db_rx_fe_path = mb_path / "dboards" / "A" / "rx_frontends";
BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)){
_tree->access<double>(db_rx_fe_path / name / "freq" / "value")
.subscribe(boost::bind(&usrp2_impl::set_rx_fe_corrections, this, mb, _1));
}
若要使其适用于N210,做如下改动:
1、将bank.size() > 2改为bank.size() > =2
2、将路径改为“_tree->access<dboard_iface::sptr>(mb_root(mboard) / "dboards"/"A"/"iface")”
编译安装后运行其中的例子 ./gpio --bank TXRX,这时候就可以测试通过了。