译者前言:
很久以来我都很期待Java能在嵌入式领域有所作为,之前的JavaME实在令我大失所望,不但被严重“阉割”,而且在硬件方面也没什么厂商支持。所以Java除了在图形界面设计(被人诟病的Swing)方面存在遗憾之外,在嵌入式领域也几乎被人遗忘。我不得不继续捧着Qt(一个跨平台的C++图形库)在嵌入式开发中漫无边际的狂奔。我不是对Qt存在偏见,我也非常的喜欢Qt,但是我更喜欢Java,它让我真心的陶醉其中。
终于让我期待已久的时刻到来了,在2012年的JavaOne大会上,Oracle展示了基于嵌入式Java SE开发的一个“玩具”——机械手臂。以此推出了2款嵌入式新产品:Java SE Embedded和Java ME Embedded。除此之外还有一款Java SE Embedded升级版——Java SE Embedded Suite。这个套件将Java SE Embedded,Glassfish,WebService等都集成在一起,用于更高性能的嵌入式设备。非常令人振奋的消息,顿时让我热血再次沸腾。毫不犹豫的到ICKey.cn(“树莓派”开发板的指定代理商)上化了500多元买了一套开发板回来(我KAO,35美元的廉价版到了中国竟变成了500多,我KAO),准备第一时间尝试一下嵌入式Java的乐趣。据外国媒体报道,英国一大学教授,用一块“树莓派”B型版加上一个砖头大小的信号发射器居然搞了一个功能完备的电信基站。可见这块开发板的强大,已经超出了原本发明它的初衷(原本只是为了教育小朋友学习编程的“玩具”)。
在Oracle的官方网站上看到了这篇Blog ,觉得对于嵌入式Java的入门非常的有帮助,特此翻译一下,方便其他的同学学习和参考。由于本人E文烂,凭借词霸和Google翻译,所以有错误之处还请谅解,翻译的主要目还是为了传播推广嵌入式Java技术。本次我自己的实验是开发一个家庭网络多媒体中心,类似机顶盒。顺便验证一下号称为嵌入式设备而生的OSGi是否真的有其存在的价值,后续我也会将自己的实验过程写成文章与大家分享。OK,前言到此结束,进入正文。
译文开始:
在不到一个小时之内,如何获取Linux并在“树莓派”上运行Java SE Embedded呢?
这是一块比信用卡还小,并且和一本Java编程书籍相同价格的东西。
这就是“树莓派(Raspberry Pi)”微型电脑,它可以为headless(所谓Headless是指不需要显示,键盘,鼠标等设备)嵌入式应用程序提供全功能的Java SE运行时支持。这篇文章可以让你了解在“树莓派”上使用Java编程的相关主题,它们包括:
- 什么是“树莓派”:关于“树莓派”的简要介绍
- 先决条件:介绍我们需要准备那些东西以及需要了解的预备知识
- 必要的Linux配置:如何安装和配置Debian Linux操作系统
- Java SE Embedded配置:如何的获取和安装嵌入式Java SE
- 可选的Linux优化和调整:如何让你的Linux运行的更好
注意:文章中提到的一些内容会存在潜在的变化,尤其是你在电脑主机(台式机或是笔记本)上的操作可能和你在“树莓派”上执行的操作会有所不同。请运用你的知识和偏好(一些主题可能会在“可选的Linux优化和调整”章节中提到)来创建一条符合自己需要的工作流程。
一. “树莓派”开发板:
“树莓派”是一块将700MHz ARMv6 CPU和图形处理器(GPU)整合在独立芯片中的小巧(和信用卡大小一般)而低功耗(只需要5V电源就能启动)的开发板。GPU和CPU共享256MB内存(总内存为512MB)。另外还可以连接一些外围设备,比如USB,以太网,HDMI,音频,SD卡,RCA视频和GPIO(译者注:目前还没有WIFI模块,但是板子上有2个USB接口,可以连接USB的无线网卡。近期还会有摄像头模块上市)。图一展示了一块“树莓派”B型的开发板并且插入了一张SD卡用于扩展。SD卡扮演着特殊的角色:“树莓派”的启动依赖SD卡。本文介绍的大部分内容就是为了指导您如何在一张可引导的SD卡上创建和修改文件。
(图一)“树莓派”B型开发板
你可以在“树莓派”上使用USB接口的键盘和鼠标并且还可以连接HDMI的显示器或电视机(可以达到1080P)。板子上的以太网提供了另外的可选项:通过SSH连接到其他网络中的主机并可与之通讯。在“可选的Linux优化和调整”章节中我们会讨论如何开启SSH登录。
二. 先决条件:
为了准备可以运行Java SE Embedded的“树莓派”B型开发板,你需要准备如下内容:
- 一个可以通过“树莓派”以太网口连接的有线网络。并且网络必须提供DHCP的动态IP地址获取服务。
- 一台装有 Linux的电脑并和“树莓派”连接在同一网路中。你也可以在Windows或是MAC主机上执行相同的操作,不过这些内容不会在本文中进行讨论。你必须要有主机的root登录权限。此外你还需要如下内容:
- 一个可以从网站下载文件的途径,例如WEB浏览器或是wget工具。
- 一个磁盘分区工具。这里我们使用的是 GParted,它是一款简单而又强大的磁盘分区工具。如果你还没有GParted,那么你可以通过在主机上执行如下操作来获取并安装它:
$ sudo apt-get install gparted
- 一个WEB浏览器和一个电子邮件客户端,用来从Oracle下载Java SE Embedded。
- 一张可读写的SD卡。如果你的Linux是建立在虚拟机上的,请确保它可以读写SD卡。
注意:不是所有的SD卡都能工作在“树莓派”上的。高速卡可以为“树莓派”总线提供更快的速度。我们已经成功的使用了创见4G Micro卡和爱国者4GB Class4卡。http://elinux.org/RPi_VerifiedPeripherals#SD_cards上为“树莓派”用户列出了可以使用的SD卡以及一些不能使用的SD卡。
- 一个5V的Micro USB电源适配器(译者注:电源适配器可以在ICKey.cn上买到,也可以使用手机充电器,甚至是碱性电池,只要能提供5V电压,至少700mA电流就行),用来提供至少700mA的电源。根据Raspberry Pi官网的介绍,不要使用USB Hub或是电脑作为供电源。
三. 必要的Linux配置:
当插上电源之后,“树莓派”就从SD卡开始启动固件。Java SE Embedded是运行在Linux上的,所以在此之前你首先需要获取Linux并将其放到SD卡上。
为“树莓派”下载Debian Squeeze Linux镜像
注意:这里所有的说明都是针对Debian Squeeze的。为“树莓派”实现的其他Linux可能也能工作,但是它们必须都是基于ARM SFP芯片构建的。在Raspberry Pi官网上可能还有其它一些基于硬件浮点运算构建的Linux镜像文件的链接,但是Java SE Embedded并不能运行在这些 Linux上。
你可以在http://elinux.org/RPi_Distributions#Debian_ARM上找到ZIP格式的Debian Squeeze镜像文件。文件的大小大概在450MB左右。下面的内容假定你已经下载了镜像文件并将其放入一个新目录中,例如:~/RaspberryPi/。为了验证下载的文件是否正确,你可以查看在开始下载页面上显示的SHA-1 Checksum说明。
用以下命令解压缩镜像文件:
$ cd ~/RaspberryPi
$ unzip *.zip
解压缩之后将创建一个子目录,看上去像这样:debian6-19-04-2012。
复制Debian Squeeze Linux镜像到SD卡上
要让你的计算机识别SD卡设备句柄需要如下步骤(如果你喜欢也可以使用其他的方法):
- 在一个Linux的终端窗口中,执行demsg|tail 命令,它会显示一些与设备加载有关的信息。只有最后的几行信息是我们感兴趣的。
- 将SD卡插入到读卡器中。
- 过一段时间之后,在终端窗口中再次执行demsg | tail命令,在额外的行(相对第一个窗口而言)中会显示出新加载的SD卡。它们可能在细节上会有所不同,但看上去应该是这个样子的:
[ 110.084625] sdb: detected capacity change from 0 to 3963617280
[ 118.055249] sd 2:0:0:0: [sdb] 7741440 512-byte logical blocks: (3.96 GB/3.69 GiB)
[ 118.059409] sd 2:0:0:0: [sdb] Assuming drive cache: write through
[ 118.064547] sd 2:0:0:0: [sdb] Assuming drive cache: write through
[ 118.066015] sdb: sdb1
其中,sdb表示设备的句柄是/dev/sdb。sdb1是指本例中的一个SD卡的单独分区,你的SD卡可能会有多个分区。
在接下来的说明中,我们假定SD卡设备的句柄是/dev/sdb 并且只有一个单独的分区:sdb1。如果你的环境有需要可以调整说明。
- 卸载SD卡的分区:
$ sudo umount /dev/sdb1
- 使用dd命令将Debian镜像复制到SD卡上。
注意:在接下来的命令中,请确认输入的of(输出文件)参数值是正确的,因为你即将调用底层的磁盘复制来覆写所有的数据,所以错误的设备指定将损坏所有的数据。
$ cd ~/RaspberryPi/debian6-19-04-2012
$ sudo dd if=yourDebian.img of=/dev/sdb bs=1M
1859+1 records in
1859+1 records out
1950000000 bytes (2.0 GB) copied, 212.344 s, 9.2MB/s
用dd将文件输出到SD卡是非常缓慢的操作。一张4GB Class4的卡要花费5到10分钟的时间。dd没有提供进度提示,所以要耐心的等待它慢慢的完成工作。
如果你想知道SD卡如何在linux下工作,可以先跳到“第一次启动”章节,然后再回过头来看“调整SD卡分区大小”章节。
调整SD卡分区的大小
现在SD卡包含了三个分区和一个未分配空间。现在我们将未分配空间加入到Linux文件系统中,让Java SE Embedded和应用程序可以使用更多的空间。为了分配未分配空间到文件系统中,我们需要在SD卡上修改分区——删除并重新创建一个分区,并调整另外一个分区的大小。
- 启动GParted:
$ sudo gparted
GParted初始化显示主机磁盘的所有分区。你不会想去更改这些分区。
- 选择GParted -> Devices,显示出/dev/sdb上的所有分区以及未分配空间:
(图二)初始化的SD卡分区
这里有三个分区:
/dev/sdb1:启动分区。
/dev/sdb2:Linux根文件系统,已经使用了1.5G的空间。
/dev/sdb3:Linux的交换空间(swap area)。
大概有一半的SD卡空间未被分配。有一块很大的free空间跟在/dev/sdb3分区之后。为了将free空间追加到/dev/sdb2上(文件系统),我们将暂时的删除/dev/sdb3,然后扩展/dev/sdb2,最后再重新创建/dev/sdb3分区。
在分区列中,选择/dev/sdb3(linux-swap),右击鼠标并选择删除。虽然分区会被显示成已删除,但是GParted会将此操作放入队列中,稍后才会真正的执行它。
(图三)SD卡删除分区命令放入队列中
在分区列中,选择/dev/sdb2,这是一个Linux文件系统,右击鼠标,选择Resize/Move。会弹出一个对话框,拖拽右边的箭头直到“Free space following”为大约512左右(或是你想要为swap空间留出的空间大小)。你并不需要拖拽到512那么精确,因为这个精确的大小并不重要。
(图四)512MB的SWAP空间
单击Resize/Move将其放入执行队列中,在弹出的“Movinga partition”警告对话框中点击OK。
现在我们已经调整了文件系统分区的大小,接下来我们将重建一个swap分区。选择512MB的未分配空间,右击鼠标并选择New。
在Create new Partition对话框中,选择“File system”下拉框中的“linux-swap”。
(图五)新建 Swap分区
点击Add。
在GParted主界面上,选择Edit -> Apply All操作。GParted将执行所有我们之前放入队列中的操作。在“Are you sure”对话框中点击Apply。重新分区是一个需要轻松运行几分钟的漫长操作,对话框中会显示进度。当它完成后点击Close。
(图六)新的分区映射
退出GParted并弹出SD卡,接着你就可以尝试你的第一次启动了。
第一次启动
注意:为了以下这些步骤,你必须已经有一些设备并将其连接到“树莓派”上:一个显示器,一个键盘,和一个可工作的以太网。
断开“树莓派”的电源,插入Linux SD卡到插槽中,然后再次连接电源。几秒钟之后,启动进程的消息将显示在显示器上。如果不是这样的话,那可能是SD卡的类型错误或是格式不正确。
如果在整个第一次启动中出现一般的错误消息,那是因为我们的一些服务还未被配置所致。第一次的启动也有可能因为等待端口映射的关闭而出现挂起。作为一个控制台消息指示,你可以让它继续运行也可以断开“树莓派”的电源并重新启动它。随后的启动会相对较快。
当你看到登录提示符之后,输入用户名和密码登录“树莓派”。在写这篇文章的时候,默认的用户名和密码分别是:“pi”和“raspberry”。
注意:不兼容的键盘会阻碍登录,例如,会产生重复的字符。如果你不能登录,请尝试使用另一个键盘。如果“pi”和“raspberry”不能工作,请咨询Linux发布的网站。
如下方法可以获取并写入“树莓派”的IP地址:
$ sudo /etc/rc.local
RaspberryIP
允许ssh登录请使用以下命令:
$ sudo update-rc.d –f ssh defaults 20
重启并使ssh登录生效:
$ sudo sync; sudo shutdown –r now
如果shutdown花费了太长的时间,你可以直接断开电源然后重新连接电源。
现在我们可以从主机上通过网络来读写“树莓派”上的SD卡了。
四. Java SE Embedded配置:
在这个章节中,我们将使用主机来下载Java SE Embedded并将其通过网络复制到“树莓派”上的Linux文件系统中。接着,我们将仍旧通过远程的方式解压缩下载的文件并运行Java。
获取Java SE Embedded软件
在主机上的WEB浏览器中访问http://www.oracle.com/technetwork/java/embedded/downloads/javase/index.html,Web页面的细节可能会和撰写本文时所有不同。
(图七)第一个下载连接
在Java SE Embedded 7一栏,点击EABI, VFP,SoftFB ABI, Little Endian。会出现一个调查页面。
完成调查并点击提交,一个验证页面会出现。
检查验证页面的正确性(尤其是你的email地址),然后点击提交。过一段时间,一封JavaSE-Embedded-LinkNotify的电子邮件会出现在你的收件箱中。
点击电子邮件中的连接,会出现另外一个下载页面(一些细节可能会与本文中的内容有所不同)。
(图八)第二个下载连接
选择“Accept License Agreement”,然后点击“ARMv6/7 Linux - Headless”连接。
注意:在撰写本文时,ARMv7 Linux – Headful还没有在“树莓派”上进行测试。ARMv7Linux - Headless - Server Compiler不能运行在“树莓派”上,因为该软件需要ARMv7的芯片。
保存.gz文件到你的downloads目录。
通过网络并使用pi用户登录到“树莓派”,并为Java下载文件创建一个目录:
$ ssh pi@RaspberryIP mkdir /home/pi/java
复制Java下载文件到“树莓派”的新目录中:
$ scp ~/Downloads/*.gz pi@ RaspberryIP:/home/pi/java
解压缩Java下载文件:
$ ssh pi@ RaspberryIP
$ cd /home/pi/java
$ tar –zxvf *.gz
运行Java:
$ ls ejre*
ejre1.7.0_04
$ cd ejre*
$ ./bin/java –version
java version "1.7.0_04-ea"
Java(TM) SE Runtime Environment for Embedded (build 1.7.0_04-ea-b20, headless)
Java Hotspot(TM) Embedded Client VM (build 23.0-b21, mixed mode)
一些细节,例如版本和创建号等,可能会与文本中的内容有所不同。
可选的,删除下载文件:
$ rm /home/pi/java/*.gz
五. 可选的Linux优化和调整:
本章节中的一些命令可以使你的“树莓派”系统运行的更可靠,响应更快,使用更方便。选择那些你喜欢的并在“树莓派”上运行它们。为了简化问题的诊断,在你做的每一次变更之后都重启系统。
本章节中:
- 设置静态IP地址
- 启用交换和优化文件系统的访问时间
- 设置时区和区域
- 设置时间服务
- 设置Internet代理
- 重新映射键盘
- 自动启动图形用户界面
- 添加不同的Web浏览器
- 开启音频
设置静态IP地址:
如果你的网络要重复利用动态的IP地址,你就可以跳过变更成静态IP地址,因为“树莓派”的IP地址将长期的有效。由于“树莓派”在每一次启动之后动态IP地址都可能不一样,所以一个静态的IP地址对于使用ssh来说就变得非常的方便了。在接下来的说明中,我们假设你想获取主机名为raspberrypi的“树莓派”。
首先用超级用户在一个文本编辑器中打开/ect/hosts文件(例如:sudo vi /etc/hosts)。为“树莓派”加入一行由静态IP地址(必须在你的网络中可用),可选的域名和一个别称。这里有个假设的例子,我们为“树莓派”指定了名称:raspberrypi:
127.0.0.1 localhost 192.168.0.100 raspberrypi.yourDomain raspberrypi loghost
保存文件并退出编辑器。
使用超级用户,在编辑器中打开/etc/hostname,加入一行类似的内容:
raspberrypi
保存文件并退出编辑器。
以下说明可以预防一个问题,那就是网络负荷过重导致的操作系统去改变“树莓派”的静态IP地址,这样的结果就是使用这个静态IP地址的ssh或其他的操作将无法工作。
通过以下方法可以发现以太网端口的硬件地址。
首先确定以太网控制器的名称(x表示地址的数字):
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether b8:27:eb:b5:e8:90 brd ff:ff:ff:ff:ff:ff
inet xx.xxx.xxx.xx/xx brd xx.xxx.xxx.xxx scope global eth0
在这个例子中,它是eth0。硬件地址是16进制的数字,紧跟在link/ether之后,在这个例子是b8:27:eb:b5:e8:90。现在你已经有了以太网控制器的硬件地址,接下来用超级用户在文本编辑器中打开/etc/network/interfaces文件并且添加一些类似的行跟在# New entries注释之后,如下所示:
# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or
# /usr/share/doc/ifupdown/examples for more information.
auto lo
iface lo inet loopback
#
# New entries to support static IP follow:
auto eth0
iface eth0 inet static
hwaddress ether b8:27:eb:b5:e8:90
address 192.168.0.100
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1
开启交换和优化文件系统访问时间
默认情况下,swap在Debian Linux中是被禁用的。如果一个运算超过了“树莓派”的256MB内存大小,那么系统就会崩溃。一般情况下,文件系统会花费点时间为每个文件维护一个最后访问时间,然而在嵌入式应用程序中却很少使用。维护文件的最后访问时间可能会减少SD卡的使用寿命。这两种默认的行为都是在/etc/fstab文件中指定的。
使用超级用户,并在编辑器中打开/etc/fstab文件,例如:vi。文件看上去如下所示:
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 0
#/dev/mmcblk0p3 none swap sw 0 0
要打开swap,将第三行的注释去掉。
注意:swap在SD卡上是很慢的。对于嵌入式应用程序,你可能想通过管理内存而避免文件交换(swap技术)。
为了消除维护最后访问时间的开销,我们在p1和p3之间插入一个p2加载点。noatime和nodiratime选项完成了这项工作。当文件看上去像这样时,我们保存它并退出编辑器:
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 0
/dev/mmcblk0p2 / auto rw,noatime,nodiratime,errors=remount-ro 0 1
/dev/mmcblk0p3 none swap sw 0 0
现在我们分配p3(swap分区我们已经在主机的/dev/sdb3上创建过了)的swap空间:
$ sudo mkswap /dev/mmcblk0p3
设置时区和区域
默认情况下,“树莓派”被设置为Europe/London时区和en_GB_UTF-8字符集。为了本地化你的电脑,请看以下的说明。
为了改变时区,输入如下命令:
$ sudo dpkg-recofigure tzdata
一个图形接口会显示出来。
(图九)时区用户界面
使用上下箭头键在区域和城市之间移动选择光标。使用左右箭头键来选择<Ok>或<Cancel>。按回车键来确认选择。
如下命令用来设置区域:
$ sudo dpkg-reconfigure –p low locales
用户界面和设置时区的界面相似。
设置时间服务
很多操作,包括软件包的更新,都依赖一个正确的日期和时间。为了自动的设置日期和时间,需要获知一台网络时间服务器的标识。然后执行如下命令:
$ sudo ntpdate yourNTPServer
为了在每次启动后设置时间,请使用超级用户,编辑/etc/rc.local文件,在已存在的脚本之前加入如下行:
ntpdate yourNTPServer
设置Internet代理
要设置代理请执行如下命令:
$ sudo export http_proxy =’http:192.168.0.1:3128’
为了在你每次登录设置代码,请将export命令加入到~/.bash_profile文件中。
重新映射键盘
如果键盘的键值被误解,或是你想改变键盘的布局,请使用以下命令:
$ sudo dpkg-reconfigure keyboard-configuration
用户界面的操作和之前讨论的“设置时区和区域”的用户界面操作类似。
自动启动图形用户界面
如果你想在“树莓派”本地登录时自动的启动窗口系统,请修改默认的启动级别,如下所示。
使用超级用户,在编辑器中打开/etc/inittab文件,找到如下的记录:
# The default runlevel.
id:2:initdefault:
将它修改成5:
# The default runlevel.
id:5:initdefault:
注意:图形界面需要消耗“树莓派”大量的内存,大概需要90MB。
添加不同的Web浏览器
如果你觉得使用默认的midori浏览器体验不够好,那可以尝试iceweasel浏览器:
$ sudo apt-get update
$ sudo apt-get install iceweasel
开启音频
默认情况下,“树莓派”的音频输出是不工作的。为了开启它,请使用超级用户,在文本编辑器中开发/etc/modules文件,在文件的结尾处加入如下行:
snd_bcm2835
保存并关闭文件。音频将在你重启“树莓派”之后开启。
译者话痨:
按耐不住自己的兴奋之情,等待了3天,“树莓派”B型板终于到了,急不可耐的晒上照片。当真的拿到这款开发板之后,果然令我赞叹不已,就是一张银行卡的大小,做工也非常的精致,外壳设计的别树一帜,非常的精美,有图为证:
(图十)亚克力的透明外壳,盖子上还有镂空的LOGO标志
(图十一)盖子是可以翻起来的,方便在板子跳线(GPIO)或清理灰尘什么的,设计非常人性化(壳子是要另外买的不是标配)
(图十二)果然就是一张银行卡的大小