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<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")”

改动后的运行结果:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 22:38:14

GPIO的相关文章

linux 标准 GPIO 操作

Linux 提供了GPIO 操作的 API,具体初始化及注册函数在 driver/gpio/lib_gpio.c 中实现. #include int gpio_request(unsigned gpio, const char *label); 获得并占有 GPIO port 的使用权,由参数 gpio 指定具体 port.非空的label指针有助于诊断.主要告诉内核这块地址被占用了.当其他地方调用同一地址的gpio_request就会报告错误,该地址已经被申请.在/proc/mem有地址占用表

Linux中的gpio口使用方法

Linux中的IO使用方法 应该是新版本内核才有的方法.请参考:./Documentation/gpio.txt文件 提供的API:驱动需要包含 #include <linux/gpio.h> 判断一个IO是否合法:int gpio_is_valid(int number); 设置GPIO的方向,如果是输出同时设置电平:/* set as input or output, returning 0 or negative errno */int gpio_direction_input(unsi

gpio操作(LS1B)

1.一般gpio_request 封装了mem_request(),起保护作用,最后要调用mem_free之类的,主要是告诉内核这个地址被占用了.当其他地方调用同一地址gpio_request就会报告错误,改地址已被申请.在/proc/mem 可以看到有地址占用表描述. 这种用法的保护前提是大家都遵守先申请在访问,有一个地方没有遵守这个规则,这功能就失效了,就好比进程互斥,必须大家在访问临界资源的时候都先获取锁一样,其中一个没有遵守约定,代码报废: 2.__gpio_set_value 和 gp

Am335x 下GPIO控制实例-驱动程序(转)

看了这么多的资料,现在决定上手了,下面将用两种方式来实现对GPIO 117的控制1,用直接添加到内核的方式,实现MISC的驱动(misc_register)2,用手工安装的方式,实现简单字符设备驱动(register_chrdev) 实现前提:当前所用的GPIO没有被其它设备所使用,大家可以用我前面BLOG说的方式查看GPIO的使用情况,当前我所用的GPIO本来是bluetooth的开关,需要屏蔽一个函数.不然后面的驱动申请IO都会失败.函数为Board-am335xevm.c 中的wl12xx

【转载】stm32的GPIO八种工作模式

一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定.         推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小.效率高.输出既可以向负载灌电流,也可以从负载抽取电流.推拉式输出级既提高电路的负载能力,又提高开关速度. 二.开漏输出:输出端相当于三极管的集电极,要得

【转载】GPIO模拟i2c通信

I2C总线的通信过程(见图4-8)主要包含三个主要阶段:起始阶段.数据传输阶段和终止阶段. 1. 起始阶段 在I2C总线不工作的情况下,SDA(数据线)和SCL(时钟线)上的信号均为高电平.如果此时主机需要发起新的通信请求,那么需要首先通过SDA和SCL发出起始标志.当SCL为高电平时,SDA电平从高变低,这一变化表示完成了通信的起始条件. 在起始条件和数据通信之间,通常会有延时要求,具体的指标会在设备厂商的规格说明书中给出. 2. 数据传输阶段 I2C总线的数据通信是以字节(8位)作为基本单位

gpio配置操作

1 pinmap_cfg.cpm_func 这个数组里是配置GPIO默认状态和功能  {PIN_KEYIN0_REG,            (PIN_SLP_IE|PIN_SPU_EN|PIN_FUNC_0|PIN_FPU_EN|PIN_BSR_WPX|PIN_DS_0|PIN_DSLP_EN)},//KEYIN0PIN_KEYIN0_REG  ID指向CPU芯片寄存器PIN_SLP_IE  在睡眠的时设置为使能输入 使能的值需要找硬件问...PIN_SPU_EN   在睡眠时使能上拉....

STM32 常用GPIO操作函数记录

STM32读具体GPIOx的某一位是1还是0 1 /** 2 * @brief Reads the specified input port pin. 3 * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. 4 * @param GPIO_Pin: specifies the port bit to read. 5 * This parameter can be GPIO_Pin_x where x can b

树莓派文档翻译 - 使用 - GPIO: 树莓派A和B

https://www.raspberrypi.org/documentation/usage/gpio/README.md 2016/6/25 GPIO: 树莓派A和B ##介绍GPIO和在树莓派上进行物理编程 树莓派的强大特性就是那一排在板子周围的GPIO(一般目的的输入输出)插针,就在黄色的视频输出插孔的旁边. GPIO pins 这些pin是pi和外界世界的物理接口.最简单,你可以把他们当作可以打开和关闭的开关(输入)或者树莓派可以打开或者关闭(输出).26个插针的17个是GPIO插针,

Linux应用层直接操作GPIO

Linux应用层直接操作GPIO 在一个老手的指导下,应用层可以直接操作GPIO,具体指设置GPIO的输入输出以及输出电平高或者低.这个大大地提高了灵活性,官方的文档有GPIO Sysfs Interface for Userspace,GPIO Sysfs. 这里我记录一下使用过例子: # RK30_PIN0_PD4 # A0-7 -> 0-7 / B0-7 -> 8-15 / C0-7 -> 16-23 / D0-7 -> 24-31 echo 28 > /sys/cla