GPIO

最新版的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(mb_root(mboard) / "gpio" / bank / attr).get();
            const boost::uint32_t new_value = (current & ~mask) | (value & mask);
            _tree->access(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(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(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(rx_fe_path / "dc_offset" / "enable").set(false);


        //create the properties and register subscribers
        _tree->create(mb_path / "dboards/A/rx_eeprom")
            .set(rx_db_eeprom)
            .subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "rx", _1));
        _tree->create(mb_path / "dboards/A/tx_eeprom")
            .set(tx_db_eeprom)
            .subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "tx", _1));
        _tree->create(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(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(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(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(mb_root(mboard) / "dboards"/"A"/"iface")”

编译安装后运行其中的例子 ./gpio --bank TXRX,这时候就可以测试通过了。

你可能感兴趣的:(GPIO)