要在Cubieboard2上开发四轴飞行器的控制模块,需要编写远程控制的接收端和底层控制模块。换言之需要编写用户层client软件和driver,本人负责单片机模块,此文是跟踪笔记,权当参考和提醒。值得声明的是,由于嵌入式平台的平台相关性很大,相关操作不一定可以完全再现。

学习资料主要参考论坛

———————2013年12月23号14点先记———————

需要什么:

  1. 一个合适的Linux发行版
  2. Java运行环境以完成网络通信。Java主要搭构client端的程序框架。安装上jdk最佳。
  3. Timer驱动完成飞行器控制。Cubieboard2应有较好性能运行arm-linux-gcc,可以尝试安装。
  4. JNI黏合,琐碎

关键点(只是开发思路和前期准备):

  1. Cubieboard2有原生的安卓4.2OS,但常年类月的安卓使用经验告诉我这个操作系统或许不能满足实时性要求,因此要更换成传统的Linux。而其中以原生搭载CPU负担最小的模块为最佳。然而需要编写驱动,因此需要有相应的内核代码和编译链。如果该发行版没有明确给出工具,第三点需求就会死绝。

    浏览下来,初步决定采用Cubian,如开发过程不顺利,有可能改变环境,日志会后续跟进
  2. 当前PC运行环境如下:
    hu@forhu-debian:~$ uname -a
    Linux forhu-debian 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 GNU/Linux
    
    hu@forhu-debian:~$ java -version
    java version "1.7.0_25"
    OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1~deb7u1)
    OpenJDK Client VM (build 23.7-b01, mixed mode, sharing)
    
    hu@forhu-debian:~$ ~/jdk1.7.0_45/bin/java -version
    java version "1.7.0_45"
    Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
    Java HotSpot(TM) Client VM (build 24.45-b08, mixed mode)
    

    当前我有两个jdk环境,这是为了测试java运行的有效性,我原来安装的OpenJDK6,实际使用时出现了一些问题,展示如下:

    hu@forhu-debian:~$ java -version
    java version "1.6.0_27"
    OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1~deb7u1)
    OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)  

    测试例程是简单的hello world程序,不赘贴出。.java文件的编译和运行操作有:

    hu@forhu-debian:~$ vi hw.java
    hu@forhu-debian:~$ ~/jdk1.7.0_45/bin/javac hw.java
    hu@forhu-debian:~$ java hw
    Exception in thread "main" java.lang.UnsupportedClassVersionError: hw : Unsupported major.minor version 51.0at java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:634)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:277)at java.net.URLClassLoader.access$000(URLClassLoader.java:73)at java.net.URLClassLoader$1.run(URLClassLoader.java:212)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:205)at java.lang.ClassLoader.loadClass(ClassLoader.java:321)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
    Could not find the main class: hw. Program will exit.

    也就是说,我用JDK7编译出来的.class程序并不能被OpenJDK6的jre运行,这比较头疼。我用Java的初衷在于消除嵌入式平台的平台相关性,JVM应该可以达成这个目标,以使得我在Windows下完成开发的无本地代码都能够正常运行。显然我现在安装的jre是不能满足要求的。因此卸载了OpenJDK6,换用OpenJDK7,运行后证实是可以的:

    hu@forhu-debian:~$ java -version
    java version "1.7.0_25"
    OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1~deb7u1)
    OpenJDK Client VM (build 23.7-b01, mixed mode, sharing)
    hu@forhu-debian:~$ java hw
    hello world!

    由于OpenJDK7是有源码的,我只要下载下来,并且编译一遍即可,这一块估计问题不大。

  3. 驱动的编写需要的环境由两个模块构建:内核代码及其.o文件和gcc。这里Cubian都有给出相关链接:内核 和编译链 。 这里的编译链应该是x86的,我的目标是在Cubieboard2上构建arm对arm的编译链,这个难度应该不高,取决于gcc和glib的版本。只要知道这两点都可以解决。但是最坏情况至少得构建在PC上的交叉编译链,否则驱动无从写起。这应该是构建完OS以后实验的第一要项。
  4. JNI的环境构建完全可以取决于上面环境的成果,相当琐碎。在最理想的情况下,可以完全通过Cubieboard2进行开发而不需要PC的介入。

——————今日追加——————

惊觉oracle已经推出了armv6/v7下的JDK,可以省去第二项时间开销,下载

———————2013年12月24号11点日记———————

TF卡启动刷进了两个操作系统,分别是Cubian和Lubuntu(因为我只有两张空闲的TF卡)。由于Lubuntu的镜像太大(3.xG呵呵),因此还是优先选择使用Cubian。

下一步是配置无线连接。这在上面没有提到,但是对工具的下载和板子的调试都是绕不过去的。

我用的无线网卡是Mercury 150US,用wext驱动即可。先查询无线信号:

cubie@Cubian:~$ iwlist wlan0 scan

扫描无线信号。这时候会列出很多搜索到的信号,如果没有搜到信号,那么这应该是OS里面没有驱动。要不就去找一个匹配的驱动,要不就换一张无线网卡。这里先记下目标信号的相关信息,尤其是pairwise、group之类的,可通过重导向至文件避免重复输入命令。然后通过设置/etc/wpa_supplicant.conf 来连接上wifi。这一步前先知道psk:

wpa_passphrase essid password >> /etc/wpa_supplicant.conf

然后再按照 教程 所述修改即可。

下面是安装JDK的过程。如上所述,采用的是JDK1.7。经实验用hf的包以加速。建立在前人成功的基础上,用的这个包。

步骤大致如下:下载->拷贝->解压->移动至/usr/java->设定环境变量->建立符号链接

即完成了JDK的建立。

值得提醒的是,为了鉴定JDK能不能在板子上运行,可以首先在解压后打开相应的jdk文件夹下的bin,并运行:

./java -version

看看会不会打印出相关信息。如果没有,那就基本可以给这个包判死刑了。

环境建立以后的结果:

cubie@Cubian:~$ java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b40)
Java HotSpot(TM) Client VM (build 24.0-b55, mixed mode)

下面是测试运行环境,比较琐碎,不做赘述

———————2013年12月25号14点日记———————

今天安装交叉编译链和建立跨平台环境,工作环境是Debian。昨天晚上下载完 gcc和 内核,今天直接上。这里值得提醒的是,要注意两个东西的版本号是否匹配。在安装完Cubian(或者其他Linux发行版)后,如不确定,可以查看dmesg的打印信息。输出的信息比较长,但是对体系结构的了解帮助很大,如果有时间可以稍作浏览。我这里需要的信息摘取如下:

[    0.000000] Linux version 3.4.67+ (root@ubtu) (gcc version 4.8.2 20130603 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.06 - Linaro GCC 2013.06) ) #4 SMP PREEMPT Wed Nov 6 08:31:09 CST 2013

上面显示内核版本是3.4.67而gcc版本是4.8.2 20130603,因此我上面给出的两个链接对于我现在所用的版本的Cubian是匹配的。对于嵌入式开发的新手容易忽略这个问题导致出现一些无法理解的错误,导致系统崩溃,这里先提醒一下,免做无用功。

在下载完gcc以后,注意到的一点是它的前缀很奇怪:arm-linux-gnueabihf-,arm-linux-gnu为止都应该知道是什么意思,后几个缩写是指代什么呢?下面稍作回答:

eabi是embedded application binary interface的意思,也就是嵌入式系统的ABI,和PC平台的ABI相似

而hf是ARM的一种体系结构。这个在构建JDK的时候就应该碰到过。简单来说,ARM的CPU分成两种,一种是带FPU的,一种没有。在没有FPU的体系结构下,浮点数运算是依靠函数来完成的,因此对于armhf或armel的库来说,这种体系结构下搞的事都是错的。

带FPU的又分成两种,armel和armhf,分别用两种方式来完成硬件浮点数运算。armel是ARM EABI Little-endian的意思。它通过CPU的寄存器(整型的)来完成参数传递。而armhf则是通过FPU的寄存器来完成的。因此这两种包仅针对浮点数的操作编译出来的机器码有所不同。因此我估计对于内核模块,这两个体系结构应在机器码级别上不做区分。

继续编译链的构建。解压完以后随便放哪儿,不过放在/usr下似乎更符合POSIX规范。然后再在.bashrc下更改环境变量,指向bin文件夹即可。然后下面就是花样hello world测试时间。不必上代码了。

然后要编写驱动的重要一步就是编译内核。按照文档设置应该不会出大问题。我的步骤如下:

hu@forhu-debian:~/sunxi-3.4$ cd sunxi-3.4/
hu@forhu-debian:~/sunxi-3.4$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sun7i_defconfig
hu@forhu-debian:~/sunxi-3.4$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
hu@forhu-debian:~/sunxi-3.4$ make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage modules

注意我的是cubieboard2,不同的板子具体设置不一样。相信编译过内核的人都大致读得懂,menuconfig是进入图形化配置界面,由于第二行已经有默认的配置选项生成,这里不过是进去瞄两眼,不是十分重要。第四行开始编译,但我这里的网络方面的模块好像编译失败。具体原因待查。今天先写到这里,明天继续。

———————2013年12月27号14点双日记———————

开发遇到了困境。首先是Java方面。原来在PC上调试好的代码现在不能使用。主要的原因是用的开源模块的JNI的动态链接库没法加载,具体原因不明,但是我自己编写的动态链接库测试出来是可以的。因此不知道这里出现问题的原因只能归结成开源包没有测试好。于是想从另外一个角度来解决,就是直接通过重新编译来解决这个问题。但是让我疑惑的地方就是这个开源包用到了一个依赖库,其用的版本比官网上放出来的版本还要新,因此想要重新编译也没有办法,最后只能再找其他方法来实现同样的功能。

更加严重的问题是我前天编译内核失败引起的。通过insmod等加载内核模块的时候,需要查询这个模块的版本号,而这个版本号是在编译的时候通过读取内核源代码目录下的Module.symvers加进去的。而由于我内核编译失败,所以这个文件也没有生成,导致我一个很简单的内核模块也没办法加载进去。另外,现在最新的《Linux设备驱动程序》上讲的知识都是针对2.6.x版本的内核,不知道3.4版本的会不会引入差异,这一点相当值得关注。

因此,要成功运行到内核模块,必须先成功编译完内核(关键的一步是make modules的一步)。逛了一天的论坛,总结下来导致内核编译失败的原因大致就是:由于github只提供zip包,而zip包是没法处理符号链接的,因此解压下来的文件是错误的,在编译的时候会显示无法找到文件。因此,针对这个问题,解决方案也有几个,各有优缺点:

  1. git clone -b /dev/sunxi-3.4 https://github.com/mmplayer/linux-sunxi.git ~/dst 来从github上下载完整的包,这个最稳健,但是国情原因这个速度太慢。
  2. 重新为zip打补丁,并编译点击打开链接
  3. 依然是zip包,但是通过7z解压,这一步最简单,我此时正在尝试

我采用的是7z解压方式,但是在解压过程中竟然报文件重复了。我想没有比这个更加蛋疼的事。我的方针是先到先得,天晓得能不能覆盖。现在编译的过程中好像还没有error(呃...),但是有很多warnings(呃呃......,代码是有多不严谨,我还看到数组越界了艹艹艹艹艹),因此我现在处于心惊肉跳的阶段,要是这个都不成功,那只能通宵开机git clone了。

假设内核编译成功,那驱动该怎么写呢?最好的方法当然是找到范例照着写,由于源码就在手上,这个并不困难。但由于要用到硬件资源,我们必须先弄懂我们要用的资源有没有和操作系统占用的冲突,然后再编写相应的驱动模块。因此,我们得先知道对应的寄存器的值,再比对器件手册查看相应的比特位来确定用那个寄存器组。

现在的进度卡在了内核编译上,是死是活就看它了。

———————2013年12月31号15点连日记———————

已经好久没更新了。为什么不呢?只是因为实在做得太爽,抽不出时间来。今天趁着过年,好好地总结一下这几天做的工作,并给出细节步骤和建议。

首先是内核编译。因为和驱动相关,所以内核编译必须得通过。通过7z解压的方式是可以编译通过内核的。但是这里会迎来另外一个问题,就是编译完的内核的版本号和cubian的版本号存在差异:一个是3.4.67,一个是3.4.67+。对,没错,就是这个差异,这么蛋疼。这个细节很重要,我通过询问cubian的开发者得知,这个+号是因为代码通过git仓库clone到本地的时候,由于某个脚本来进行判断的。但是通过浏览器下载zip包又有其自在的优势(稍微快一些,下载的体积小,不容易断线),因此我这里还是建议大家采用浏览器下载的方式下载zip包内核然后通过7z解压。

那+号引起的版本不匹配导致的内核模块无法加载的问题怎么解决呢?这个好办,我们只要uname这个命令的返回结果到底是以什么文件为依据就可以了。这个文件是include/linux/vermagic.h。打开这个文件如下:

#include <generated/utsrelease.h>/* Simply sanity version stamp for modules. */
#ifdef CONFIG_SMP
#define MODULE_VERMAGIC_SMP "SMP "
#else
#define MODULE_VERMAGIC_SMP ""
#endif
...//omit following code

这里发现还include了另外一个文件。当我去找这个文件的时候发现没找到(应该是从来没编译过,或者make clean后就找不到)。从文件夹名字其实就知道这个文件夹里面的文件都是在编译的时候产生出来的。因此,我们要做的并不是去手动修改这个文件(因为会在一次新的编译启动的时候被覆盖掉),而是去修改内核编译的config文件。当然,有更好的方式就是menuconfig选项。只要在某个位置输入+号,编译时编号后面就会以用户定义字串的方式把+号增加上去。

General setup->Local version - append to kernel release

这里要提醒的是,如果是通过git来下载源码包,那么上述操作都是多余的。git下来的包原本就有+号,因而可以直接开始编译。

当内核编译通过以后,内核目录下就会生成Module.symvers文件,这个文件对内核模块的版本号提供至关重要,决定了模块是否能被成功加载。如果内核编译通过,并且注意到版本号问题,那么这个时候就可以开始动手写驱动。这里的驱动需要的是要产生一个PPM波(Pulse Position Modulation)。虽然Cubieboard2有PWM的驱动,但是由于没法(或者不知道)向里面注册中断处理程序,因此,无法满足时间要求,因而要自己编写特定的驱动程序。

这里编写驱动程序要分两步走:

  1. 要先确定哪些资源能用,哪些资源不能
  2. 确定下来后,寄存器怎么配置,驱动程序怎么写

其实第一步就是要读取寄存器,相当于要求编写一个特定的驱动程序了。当然,这个驱动程序并没有任何难点,只要iomap一下就可以了。我这里核心要用到timer中断,因此只需要看timer的基址后一段距离的寄存器状态,就可以根据这个状态来判断是不是已经被操作系统占用了。实际的运行结果如下:

root@Cubian:/home/cubie/kermod# insmod check_reg.ko
base addr: 0x1c20c00:
offset  value
0x0:    0x3
0x4:    0x0
0x8:    0x0
0xc:    0x0
0x10:   0x44
0x14:   0x3a98
0x18:   0x3a8d
0x1c:   0x0
0x20:   0x4
0x24:   0x3a980
0x28:   0x3720a
0x2c:   0x0
0x30:   0x4
0x34:   0x0
0x38:   0x0
0x3c:   0x0
0x40:   0x0
0x44:   0x0
0x48:   0x0
0x4c:   0x0
0x50:   0x4
0x54:   0x0
0x58:   0x0
0x5c:   0x0
0x60:   0x4
0x64:   0x0
0x68:   0x0
0x6c:   0x0
0x70:   0x0
0x74:   0x0
0x78:   0x0
0x7c:   0x0

和 用户手册结合,就可以知道寄存器的使用情况。

得知可用timer4资源。因此后面就是编写timer4相关的驱动程序。等我这个项目做完会发布相关源码,而且这个驱动程序也很简单,因此今天不再作赘述。

———————完结补记———————

临近考试周,所以我就断了两个星期备考,另加上这个东西都要做不完了,所以现在才来补上。

首先之前我已经确认内核模块和Java环境两点,因此下面的步骤就是上机连调。

上机以后发现,直接用Timer产生PPM波会有10+us的误差因而导致整个想法崩盘,最后使用的方式是MSP430+ARM GPIO控制的方式实现NAZA飞控控制。至于430程序怎么编写这点实在是琐碎,而且也不必要,任何一个简单的单片机都能胜任的工作,只是手头上有小体积的430并且熟悉,可以短时间完成开发,而GPIO的控制驱动就更加简单了,因此这一部分的开发就没什么难度。

然后就是用户层接口。就是简单的open,close和ioctl的wrapper罢了,不予赘述。

这个项目的难点,对于我来说其实就是前面的环境构建部分,由于我混底层还是有点经验了,因此后面的驱动、单片机开发基本就不会出现什么意料以外的事情,比较平淡地就过去了。最后上几张飞起来的图。

最后会有总结型的日志以报告形式给出,这篇日志还是略显繁琐。

Cubieboard2开发要点简记相关推荐

  1. 体感(Kinect)开发要点总结一

    体感(Kinect)开发要点总结一 Kinect有两类摄像头,近红外摄像头和普通的视频摄像头.视频摄像头提供了一般摄像头类似的彩色影像.       Kinect的彩色摄像头默认每秒产生30副Colo ...

  2. Contiki开发要点

    Contiki开发要点 一.Protothread变量定义 Adam Dunkels的论文中提到,基于Contiki的protothread开发时要特别注意变量的生存周期,分配在栈中的自动变量,随着函 ...

  3. [读书笔记] 《修炼之道:.NET 开发要点精讲》

    <修炼之道:.NET 开发要点精讲> 目录 <修炼之道:.NET 开发要点精讲> 第 1 章 另辟蹊径:解读.NET 1.7 本章思考 > 位置 465 第 2 章 高屋 ...

  4. 一对一直播交友APP的核心开发要点,小而美的APP出路吗?

    一对一直播APP从大众化的直播行业走出了自己的特色,小众化的一对一直播交友APP不断地优化,满足了市场小部分人的需求,小众化的产品并非没有市场,现在正是"小而美"的大好时代,这也正 ...

  5. 一文看懂汽车电子ECU bootloader工作原理及开发要点

    随着半导体技术的不断进步(按照摩尔定律),MCU内部集成的逻辑功能外设越来越多,存储器也越来越大.消费者对于汽车节能(经济和法规对排放的要求)型.舒适性.互联性.安全性(功能安全和信息安全)的要求越来 ...

  6. 【UDS统一诊断服务】(补充)五、ECU bootloader开发要点详解 (1)

    文章目录 引言 1. bootloader的功能 2. 如何建立可靠的总线通信? 重要说明: 3. 解析编程文件(S19/HEX/BIN) 引言 bootloader的功能 如何建立可靠的总线通信? ...

  7. 【CSS】固定定位示例 ( 屏幕左右两侧广告栏 | 开发要点分析 | 代码示例 )

    文章目录 一.开发要点分析 二.代码示例 一.开发要点分析 实现下图样式 : 中间部分是网页内容 , 左右两侧是 固定广告栏 , 不管浏览器如何滚动 , 缩放 , 该左右两侧广告栏不变 ; 标签结构分 ...

  8. 金融信创快速落地的应用迁移或创新开发要点 | 一文读懂

    转载本文请注明出处:微信公众号EAWorld 近日,汇聚专家智慧.分解转型实战的<重塑>直播栏目再上新,本期聚焦金融信创,解析推进金融信创快速落地的应用迁移或创新开发要点. 访谈问题概览: ...

  9. 微信小程序实战开发要点-立哥技术

    -剑气纵横三万里,一剑光寒九百州 前言:小程序开发有自己独特的技术规范和开发要点,但是也不是完全和MVVM前后端开发模式完全不同,仅仅看官方文档并不能解决很多实际中的问题与难点.笔者就结合实际开发经验 ...

  10. 汽车电子ECU bootloader开发要点详解

    引言 1. bootloader的功能 2. 如何建立可靠的总线通信? 3. 解析编程文件(S19/HEX/BIN) 4. NVM驱动程序开发 5. bootloader开发的其他要点 a. boot ...

最新文章

  1. CRM User Status profile中Business Transaction字段的用途
  2. python编程课程上课有用吗-Python培训网络课堂|Python编程软件有哪些功能?
  3. 手机直播系统源码搭建说明
  4. NOj 720项目安排
  5. .net门槛是否真的很低?
  6. git@github.com:Permission denied(publickey).fatal: Could not read form remote repository错误
  7. Spring Boot 实现微信小程序订阅模板消息
  8. 玩转 SpringBoot 2 之整合 JWT 上篇
  9. Freemarker简单封装
  10. UVA10427 Naughty Sleepy Boys【数学】
  11. JS 在火狐浏览器下关闭弹窗
  12. 有没有测试直播源的软件,直播源检测验证管理工具(电脑直播源检测助手)V1.2 最新版...
  13. 西门子PLC的选型方法总结
  14. 天网防火墙去掉更新提示对话框
  15. 不同操作系统查询硬盘序列号的方法
  16. 爱心的数学函数方程_求心形函数表达式~~~
  17. 运动会加油稿计算机学院150字,学校运动会加油稿150字
  18. Pvr_UnitySDKAPI
  19. 名编辑电子杂志大师教程 | 如何删除电子画册中不要的页面?
  20. 泰拉服务器生存模式物品修改,荒岛求生修改存档生存物品方法

热门文章

  1. xxx(telnet, netstat): command not found
  2. 女神让我去修电脑,无数次戳中笑点
  3. Android 面试中高级上
  4. 设计模式——设计模式中英文对照
  5. iOS 福利局之开发加速库分享
  6. python网络爬虫-淘宝商品比价定向爬虫
  7. 淘宝打折骗局--尤其硬盘
  8. sox处理mp3_sox的常用方法
  9. springboot点餐微信小程序系统毕业设计源码221144
  10. 带托管代码的infopath2007表单创建, 发布,应用(MOSS开发)