OpenWrt与嵌入式Linux
由于要接手学长留下来的一个项目,“被迫”要学习OpenWrt的配置方法——虽然对于一个five电工来说这事挺莫名其妙的,但还是硬着头皮上吧(我本想拒绝,但他给的是在太多了)
简介
在官网中这样描述OpenWrt
OpenWrt项目是一个针对嵌入式设备的Linux操作系统。OpenWrt不是一个单一且不可更改的固件,而是提供了具有软件包管理功能的完全可写的文件系统。这使您可以从供应商提供的应用范围和配置中解脱出来,并且让您通过使用适配任何应用的软件包来定制设备。对于开发人员来说,OpenWrt是一个无需围绕它构建完整固件就能开发应用程序的框架; 对于普通用户来说,这意味着拥有了完全定制的能力,能以意想不到的方式使用该设备。
听上去很高大上,实际上OpenWrt就和Ubuntu、CentOS、Raspbian等GNU/Linux发行版一样,是一个基于Linux内核的操作系统。只不过它具有高度模块化可定制的特点,并且自带一系列网络组件,因此常常被用于路由器、工控、智能家居、小型交换机中。笔者接手的这个项目就是基于OpenWrt实现路由器-交换机的应用,并配置一个网络摄像头和一个网口数据转串口
OpenWrt除了以上特点外,还有一个堪称嵌入式Linux杀手锏的特性:超级大规模的开源社区。可能是因为大家都很喜欢软路由,OpenWrt的软件包已经达到了好几千,这让它能秒掉一堆其他的嵌入式Linux发行版
OpenWrt与桌面Linux操作系统
可能大家无法理解OpenWrt这种发行版的独特之处,请允许我在这里为大家重新介绍一下桌面Linux操作系统
一般的桌面操作系统都很难在低性能的嵌入式设备上运行,这是因为两点:
它们需要占用大量的系统资源,尤其是内存用于支持各种deamon的运行
一般的GNU/Linux发行版都采用Bash乃至更人性化也更占用资源的Zshell作为终端;而OpenWrt为了适应低性能的处理器,采用更简单的Ash作为默认shell。此外,OpenWrt使用的C库是uClibc而不是glibc,这是一个面向嵌入式系统的小型C标准库,也有很多RTOS比如FreeRTOS和RT-Thread都采用了这个C库
它们的体积都比较大,一个典型的桌面操作系统占用的存储空间至少在1GB以上
Ubuntu已经膨胀到了2GB,Debian也往往需要占据1GB的硬盘/SD卡/Flash空间;但OpenWrt具有很强的可裁减性,其内核、驱动、自带软件都可以方便地通过menuconfig进行配置,它的运行内存最小只要32M,存放代码数据的Flash空间最小只要8M,但支持使用完备的Linux内核,支持无线、有线网络应用
OpenWrt牺牲了兼容性,但是由于庞大的开源社区资源,他能够对大多数网络嵌入式设备提供支持
OpenWrt优化了效率和资源占用,然而因为难以支持更高性能开销的应用导致其工作范围局限在嵌入式领域
OpenWrt与一般的嵌入式Linux
一般的嵌入式Linux都具有上面所说的特点,一些介于桌面Linux操作系统和嵌入式Linux操作系统之间并经过特殊优化的操作系统如Raspbian甚至能够提供更高的性能-资源占用比,但是OpenWrt相比一般的嵌入式Linux系统具有强大的多的网络应用:
默认自带SSH
可选的图形化网络操作界面Luci(Lua Configuration Interface)
这是一个使用Lua脚本语言编写的mvc架构的web框架,包含了openwrt的配置界面和一套扩展API。安装luci-core后只要在浏览器中输入OpenWrt设备的IP地址,即可出现其登录界面,可以通过安装luci扩展app实现对OpenWrt设备方方面面的管理
这个操作界面是对OpenWrt没有图形界面的有效弥补,也是它不同于其他嵌入式Linux的特殊点,这也使OpenWrt相当好上手
自带软路由模块和交换机模块,可配合硬件实现软/硬件路由功能
可选搭建VPN
可运行轻量级服务器软件
可运行轻量级流量整形与捕获分析软件
OpenWrt常常被用于搭建软路由,很大程度上就是因为它支持各种控制网络流量和数据包的应用扩展
除了以上网络特性,OpenWrt还支持嵌入式Linux所具有的基本能力,包括对POSIX的兼容和VFS等
OpenWrt与LEDE
LEDE是一个源于OpenWrt的分支嵌入式Linux系统,最初一批OpenWrt开发者觉得OpenWrt规则太老套,于是fork了OpenWrt的源码,然后创建了LEDE的分支,在里面添加了很多新开发流程和新功能,然后越来越多OpenWrt开发者转移到LEDE,最后二者又在2018年合并,形成了现在的OpenWrt
有的时候OpenWrt源里面会注明LEDE package,其实和OpenWrt一样,把它看成OpenWrt的某个版本即可
官网这样解释:
OpenWrt/LEDE是一个为嵌入式设备(通常是无线路由器)开发的高扩展度的GNU/Linux发行版。与许多其他路由器的发行版不同,OpenWrt是一个完全为嵌入式设备构建的功能全面、易于修改的由现代Linux内核驱动的操作系统。在实践中,这意味着您可以得到您需要的所有功能,却仍能避免臃肿。
在2016年,LEDE项目作为OpenWrt项目的副产品而诞生,与OpenWrt共享很多相同的目标。该项目旨在成为一个嵌入式Linux版本,能让开发者、系统管理员或其他Linux爱好者轻松的为嵌入式设备特别是无线路由器构建或定制软件。LEDE这一名称代表Linux Embedded Development Environment。
项目成员与OpenWrt社区活跃成员高度重合,他们计划通过建立一个高度透明、注重协作和去中心化的社区为嵌入式Linux的开发带来新生。
LEDE已公布的目标包括:
- 构造一个的伟大的嵌入式Linux发行版,运行稳定且功能实用
- 伴随社区设备测试反馈,形成定期、可预期的版本迭代
- 通过广泛的社区参与和公开会议,建立透明的决策机制
LEDE项目的形成是为解决那些被OpenWrt项目或社区认为无法解决的长远问题
- 活跃核心开发者数量一直很低,而且无法吸引新面孔加入项目。
- 不可依赖的基础设施,内部不同意和单点故障阻碍了错误修复。
- 在OpenWrt项目中缺少沟通交流、透明度和协调, 无论是在核心团队内部还是在核心团队和其他团队之间。
- 没有足够拥有权限的人处理补丁来流,很少关注测试和定期版本。
- 不重视对稳定性和文档。
为解决这些问题,LEDE项目采用了与OpenWrt不同的组织架构:
- 所有交流频道均是公开的,对非成员只读的频道控制在一个很好的信噪比。
- 决策过程更公开,拥有投票权的开发者和重度用户数量接近50比50。
- 大大简化基础设施,确保减少我们的维护工作量。
- 更开明的合并政策,基于我们在处理Github上OpenWrt软件包反馈信息的经验。
- 高度重视与简化发布流程合并的自动化测试。
2018年1月,OpenWrt和以前的LEDE项目同意以OpenWrt这一名称进行合并。
新的、统一的OpenWrt项目将按照 由前LEDE项目建立的章程 进行管理。以前的LEDE和OpenWrt项目的积极成员将继续在统一的OpenWrt上工作。
OpenWrt慢速上手
之所以这部分名叫《慢速上手》,是因为笔者要从底层开始到建立OpenWrt开发环境的全过程进行梳理,至于为什么——这就是我接手这个项目时遇到的窘境:学长跑路,给我留下了一堆残缺的资料,还有一个时灵时不灵的远程支援(虽然在前期的嵌入式开发debug部分确实给我帮了很大忙,但是怎么还在我滚挂系统的时候幸灾乐祸……这对青少年造成的坏影响,不可估量),于是只能从底层开始
所有我遇到的问题都会在
引用栏
中说明,避免后来者掉到坑里
硬件
硬件设备使用的是海凌科的MT7621模块,基于联发科7621A SoC开发
- MIPS架构CPU 1004Kc,双核主频880MHz
- 256MB内存,32MB片上Flash,16位DDR2
- 自带片上、板载晶振
- 3.3V、500mA工作电压电流
- JTAG调试接口
- 双WiFi接口
- 1个WAN口,4个LAN口,全千兆
- 2路SPI、1路IIC
- I2S、PCM等组成的音频接口
- 2路USB2.0、3.0接口
- 3路UART接口
- GPIO引出
GPIO
手头的MT7621 SoC带有GPIO外设,可以通过控制GPIO_MODE寄存器来使能对应引脚,默认情况下会直接将GPIO复用到其他外设。GPIO是32位的,每个寄存器控制32个IO
常用寄存器如下所示:
- GPIO_CTRL_X 方向控制寄存器,用于控制GPIO状态为1输出,0输入,2高阻态
- GPIO_POL_X 极性控制寄存器
- GPIO_DATA_X 数据寄存器,通过读取这个寄存器来获取当前GPIO的值
- GPIO_DSET_X 设置寄存器,置1进行使能GPIO
- GPIO_DCLR_X 清除寄存器,置1进行失能GPIO
使用方法如下:
登录OpenWrt,使用
1
2reg s 0
reg w 60 0x48258读取GPIO_MODE寄存器值,将要配置为GPIO的引脚位设为1
使用
reg r 60
查看是否配置成功对应datasheet按照寄存器顺序使用指令
1
reg w <寄存器位> <要写入的寄存器值>
进行配置
特别地,有些系统中提供了脚本控制的方法,这会使GPIO配置异常简单:
1 | echo "13" > /sys/class/gpio/export #要设置的引脚 |
当然如果你要给OpenWrt写一套串口驱动,那就必须按照Linux驱动标准来了,这里不再赘述
SPI与IIC
OpenWrt是支持SPI、IIC的,只要硬件支持就可以调用这俩东西
相对应的驱动随设备不同而不同,甚至需要在编译时单独加入
特别地,很多屏幕需要使用SPI驱动;很多摄像头需要使用IIC驱动(用来支持SCCB接口),因此最好在编译内核的时候将二者添加进去(占用空间并不是很大)
LAN口
路由器LAN口用来连接局域网,也就是内网,路由器可以为LAN口设备提供互联网接入或将所有LAN口设备连接到一个VLAN实现交换机目的
相关的内容等到之后的配置OpenWrt再说
WAN口
路由器WAN口用于连接外网,通常会通过某个外部路由器接入互联网
WAN口是路由器的灵魂,没有WAN口的路由器就是个死交换机,有了WAN口,它才能从外网下载程序、实现路由功能等
一般路由器的配置都是单WAN口多LAN口
这里使用的路由模块配备了1WAN口4LAN口
很可惜,在硬件组装初期,笔者的路由器WAN口完全连不上,不仅仅无法ping通,甚至ifconfig根本看不到有这个接口
在这种情况下如果想安装软件包就必须使用LAN口,在路由器端使用SCP协议拉取上位机提供的软件包,然后用opkg进行安装(opkg是OpenWrt里面类似dpkg的一个软件包管理器,可以很方便地安装、更新、删除软件包、切换软件源)
解决方法在后文给出
网络变压器与Bob-Smith电路
在网络硬件设计中经常接触到RJ-45网口,现在的RJ45网口很多都自带了网络变压器,因此只要正常接入并记得使用75欧或50欧电阻进行阻抗匹配就可以了;但是对于这里的路由模块,它使用杜邦线-排针代替RJ45网口(别问为什么,问就是特殊领域),因此需要仔细设计网络变压器部分的电路,它被称为Bob-Smith电路
他有如下几个关键作用:
信号传输
Bob-Smith电路分为电流型和电压型,根据驱动网络变压器的是电流为主还是电压为主区分
电流型:网络变压器输入侧(接PHY芯片或SoC的那一侧)需要在每个变压器抽头处上拉到电源,如果EMC要求更加严格,还会使用一个高频(75MHz-200MHz)电感跨接在抽头和电源之间,上拉电源可以是1.8、2.5、3.3等,这是为了增强网络变压器的驱动能力
同时需要在输入侧变压器正负端跨接50-100欧姆(常用75欧姆)的分流电阻,用于调整信号驱动强度
电压型:输入侧变压器抽头接到一起再通过100nF电容到地,这是为了提高网络变压器的EMC性能;正负端则分别接入50-100欧分压电阻到PHY芯片或SoC,用于调整信号驱动强度
阻抗匹配
阻抗匹配:当传输路径上阻抗不连续时,会有反射发生,阻抗匹配的作用就是通过端接元器件时,保证传输路线上的阻抗连续以去除传输链路上产生的反射。
网络变压器的输出端要接共模双绞线,双绞线上传输的是差分信号,因此需要使用100-150欧的阻抗匹配
网络变压器输出端的抽头都需要接50欧或75欧(根据线缆长度不同决定,也可以改为100欧,但25欧因为阻值太低不常用)到线缆,同时需要一个100nF的电容用于旁路(滤波)
这几个电阻就起到了阻抗匹配作用,计算公式如下
$$
Z=\sqrt{R-j\frac{1}{\omega C}}
$$波形修复
输出端的旁路电容可以有效对外传输线路上的噪声实现滤除
抑制杂波
电压型BS电路通过下拉到地的100nF滤波电容实现了滤出高频噪声的作用,而两个串联在变压器上的分压电阻配合变压器寄生电感可以提高电路对差模信号的抑制能力,从而滤除高频杂波,保证网口通信正常
电流型BS电路则直接使用较高电流驱动的方式削弱从控制端输出的高频杂波影响。但是因为电流型电路会导致整体功耗较大,所以正在被电压型取代(不过在大功率信号传输的领域还是有一定应用)
隔离高压
这一条也可以称为共模-差模防护,电路可以通过一系列泻放路径抵抗从网络变压器输出端而来的浪涌电压电流。
具体实现出于篇幅所限不在这里列出,大致思路就是共模浪涌会被变压器和输出端电阻自行抵消,最多可能付出电容被击穿的代价,并不会伤害到控制端;而差模信号会被变压器引入到输入端,之后直接通过抽头的电容或上拉电阻被滤除,能够很大程度地减少对输入端和信号的影响
在配置过程中发现:WAN口无法使用
重新刷入三次系统,反复调试一周后发现还是这样,基本上排除了所有可能的软件问题。于是决定回到硬件检查是否网络变压器或引脚出问题。首先用万用表通断档依次检测电容两端对地是否导通,发现WAN口的输入电容两端都对地为0——短路了;之后换用电阻档断电测量输入输出电阻,原本电路中使用75欧电阻,但测量中发现有两个电阻阻值不对,一个是偏小到50欧,另一个则无穷大。换掉电容电阻,上电接网线,成功秒杀
自定制并编译内核
openwrt整个项目在github上可以找到
也可以通过官方OpenWrt源码下载
于是直接用git下载或下载压缩包到linux系统就可以使用了
一般来说可以使用虚拟机搭建环境,但是如果你习惯了使用桌面端linux,可以直接在你的双系统/纯linux环境中搭建openwrt的开发环境
配环境
根据openwrt项目中的README文档就可以简单地配好整个环境,这里摘录一下在ubuntu20中所需要安装的一些关键软件包
1 | sudo apt install gcc g++ make gettext libncurses5-dev patch binutils flex bison subversion build-essential autoconf bzip2 libz-dev zlib1g-dev gawk git ccache gettext asciidoc libssl-dev sphinxsearch xsltproc sphinx-common libtool libssl-dev unzip |
安装完依赖以后还要下载一些openwrt主分支中没有加入的源代码,这些都是诸如kernel、package之类的大号源码,需要从官方对应的版本库中拉取到本地
这里需要注意:版本!
在拉取之前应该确定你想要编译的内核版本
常用的大版本有14、15、16、17、18、19,小版本从.1到.9不等,各个版本差异都比较大,大版本之间软件包基本是不可能通用的,小版本之间的软件包安装也存在各种问题,所以选版本的时候尽量考虑清楚
使用指令git checkout openwrt-xx.xx
来切换到某个指定的内核版本,可以通过git指令查看各个版本间的不同
选择版本后就要添加软件扩展包了:
首先
1 | cp feeds.conf.default feeds.conf |
设置所需要使用的源,然后
1 | ./scripts/feeds update -a |
更新并安装扩展程序
完成后应该可以看到OpenWrt目录如下:
- config 编译选项配置文件目录: 包含全局编译设置,开发人员设置和内核编译设置
- include 就是普通的头文件目录,但是也包含了各种脚本和Makefile
- package 软件包目录
- scripts 环境脚本、下载补丁脚本、Makefile等
- target 嵌入式平台移植包
- toolchain 编译器和C库工具链
- tools 用于生成固件的辅助工具
- dl 下载的软件包目录
顺带一提,在编译完成时还能看到build_dir和staging_dir,二者分别是中间文件目录和编译安装目录
在完成配置后可以使用make defconfig
来测试编译环境是否配置正确
千万注意不要被老版本的配环境资料误导,包括本篇!不要看见一个差不多的资料就从里面复制粘贴指令!
一定要选择适合自己系统的配环境资料,最好查阅官方文档!虽然会麻烦一点但是可以很大程度上避免滚挂系统!
不要问我怎么知道的,我只能说linux双系统有风险,滚挂系统重装好麻烦的!
menuconfig
配完环境以后就可以进行半可视化配置内核、应用程序的menuconfig了
先使用
1 | make menuconfig |
打开menuconfig半图形化配置界面,在里面添加需要选用的组件
操作:键盘上下移动光标,左右选择底部按键,回车是确认,空格是设置选择模式,选项最前面的选择模式有[*]表示编译进固件,[M]表示编译成安装包,[ ]表示不选择,esc是返回上级菜单,按?是帮助,按/是搜索
注意一般应用程序编译成安装包等进入系统后再安装,kmod内核驱动要编译进固件,带opkg字样的东西一定要编译进固件,不然没法安其他包
配置选项定义
配置选项 | 含义 |
---|---|
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 | 一些实用工具模块 |
(上面内容摘录自https://www.jianshu.com/p/e2b5a292392e)
完成选择后就可以保存退出了,生成的文件会让你命名,一般直接保持默认.config
即可
在这个项目里,我遇到的最大问题就是在menuconfig的时候安装进模块的软件包无法使用,于是只能和OpenWrt内核版本、底层硬件驱动、网口配置斗智斗勇……在一般情况下面对嵌入式设备一定要首先考虑在menuconfig的时候安装软件包,否则后续的操作有可能反而比menuconfig复杂——尤其是在安装额外的kmod,也就是内核驱动时。自行编译的内核是具有独立的md5码的,并不能和官方的bin文件对应的md5码吻合,这就导致下载软件包的时候kmod无法匹配内核,所以要使用强制安装,而又因为你的内核是自行编译的,所以很有可能会出现因为内核版本不对而很多程序无法运行,甚至运行时崩溃的情况
漫长的编译
make就完事了,make的时候可以换各种姿势
1 | make V=s #输出编译信息,第一次编译一般用这个,单核编译小水管不得不品尝 |
特别地,现在GitHub有一个叫Actions的服务,有人利用这个服务制作了一套在线编译OpenWrt的系统
主要有以下特色:
- 免费!快速!一次编译成功率高!
- 一键快速自动多线程编译
- 无需搭建编译环境,上手就用,用完就扔
根据项目的中文介绍页面里面的介绍一步步来就可以实现在线编译了(记得提前准备一个GitHub账号)
其中比较友好的是可以支持SSH连接到GitHub Actions虚拟服务器环境,直接在服务器上menuconfig
编译的时候出现了很多错误,不要嫌麻烦,挨个查看改正就行,第一次编译难免出错,正常情况下改一天肯定是能编译出来的
不过后续烧录能不能识别嘛……祈祷自己的设备比较常见吧;特种设备采用特殊器件装特殊系统……自求多福,运气好总能成功的
上位机连接到OpenWrt
终于完成了整个系统的编译,接下来就能尝试烧录并连接到设备了。烧录过程和设备具体硬件配置有关
烧录
如果你使用的是普通路由器,一般来说连上LAN口,登录网关地址,里面的选项里会有一个更新固件,直接把bin文件上传,点击烧录就可以了;如果使用的是一般的嵌入式设备,一般可以选择使用openocd配合jtag进行烧录,只要900+rmb氪入一套jlink基本可以完美烧录(笑)上面两个方法都太简单(没钱买设备是个人问题,有钱人烧录都很简单的)。下面介绍一下常用的三种烧录方法:
uBoot烧录
一般来说设备出厂以后都会烧录uBoot,这个东西和grub有点像,但是它工作在嵌入式领域,可以支持Linux、安卓、FreeBSD等系统的引导,支持MIPS、x86、ARM、RISC-V等等各种架构的CPU,而OpenWrt对应使用的uBoot往往会着重增强网络能力,因此一般OpenWrt设备的uBoot都会自带TFTP协议的功能,并且会打开一个操作界面,因此可以直接参考厂商给出的说明,按以下步骤启动设备
- 连接LAN口到上位机
- 修改上位机IP为厂商指定的静态IP地址,并按照地址设定子网掩码
- 下位机设备断电,按住Boot按键(或者叫WPS按键)(当然如果没有这个按键应该从Boot引脚到地焊接一根跳线)
- 将设备上电
- 保持按键一段时间,等待设备从uBoot启动(类似于按住进入键盘上某个键进入BIOS设置界面)
- 松开按键并在上位机打开厂商指定的IP地址(浏览器打开,别想着用什么奇奇怪怪的软件)
- 选择固件、上传、等待
- 等到足够长时间以后(具体多长要参考厂商说明)修改LAN口为dhcp或默认设置的静态IP
- 尝试正常连接路由器
如果中间没有操作界面,可以尝试反复ping要连接的uBoot地址,如果能ping通那就是连上了,之后使用类似下面的uboot命令(由厂商决定)
1
2
3
4
5
6tftp 固件保存地址 要上传的固件
erase 固件启动地址 + $固件大小
cp 固件保存地址 固件启动地址 $固件大小
set bootcmd 固件启动地址
save
boot总体过程就是:上传-擦除原本固件-复制上传的固件到启动位置-设置固件启动位置-保存-重启设备
uBoot功能很强大,在某种程度上说它就像桌面版linux的livecd一样,只要uboot不刷坏,设备就可以说是不死的,一直可以通过重新进入uboot的方式刷新系统
顺便提一下,对于14.07版本的内核,应用在MT7621上时,安装kmod-usb-ehci与kmod-usb-hid可能会导致冲突让系统崩溃,就是因为同时安装了他俩让我不得不重新刷机好几次
luci界面升级
就是上面说过的登入网关以后从配置界面上传固件升级的过程,但是一般来说会保留原来系统的配置,所以最好刷更新的固件,而不是刷老版本固件,否则会有可能变砖,还需要用第一种方法再刷一次
烧录器烧录
如果uBoot损坏、网口有问题甚至Flash挂了,那就必须使用这种方法了。
一般来说需要使用专门的Flash烧录器配合上位机软件对准Flash的引脚进行烧录,Flash烧录器有1.8V、3.3V、5V三种,一般来说现在的SPI Flash(最典型的W25Q128)使用3.3V烧录器就可以,但是很多设备都用上了低功耗Flash,这就需要一个电平转换板或者直接使用1.8V烧录器进行烧录。如果是最为极端的情况,Flash挂了,那就必须把Flash拆下来,换一个新Flash上去再烧录
在艰难的配环境过程中,某个不愿透露姓名的学长就把Flash整废了,好巧不巧那块Flash还是特殊封装的贴片元件,极其难焊接,于是只能购入巨贵的专用烧录板,烧录新的Flash以后再装上去。由于没碰见过这种情况+快递速度缓慢,流程整整走了一周。
笔者接手项目以后,还遇到了uBoot死活不启动的情况,检查电路以后发现是板上的Boot线路被莫名划坏一道,于是补好了铜线才得以启动uBoot
新手注意:遇到uBoot不启动不要慌,较大可能是你按的时间不够久或者操作有疏忽导致uBoot启动被跳过了,只要认真多试几遍总能成功,在期间善用百度很关键
Luci
完成系统烧录以后,上电,上位机连上LAN口,等待几分钟,浏览器打开网关地址(一般是192.168.1.1
),一般来说就能进入一个登陆界面,这就是OpenWrt的Luci界面
通过这个界面可以对设备的大多数设置进行调整,这里不多作介绍,都是很直接了当的东西
在某些角落会留着language的设置栏,在这里可以选择语言,省去啃生肉的烦恼
串口终端
最传统登录Linux的方法当然是串口终端——不论嵌入式linux还是服务器linux
TTL串口是人类的好朋友
这种方法不必多说,折腾过树莓派的人都懂,串口调试器连接UART Tx、Rx、GND,重启设备,开启Putty或者XShell,之后开机信息就会从界面喷涌而出
SSH
这种方法很适合具有WiFi功能的OpenWrt设备,能够省掉一根网线。不过有网线连接的时候也很实用,对于linux来说命令行总是比可视化可靠。
连上网线ping通后,直接
1 | ssh 用户名(一般是root)@目标设备IP |
就可以登录到OpenWrt了
任何其他Linux发行版允许的登录方式
只要在内核里面使能了某个可行的登陆方式,并且硬件允许它运行,那么用户就能用这种方式进行登录OpenWrt
毕竟这可是Linux啊!
联网
强调一下:如果是必须的kmod还是应该先想好然后在编译内核阶段完成安装
一般来说正常安装了网络设备驱动和普通luci界面的设备直接插上网线或者通过luci界面配置好wifi以后就可以联网了,但是如果无法联网可能有以下几个原因:
- 编译内核时没有把网络设备驱动编译进去(一般来说是默认添加且不能修改的,但是谁知道用户会做出什么逆天操作)
- 外部设备不支持联网(一般是硬件坏了,弄个交换机上OpenWrt还不如多花点钱买个带千/万兆网口的)
- 配置问题
1、2点需要重新编译或者检查硬件甚至重新选型,非常难以解决,所以一定要避免这两种问题出现;第三种相对容易解决一些,根据百度到的教程一步步来即可,一般来说都是因为路由器接口/netif/wpa/交换机接口配置出错,依次排除不要着急
在我调试这个板子的时候发生了一件很绝望的事情:板子无法联网,但是能够在内网登录luci界面并ssh。刚开始我以为是软件问题,先去查找了一遍OpenWrt的官方文档,通过luci界面配置了一遍接口,但是无济于事;然后又ssh进去通过vi查找配置文件,无果;因为项目进度逼的比较紧,于是只能换用离线装软件包的方法。等到折腾了一大通硬装软件包以后才想起来检查硬件问题,最后发现是开头说的网络变压器电路问题导致无法联网
所以嵌入式编程一定要先排除硬件问题!
包管理器
OpenWrt最与众不同的一点就是它配备了opkg包管理器,它和apt、yum、pacman等指令使用方式类似,能够不是很智能地智能解决软件包依赖问题:只能解决一点点。一般来说自动解决需要一层依赖的软件包安装还是可以的,但是为了安全起见还是一步一步的安装软件包吧。opkg常用指令如下
1 | opkg install |
软件包管理器的设置位于/etc/opkg
中
这个包管理器也是支持换源的,如果某个软件源不好连接,完全可以更换当前使用的软件源,使用luci界面就可以轻松换源,如果非要使用命令行也可以像ubuntu那样直接编辑设置文件来换源
具体操作网上有很多,不再赘述,特别指出善用下面的指令可以快速更换软件源的域名
1 | sed -i |
特别地,安装软件包时如果碰到了kmod字样的软件包,就说明这是一个内核驱动包,在安装它的时候很可能会遇到内核版本不正确的情况——因为自行编译的OpenWrt生成时会自动携带一个经过修改的md5码,它往往和已有的内核驱动应该对应的验证码不一致,因此会出现报错,这种情况下在安装指令后面加上如下参数就可以解决问题了
1 | --force-depends |
如果还是不行,甚至出现系统崩溃、变砖的情况,就要考虑是否是自己的软件源选错抑或是自己编译的内核版本不对了
这就是为什么在上面反复强调要注意内核版本与内核驱动
snapshot版本和release版本区别
我们经常会看到软件源中的某些项目版本以release或snapshots结尾,一般来说snapshots版本代表正在开发中的版本(快照版本,一般处于开发阶段),release代表比较稳定的发布版本(这次迭代的所有功能都已经完成)
换源的操作对于嵌入式Linux,或者说OpenWrt来说不是很重要,但是在面对很难处理的软件bug时可以考虑换源来解决,我在处理项目时通过多次换源解决了一些软件包的依赖问题,使用到的源如下:
清华源 src/gz barrier_breaker_base http://mirrors.tuna.tsinghua.edu.cn/openwrt/barrier_breaker/14.07/ramips/mt7621/packages/base
稳定版官方源 src/gz barrier_breaker_base http://downloads.openwrt.org/snapshots/trunk/ramips/mt7621/packages/base
快照版官方源 src/gz barrier_breaker_base http://downloads.openwrt.org/snapshots/trunk/ramips/mt7621/packages/base
存档版官方源src/gz barrier_breaker_base https://archive.openwrt.org/snapshots/trunk/ramips/mt7621/packages/base
主要的思路就是查看自己要安装的软件包都需要什么依赖,然后对照依赖版本寻找对应的md5码,再根据md5码选择支持的官方源
在换源的时候可能会遇到下面的报错:Package xxx version xxx has no valid architecture, ignoring.
这是因为源指定的系统和设备上刷入的系统md5码不符合,可以直接在/etc/opkg.conf文件中加入对系统支持的architecture的设置,也就是在文件中添加下面的内容:
1
2
3 arch all 100
arch <arch类型1> 200
arch <arch类型2> 300arch类型可以在源下面的package目录内配置文件中查找到,我使用的配置如下:
1
2
3
4 arch all 100
arch mips 200
arch ramips 300
arch unkown 400换用官方archive源也可以帮助解决一些老版本不兼容的问题
安装软件包
只要登陆进luci界面,再让设备联网就可以轻松地进行可视化安装,并且luci界面还会将软件包依赖关系列出来,非常简便;命令行下的安装过程也不算复杂,和ubuntu、centos等发行版的软件安装方法类似
一般我们用opkg安装软件有两种方式:
是连上网络后从官方网站安装
1
2opkg update
opkg install xxx把软件下载到上位机(直接进入软件源网页,通过ftp下载即可),通过winscp或者linux下使用scp指令传到路由器tmp目录,再使用指令
1
opkg install xxx.ipk
安装
如果路由暂时上不了网,就无法使用前一种方法,后一种方法又有些麻烦,其实除此之外还可以通过上位机开启ftp/http服务,让设备接入来实现“在内网”安装:
在本机上开ftp/http/其他网络服务
修改/etc/opkgconfig,将第一行的网址(也就是软件源地址)改成上位机服务器放安装包的服务目录
从软件源下载需要的安装包到服务目录
把软件源的packages文件下载到服务目录
使用指令
1
2opkg update
opkg install xxx安装软件
上面提到了本地安装软件包的方法,所以在这里特别提一下,实际上安装非常麻烦,所以尽量不要使用这种方法