一、 简介
openWRT是一个堪入式设备的linux发行版,开发团队每年至少发行一个新版本,现在最新版本版本号是LEDE 。
接下来我将会介绍怎样为一个设备安装openWRT系统。
二、准备
- 准备一台linux主机, 可以是Ubuntu、Debian、 Gentoo、 Centos 等等。
- 为主机安装以下必需的软件:
- AsciiDoc 是一种文本文档格式,可以用于书写文档,文章,手册,书籍和UNIX手册。
- 2.GUN Bash 大家都认识。
- 3.GUN Binutils 是一整套的编程语言工具程序,用来处理各种格式的目标文件,其中包括汇编器和链接器。
- 3.bzip2 bz格式文件压缩或解压缩工具。
- 5.flex 是词法分析工具,用于编译程序语言。
- 6.git 大家都认识。
- 7.g++ 、gcc 、 make、 unzip 这些都是熟人
- 8.ncurses 提供字符终端处理库。
- 9.openssl/ssl.h 安全软件包,应用程序可以使用这个包来进行安全通信,避免窃听。
- 10.gettext 是一种国际化与本地化系统,在类Unix系统中编写多语言程序时经常被使用。
通过以下方法安装所需软件包
- UBUNTU 18.4 LTS :
sudo apt-get install subversion build-essential libncurses5-dev zlib1g-dev gawk git ccache gettext libssl-dev xsltproc zip
- UBUNTU 18.4 LTS :
- Debian 9.4 Stretch :
sudo apt install build-essential libncurses5-dev gawk git libssl-dev gettext zlib1g-dev swig unzip time
- Debian 9.4 Stretch :
- Centos x86-64 (some packages require EPEL)
yum install binutils bzip2 gcc gcc-c++ gawk gettext flex ncurses-devel zlib-devel zlib-static make patch unzip perl-ExtUtils-MakeMaker glibc glibc-devel glibc-static ncurses-libs sed sdcc intltool sharutils bison wget git-core openssl-devel xz
- Centos x86-64 (some packages require EPEL)
下载openWRT源代码
git clone https://git.openwrt.org/openwrt/openwrt.git
- 可以指定代码分支
例如: lede-17.01 :git checkout lede-17.01
openwrt-18.06:git checkout openwrt-18.06
- 可以指定代码分支
三、了解openWRT
目录结构
- openwrt包含以下几个顶层目录:
目录 | 含义 |
---|---|
config | 这是编译选项配置文件: 包含全局编译设置,开发人员设置和内核编译设置 |
include | 包含准备环境脚本,下载补丁脚本,编译Makefile和编译指令 |
package | 各种功能的软件包,软件包仅包含Makefile、补丁及配置文件 |
scripts | 包含准备环境脚本、下载补丁脚本、编译Makefile以及编译指令 |
target | 嵌入式平台,包含特定的嵌入式平台内容 |
toolchain | 编译器和C库,例如包含编译工具gcc和glibc库 |
tools | 通用命令,用来生成固件的辅助工具,如patch/make/spuashfs等 |
- 编译之后会增加以下目录:
目录 | 含义 |
---|---|
dl | 下载软件代码包目录,软件包编译前会将包下载到该目录。 |
build_dir | 编译时的中间文件目录,软件包编译时会将代码包解压到该目录。 |
staging_dir | 编译安装目录,文件安装到这里,并根据这里的文件生成最终编译结果。 |
- 脚本文件目录概说
脚本文件 | 含义 |
---|---|
scripts/download.pl | 下载编译软件包源代码脚本 |
scpipts/patch-kernel.sh | 打补丁的脚本 |
scripts/feeds | 扩展软件包工具,用于下载和安装扩展软件包 |
scripts/diffconfig.sh | 收集和默认配置不同的脚本 |
scripts/kconfig.pl | 处理内核配置的脚本 |
scripts/deptest.sh | 软件包依赖项检查 |
scripts/metadata.pl | 检查metadata脚本 |
scripts/rstrp.sh | 裁剪目标文件中的符号、使固件变小 |
scripts/timestamp.pl | 生成文件的时间戳 |
scripts/ipkg-make-index.sh | 生成目标系统应用包ipk索引,在使用opkg安装应用时使用 |
scripts/ext-toolchain.sh | 工具链 |
scripts/stip-kmod.sh | 删除内核模块的符号信息,使固件变小 |
编译流程
1.编译环境检查
2.生成交叉编译链
3.下载需要编译的代码包
4.打补丁
5.编译及生成固件
- 输入命令
make defconfig; make
openWRT就会生成一个默认配置的固件
- 输入命令
编译配置
openWRT自动完成上面1 - 5五个步骤, 如果要自定义配置,输入make menuconfig
就可以通过配置界面自定义。要为设备安装适合的openWRT系统,就必须进行适合的配置。
进入openwrt目录,make menuconfig 会显示如下界面:
配置选项定义
配置选项 | 含义 |
---|---|
Target System | 目标平台,对应目录openwrt/target/linux 里的目录 |
Subtarget | 目录 openwrt/target/linux/(目标) 里的子目录,定义特定目标 |
Target Profile | 目标描述文件,在subtarget目录下面的profile目录中 |
Target Images | 编译生成目标固件的控制选项 |
Global build settings | 全局编译设置,按默认设置进行编译就可以 |
Advanced configuration options | 高级配置选项,无需理会 |
Build the OpenWrt Image Builder | 可以编译出一个编译系统供其它主机安装 |
Build the OpenWrt SDK | 编译生成SDK开发包,提供给其它主机进行应用开发 |
Package the OpenWrt-based Toolchain | 生成开发工具链包,提供给其它主机进行应用开发 |
Image configuration | 控制是否打开feed.conf中的模块 |
Base system | 基本软件包选择,主要是busybox组件 |
Boot Loaders | 引导系统的系统,不用管它 |
Development | 开发包、开发工具,如gcc、gdb之类 |
Firmware | 特定硬件的固件 |
Kernel modules | 内核模块、内核配置选项 |
Languages | 软件开发语言选择 |
Libraries | 动态链接库选择 |
Network | 网络功能模块选择 |
Utillities | 一些实用工具模块 |
四、了解设备
要想正确编译出OpenWrt固件,需要熟识openwrt/target/linux目录下的目标平台目录,目标平台目录相当于设备的描述文件,能正确选择合适的平台,则要熟识设备。
有一个新设备,想要了解它,就需要取得一些权限
- ssh/telnet 的权限,如果有ssh/telnet权限就可以获知设备更多的硬件信息
- 串口的权限,如果有串口控制的权限就可以通过串口控制bootloader
- JTAG接口,利用JTAG软件通过JTAG接口烧录falsh
有了上面的权限,可以收集到设备更多的信息
在编译OpenWrt前,需要知道:
- 设备是基于什么目标平台,例如ARM、MIPS、X86,用的SOC是什么型号,例如AR9331、QCA9531,知道型号后,可以查阅相关SOC的Datasheet,深入了解SOC的结构和功能,弄清楚设备使用什么型号CPU,什么类型存存器,搭载了什么类型的网络设备。
- 设备使用那些GPIO控制LED?
- 设备是否有特殊的SPI设备? I2C设备?
- GPIO连接的其它设备?
五、 GPIOS
GPIO 是通用型输入输出的简称,使用者可以很方便的通过GPIO接口控制多种外部设备,如:舵机、LED等。
GPIO LED
使用下面脚本可以检测到LED灯是和那个GPIO相连接的
#!/bin/sh
GPIOCHIP=0
BASE=$(cat /sys/class/gpio/gpiochip${GPIOCHIP}/base)
NGPIO=$(cat /sys/class/gpio/gpiochip${GPIOCHIP}/ngpio)
max=$(($BASE+$NGPIO))
gpio=$BASE
while [ $gpio -lt $max ] ; do
echo $gpio > /sys/class/gpio/export
[ -d /sys/class/gpio/gpio${gpio} ] && {
echo out > /sys/class/gpio/gpio$gpio/direction
echo "[GPIO$gpio] Trying value 0"
echo 0 > /sys/class/gpio/gpio$gpio/value
sleep 3s
echo "[GPIO$gpio] Trying value 1"
echo 1 > /sys/class/gpio/gpio$gpio/value
sleep 3s
echo $gpio > /sys/class/gpio/unexport
}
gpio=$((gpio+1))
done
这个脚本的原理是遍历设备所有GPIO接口,对接口分别输出低电平和高电平,观察到LED到产生变化时,记录下产生变化时遍历到的GPIO编号,最后就能找出所有和LED有连接的GPIO。
GPIO 按钮
使用下面的脚本可以找出和按钮连接的GPIO接口
#!/bin/sh
GPIOCHIP=0
BASE=$(cat /sys/class/gpio/gpiochip${GPIOCHIP}/base)
NGPIO=$(cat /sys/class/gpio/gpiochip${GPIOCHIP}/ngpio)
max=$(($BASE+$NGPIO))
gpio=$BASE
while [ $gpio -lt $max ] ; do
echo $gpio > /sys/class/gpio/export
[ -d /sys/class/gpio/gpio${gpio} ] && {
echo in > /sys/class/gpio/gpio${gpio}/direction
echo "[GPIO${gpio}] value $(cat /sys/class/gpio/gpio${gpio}/value)"
echo ${gpio} > /sys/class/gpio/unexport
}
gpio=$((gpio+1))
done
脚本使用方法:
- 执行脚本,将会输出所有GPIO接口的当前状态。
- 按下按钮,保持按下状态。
- 再次执行脚本,脚本输出GPIO状态。
- 对照两次脚本输出,状态变化的GPIO接口就是和按钮相关。
- 记录下来。
六、例子
参考 [dragino] (www.dragino.com) 板子的例子
-
在target目录里找出和dragino相关的文件
grep -lri dragino target/
grep搜索结果如下:
target/linux/ar71xx/base-files/etc/board.d/01_leds
target/linux/ar71xx/base-files/etc/diag.sh
target/linux/ar71xx/base-files/lib/upgrade/platform.sh
target/linux/ar71xx/base-files/lib/ar71xx.sh
target/linux/ar71xx/files/arch/mips/ath79/mach-dragino2.c
target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt
target/linux/ar71xx/files/arch/mips/ath79/Makefile
target/linux/ar71xx/files/arch/mips/ath79/machtypes.h
target/linux/ar71xx/config-4.14
target/linux/ar71xx/image/generic.mk
target/linux/ar71xx/generic/config-default
- 重要文件
(1)/target/linux/<arch_name>/base-files/etc/…
这个目录的文件是要和固件的/etc目录集成到一起的,包含了以下的子目录和文件:
* …board.d/ 包含一些用来定义硬件的脚本,例如LED、网络接口
* …hotplug.d/ 包含一些定义热插拔的脚本
* …init.d/ 包含开机启动脚本
* …uci-defaults/ 包含一些默认的uci配置文件
* …diag.sh 各个板子的错误代码LED指示脚本
(2)/target/linux/<arch_name>/base-files/lib/…
这个目录的文件将会和固件中的/lib目录集成在一起,它包含如下目录和文件:
*…<arch_name>.sh 和体系相关联的应用脚本
*…preinit/ 当前体系通用的前置启动脚本
*…upgrade/ 当前体系通用的固件升级脚本
(3)/target/linux/<arch_name>/dts/
包含设备描述源文件,有些DTS文件如果在上游的linux目录里出现过,就不会出现在这里
可以使用命令`make target/linux/{clean,prepare}`下载和更新DTS
(4)/target/linux/<arch_name>/image/
固件映象配置文件
(5)/target/linux/<arch_name>/<board_name>/
目录如存在,则保存和当前设备相关的独立配置文件
(6)/target/linux/<arch_name>/modules.mk
Linux模块配置文件