8月 102014
 

bladeRF 维基上介绍了在 Linux 系统上搭建 bladeRF 环境的步骤,不过原文是英文的,另外其中一些具体选择不尽合理。本文以 Fedora 系统为示例,提供一个中文版的 bladeRF 环境搭建指南,并着重介绍和维基上的不同点。比较可能有一定的时效性,但一些原则应该足够通用。本文的比较基准是当前的维基版本

安装依赖

维基上建议安装 “Development Tools” “Development Libraries” 两个软件包组,但我们只需要其中的一部分软件包,其中有些可能已经安装过了,而像 cvs 等并不必须。如果你像我一样有“洁癖”,不希望安装不需要的软件包,那么可以用如下的命令安装必须的依赖(未严格验证,在我这里绝大多数包都在之前安装过了):

sudo yum install git doxygen gettext glibc-devel ncurses-devel readline-devel zlib-devel boost-devel
sudo yum install libusbx libusbx-devel cmake wget gcc-c++

注意其中是 libusbx 而非 libusb,后者是 0.x 系列的版本,而非 1.x 系列。Debian/Ubuntu 系的用户会注意到软件包命名上的差异 (devel 而非 dev)。

维基上推荐安装 libtecla,以增强 bladeRF-cli 交互模式的编辑功能。不过 Fedora 软件源里目前还没有这个包,所以需要手动下载,解压缩,使用经典的 ./configure; make; sudo make install 三部曲安装。

构建 bladeRF

在终端下进入打算用来放置 bladeRF 源码的目录,用 git 将 bladeRF 的源码库克隆下来:

cd /path/to/bladeRF/directory
git clone https://github.com/Nuand/bladeRF.git

切换到源码目录中的 host 目录,创建一个 build 目录用来存放构建过程的中间文件。这种使用单独的构建目录的方式称为树外构建 (out of tree build),相对于直接在源码目录构建,好处在于生成的中间文件不会分散在源码目录里,方便清理,另外可以用多个构建目录构建出互不干扰的不同参数下的版本。之后切换到构建目录,然后就是标准的 cmake ..; make; sudo make install 三部曲了。注意这里 cmake 时启用了 INSTALL_UDEV_RULES 宏,使得安装时把 udev 规则文件也安装到系统中。

cd bladeRF/host/
mkdir build
cd build
cmake -DINSTALL_UDEV_RULES=ON ../
make
sudo make install

很遗憾的是这里安装的 udev 规则文件使用了 plugdev 群组,不是 Fedora 下的标准做法。可以参考之前的博文修改 udev 规则文件。

为了让新安装的 bladeRF 库文件可以被二进制文件使用,我们需要用 ldconfig 刷新系统动态库的缓存。上面的构建过程会将 bladeRF 安装到 /usr/local 下,而其中的库文件目录 /usr/local/lib{,64} 不在 ldconfig 的默认搜索路径里。所以我们可以将它们添加到 /etc/ld.so.conf 里。添加之后文件内容如下:

/usr/local/lib
/usr/local/lib64
include ld.so.conf.d/*.conf

之后,用 sudo ldconfig 刷新缓存即可。可以用 ldd /usr/local/bin/bladeRF-cli 命令检查 bladeRF 库文件是否被找到。连上 bladeRF 设备,用 bladeRF-cli -p 命令看下是否能够发现设备。更多操作见于另一个维基页

构建 GNU Radio 与 gr-osmosdr

通过上述步骤,就可以操作 bladeRF 板卡了。但是,要想便捷地为 bladeRF 开发软件无线电应用,最好再构建一下 GNU Radio 和 gr-osmosdr。GNU Radio 是一个开源的软件无线电开发平台,提供众多的信号处理模块和简单易用的图形界面开发环境。gr-osmosdr 适配 GNU Radio,为众多硬件板卡(除了 bladeRF 之外还有 HackRF 等)提供一个统一的软件接口。

GNU Radio 依赖比较多,编译安装相对麻烦,一般推荐使用 build-gnuradio 脚本。但是因为其中涉及到从网络下载诸多软件以及编译安装,效率受网速和电脑硬件性能限制,耗时较长。另外,脚本的健壮性不高,所以很容易中途退出。这个脚本很长,但实际上是把整个构建过程划分为几个步骤,放在几个函数里先后执行的。我建议阅读这个 Shell 脚本,每次运行其中的一步或几步,必要时手动完成一些配置。对于新手,这会是一个很好的通过阅读代码学习 Shell 编程的机会。

具体的构建步骤可以在维基或这里找到,这里就不再赘述。只是提几点注意事项:

  • 如果你像我一样,除了 bladeRF 之外,还会使用 Ettus 公司的 USRP 系列设备,那么记得先构建 UHD,然后构建 GNU Radio。
  • build-gnuradio 脚本在 cmake 时,有时用了树外构建,但有时又没用。建议始终用树外构建。
  • 编译 GNU Radio 时,并行 make (make -j N 其中 N 大于 1)时有时会编译失败(竞态条件?),直接 make 就可以正常编译通过,虽然速度会慢很多。什么?make 也会出错?那考虑换一个 git 提交重新编译,并向上游报 BUG 吧。

构建成功 GNU Radio 后,构建 gr-osmosdr 就显得小菜一碟了,标准的 cmake 构建三部曲,项目不大,编译过程也能很快完成。

全部构建完成后,可以使用如下命令用 bladeRF 看一下频谱,检验是否大功告成。其中 FPGA 映像可以从 Nuand 网站下载。此外,最新固件也可以从官网下载。

osmocom_fft -a bladerf=0,fpga=<your FPGA image> -s 2000000 -f 446000000

致谢

本工作由星天科技赞助。

2月 032012
 

我的 connect6-ng 是在 connect6 的基础上进行的。原项目使用 SVN 做版本控制,但我更喜欢使用 Git。所以我在开始 connect6-ng 时先检出了 SVN 仓库里的最新版本然后取出其中源代码初始化了 Git 仓库,并没有继续 SVN 历史。

董渊老师建议我能把两段历史连接起来,以体现出项目的延续性。老师还帮忙使用 git-svn 在 Ubuntu 9.10 下将 connect6 项目的 SVN 历史转换到了 Git 仓库下:

mkdir connect6.git
cd connect6.git/
git-svn init http://connect6.googlecode.com/svn/ --no-metadata
git config svn.authorsfile ../authors.txt
git-svn fetch
git log
cd ..
tar -zcvf connect6.git.tgz connect6.git/

其中authors.txt的内容为:

qq280833822 = CHEN Shuang <qq280833822@gmail.com>
wanglei     = WANG Lei    <leopardguo25@gmail.com>

我收到 connect6.git.tgz 后在连接两段历史前,对前一段历史记录做了一些更改:使用 git filter-branch 删除了仓库里的 *.class 文件、/trunk/connect6.jar 文件,因为我觉得这些中间文件或目标文件放在仓库里意义不大。另外,我又将 trunk 目录做成了仓库的根目录,这和后面我的仓库更接近。处理后的仓库目录我命名为 connect6-shrinked/

参考 stackoverflow 中这个问题回答,我使用其中的第三种方法(refs/replace/) 将 SVN 仓库历史转换成的 git 历史添加在了 connect6-ng 提交历史的前面,连上了两段历史。不太详细的步骤如下:

切换到新项目 connect6-ng 的顶层目录,把 connect6-shrinked 加为一个远程仓库,命名为 history:

$ git remote add history file:///path/to/connect6-shrinked/

然后找出 connect6-ng 项目最初的提交(Initial commit)的 SHA1 值,保存到 $TAIL 变量中:

$ TAIL=$(git rev-list --topo-order master | tail -n 1)

接着找出要导入历史的旧项目的最近的一次提交,保存到 $TOP 变量中:

$ TOP=$(git rev-parse --verify history^0)

然后读取 $TAIL 这个 commit 对象的内容:

$ git cat-file commit $TAIL > TAIL_COMMIT

手工编辑 TAIL_COMMIT 这个文件,加入一行 parent $TOP(其中 $TOP 换成对应的 SHA-1 值),这使得新项目的初始提交有了旧项目的顶部作为父提交。将新的 TAIL_COMMIT 写入仓库:

$ NEW_TAIL=$(git hash-object -t commit -w TAIL_COMMIT)

最后使用 git replace

$ git replace $TAIL $NEW_TAIL

这样就连接好了两段历史记录,可以用 git log 等查看。

要把合并后的历史 push 出去,需要在自己仓库 .git/config 文件中对应 remote 部分加一行:

push = +refs/replace/*:refs/replace/*

在合并两段历史之前已经从 connect6-ng 远程仓库 clone 了代码仓库的同学,如果不做修改,还是只能看到较新的一段历史。要想看到旧的SVN导出的历史,需要修改自己的 .git/config 里 origin 部分(或者其他指向 connect6-ng 远程仓库的 remote 分支名)添加一行:

fetch = +refs/replace/*:refs/replace/*

这样之后 git fetchgit pull 就可以拉取 refs/replace/ 下的后来添加的历史了。

附注:本文参考了董渊老师和我的邮件、stackoverflow 上的回答等,一并感谢。