14.OrangePiZero2系统移植
OrangePiZero2系统移植
之前我们讲解香橙派的使用时, 都是直接在香橙派上进行代码编译, 但在实际的项目开发过程中,更多
的还是使用交叉编译环境进行代码的编译。再编译完成之后再把代码放到香橙派等ARM开发板上运行。
因此这章节专门讲解下交叉编译环境的搭建、Uboot移植和内核移植内容
1.OrangePi Zero2 SDK说明
SDK 全称 Software Development Kit,即软件开发工具包。一般包括了一些工具(如交叉编译工具
链)、库、文档和示例代码。香橙派的Linux SDK其实指的就是 orangepi-build 这套代码集,orangepi
build 在脚本和配置文件中会指定 u-boot、Linux内核和交叉编译工具链的地址,运行 orangepi-build
时,当其发现本地没有这些东西,会自动去相应的地方下载的。使用 orangepi-build 可以编译出多个版
本的 Linux 镜像。
1.1.环境要求
新版本的orangepi-build对编译主机(也就是搭建的vmware 虚拟机)的要求:新版本的orangepi-build是在Ubuntu22.04的x64电脑或者虚拟机上运行的。
-
确认自己的虚拟机或者Ubuntu实体机是不是22.04的方法如下:
kevin@kevin-virtual-machine:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammy -
如果不是,可从ubuntu官网重新下载ubuntu 22.05 x64镜像,重新更新下虚拟机,ubuntu 22.05
X64镜像下载地址:
http://releases.ubuntu.com/jammy/ubuntu-22.04.5-desktop-amd64.iso -
编译出来的完整SDK大概有16 G大小,因此建议在创建虚拟机时,至少分配50G的存储给虚拟机使用。
1.2.获取Linux SDK
1.2.1.方法一:从 github 下载 orangepi-build(*要求网络要好,因此当前不是特别推荐)
搭建完虚拟机后, 从github下载香橙派Linux SDK:
kevin@kevin-virtual-machine:~$ sudo apt update
kevin@kevin-virtual-machine:~$ sudo apt install git
kevin@kevin-virtual-machine:~$ git clone https://github.com/orangepi-xunlong/orangepi-build.git -b next
- 如果git clone失败, 也可以直接访问该网址, 把orangepi-build的压缩包下载下来后,再放到编
译主机里。
然后解压下载下来的压缩包:
unzip orangepi-build-next.zip
-
orangepi-build 下载完后会包含下面的文件和文件夹
a. build.sh: 编译启动脚本, 我们可以通过build.sh编译uboot、内核、根文件系统甚至完整的img
b. external: 包含编译镜像需要用的配置文件、特定的脚本以及部分程序的源码等
c. LICENSE: GPL 2 许可证文件
d. README.md: orangepi-build 说明文件
e. scripts: 编译 linux 镜像的通用脚本
-
解压完后,需要去修改适配orangepizero2的配置脚本
cd ~/orangepi-build-next vi ./external/config/sources/familiessun50iw9.conf
配置文件 sun50iw9.conf修改,在next分支里的内核配置版本(默认是6.1.y这里改成5.16.y版本),不然6.1.y默认编译出来的内核默
认没有无线网卡、I2C也不支持。
## For Linux5.16.y
KERNELBRANCH="branch:orange-pi-5.16-sunxi64"
LINUXCONFIG="linux-5.16-sun50iw9-current"
## For Linu6.1.y
#KERNELBRANCH="branch:orange-pi-6.1-sun50iw9"
#LINUXCONFIG="linux-6.1-sun50iw9-next"
1.2.2.方法二:从百度网盘下载(推荐使用该方法, 就不用考虑github下载过程中出现下载失败导致最后编译出 来的系统可能是异常的)
从下面的百度网盘链接下载提前编译好的oragepi-build SDK包:
链接:https://pan.baidu.com/s/1y3db5GZFPZSnyYOCrKQcmQ
提取码:92gt
下载下来后是几个拆分好的压缩包, 如下所示:
kevin@kevin-virtual-machine:~/orange-build$ ls
orangepi-build-ok.tar.gz_00 orangepi-build-ok.tar.gz_01 orangepi-buildok.tar.gz_02
这个时候可以用如下的命令进行合并解压:
cat orangepi-build-ok.tar.gz_0* > orangepi-build-ok.tar.gz
tar -xvf orangepi-build-ok.tar.gz
1.3 首次编译完整SDK
下载完源码后, 即可用build.sh进行首次编译.(注:如果是从6.1.2节 方法二:从百度网盘下载后, 由
于已经缓存了交叉编译工具链、uboot和内核源码, 可以不运行build.sh脚本 )
1.4.执行编译
1.运行 build.sh 脚本,记得加 sudo 权限
sudo ./build.sh
2.选择Full OS image for flashing 进行完整镜像的编译

3.选择不修改配置

4.根据实际的香橙派派开发版的型号, 选orangepizero2

- 选择根文件系统类型, 这边选择ubuntu 22.04 的根文件系统, 也就是jammy:

6.选择带桌面环境,即接入HDMI显示器后,是有桌面显示的:

7.最后选择桌面环境,这边选择xfce:


- 这里的软件主要是一些额外第三方软件包的安装, 都不选择,直接ok开始编译
![]()
9.如果是第一次运行 orangepi-build 中的 build.sh 脚本时会自动下载交叉编译工具链、 u-boot 和
linux 内核源码,成功编译完一次 linux 镜像后在 orangepi-build 中可以看到 的文件和文件夹有:
- a. build.sh: 编译启动脚本
- b. external: 包含编译镜像需要用的配置文件、特定功能的脚本以及部分程序 的源码,编译镜像过程中缓存的 rootfs 压缩包也存放在 external 中
- c. kernel: 存放 linux 内核的源码,内核源码的文件夹的名字请不要手动修改,如 果修改了,编译系统运行时会重新下载内核源码
- d. LICENSE: GPL 2 许可证文件
- e. README.md: orangepi-build 说明文件
- f. output: 存放编译生成的 u-boot、linux 等 deb 包、编译日志以及编译生成的 镜像等文件
- g. scripts: 编译 linux 镜像的通用脚本
- h. toolchains: 存放交叉编译工具链
- i. u-boot: 存放 u-boot 的源码,u-boot 源码的文件夹的名字请不要手动修改,如果修改了,编译系统运行时会重新下载 u-boot 源码
- j. userpatches: 存放编译脚本需要用到的配置文件。
10.经过漫长等待编译完成后, 会在
orangepi-build/output/images/Orangepizero2_3.1.0_ubuntu_jammy_desktop_xfce_linux5.16.17/
下Orangepizero2_3.1.0_ubuntu_jammy_desktop_xfce_linux5.16.17.img镜像。 可以直接拿这个
img 烧入到SD卡中运行
2.交叉编译工具链配置
2.1.关于编译
编译是指将源代码文件(如C/C++文件)经过预处理、编译、汇编和链接等步骤,转换为可执行文件的过
程。将源代码转换成机器代码的过程称为编译(Compile),编译的工作需要编译器(Complier)来完
成。
2.2.本地编译
本地编译是指在当前的编译平台上,生成能在当前平台上运行的可执行文件。例如,在x86平台上,使用
x86平台上的工具,开发针对x86平台本身的可执行程序,这个编译过程称为本地编译。
以一个简单的例子来说明本地编译,假设有一个hello.c文件,它包含以下内容:
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
return 0;
}
我们想要在x86平台上进行本地编译,并在x86平台上运行这个程序。可以使用以下命令:
gcc -o hello hello.c
运行:
./hello
输出结果为:
Hello, world!
2.3.交叉编译
交叉编译是指在当前的编译平台上,生成能在体系结构不同的另一种目标平台上运行的可执行文件。例
如,在x86平台上,使用针对ARM平台的工具,开发针对ARM平台的可执行程序,这个编译过程称为交
叉编译。
以一个简单的例子来说明本地编译,假设有一个hello.c文件,它包含以下内容:
#include <stdio.h>
int main()
{
printf("Hello, world!\n");
return 0;
}
想要在x86平台上进行交叉编译,并在ARM平台上运行这个程序。首先需要在家目录下的.bashrc最后配
置添加交叉编译工具链:
kevin@kevin-virtual-machine:~$ vi .bashrc
最后面添加
export PATH=$PATH:/home/$(whoami)/orangepi-build/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
然后断开重连桌重新登陆后, 执行export指令,即可看到最新导入的PATH环境变量
kevin@kevin-virtual-machine:~$ export
同时执行aarch64-none-linux-gnu-gcc --version可以看到对应的版本号:
kevin@kevin-virtual-machine:~$ aarch64-none-linux-gnu-gcc --version
aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
在x86平台上进行交叉编译,可以使用以下命令:
aarch64-none-linux-gnu-gcc -o hello hello.c
利用file命令可以看到编译出来的程序是ARM aarch64的二进制程序:
kevin@kevin-virtual-machine:~$ file hello
hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, with debug_info, not stripped
这时候需要将该文件拷贝到比如香橙派等ARM开发板上运行, 在X86宿主机上是无法正常运行的。
scp hello orangepi@192.168.4.129:/home/orangepi
3.Makefile的入门
3.1.编译工具及构建工具介绍
在之前的课程,都是直接使用gcc对代码进行编译,这简单的工程是可以的,但当我们遇到复杂的工程
时,每次用gcc等编译工具去操作就会显得很低效。因此make工具就出现了, make的出现是为了解决手
动编译和链接大型工程的问题,它可以避免重复的工作,提高效率,保证正确性。make工具就根据
makefile中的命令进行编译和链接的。但是当工程非常大的时候,手写makefile也是非常麻烦的,如果
换了个平台makefile又要重新修改,因此更高级的一些构建系统或者工具工具像cmake、qmake、ninja
和auto make就出现了,它们可以根据一些配置文件来自动化编译和链接软件项目。

cmake是一个跨平台的构建系统,它可以根据CMakeLists.txt中的指令来生成不同平台和工具的工程文
件,例如Makefile、Visual Studio解决方案、Ninja文件等。cmake可以支持多种语言和多种架构,它还
提供了一些高级功能,如测试、打包、安装等。
qmake是一个用于Qt项目的构建系统,它可以根据.pro或.pri中的指令来生成Makefile或其他形式的工程
文件。
ninja是一个小巧而快速的构建工具,它可以根据ninja.build中的规则来执行编译和链接命令。ninja主要
关注于性能和效率,它可以利用多核处理器和并行处理来加速构建过程。ninja通常不需要用户直接编写
配置文件,而是由其他构建系统(如cmake)来生成
auto make是一个用于生成Makefile.in文件的工具,Makefile.in是一种用于auto conf的配置文件格式,
auto conf是一个用于生成configure脚本的工具。configure脚本是一个用于检测系统环境并生成最终的
Makefile文件的脚本Makefile.am是一种用于auto make的配置文件格式,它包含了一些指令和变量,用
于定义程序或库的源文件、目标文件、依赖关系和编译选项等。
make是一个经典而通用的构建工具,它可以根据Makefile中的规则来执行编译和链接命令。make可以
支持多种平台和工具,它还提供了一些高级功能,如条件判断、函数调用、模式匹配。
3.2 Makefile的简单讲解
3.2.1.编译的四个阶段
回顾下编译的四个过程:预处理(Pre-Processing)、编译(Compiling)、汇编 (Assembliang)、链接
(Linking)

3.2.1.Makefile的规则
a.基本规则
target ... : prerequisites ...
<tab缩进>command
<tab缩进>...
<tab缩进>...
target 也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签( Label),
对于标签这种特性,在后续的讲“伪目标”中会有叙述。prerequisites 就是,要生成那个 target 所需要的
文件或是目标。command 也就是 make 需要执行的任意shell命令。
Makefile一个示例:
debug:
@echo "hello world"
如果,我们要编译下面这个最简单的例子:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello world!\n");
return 0;
}
Makefile修改如下:
debug:
@echo "hello world"
test:
gcc -o test test.c
执行命令make test 可以生成 test文件, 执行make debug可以输出“hello world”:
kevin@kevin-virtual-machine:~/makefileCode$ make debug
hello world!
kevin@kevin-virtual-machine:~/makefileCode$ ls
makefile test.c
kevin@kevin-virtual-machine:~/makefileCode$ make test
gcc -o test test.c
kevin@kevin-virtual-machine:~/makefileCode$ ls
makefile test test.c
b.伪目标
如果一个目标和一个实际文件同名,那么make会认为该目标已经是最新的,不需要重新生成,也不会执
行其命令。通过将目标声明为伪目标,可以避免这种情况,强制执行其命令。
debug:
@echo "hello world!"
test:
gcc -o test test.c
.PHONY: test
c.变量赋值和预定义变量
Makefile中的变量赋值运算符有四种,分别是=、:=、?=和+=, $符号表示取变量的值,当变量名多于一
个字符时,使用"( )":
= 表示延迟展开赋值,即变量的值是在使用时才确定,可能会受到后面的赋值影响。例如,VAR_A = A,
VAR_B = $(VAR_A) B,VAR_A = AA,那么最后VAR_B的值是AA B,而不是A B。
:= 表示直接赋值,即变量的值是在定义时就确定,不会受到后面的赋值影响。例如,VAR_A := A,
VAR_B := $(VAR_A) B,VAR_A := AA,那么最后VAR_B的值是A B,而不是AA B。
?=表示条件赋值,即只有当变量没有被赋值时,才使用等号后面的值作为变量的值。例如,VAR ?=
new_value,如果VAR在之前没有被赋值,那么VAR的值就为new_value,否则保持原来的值不变。
+= 表示追加赋值,即将等号后面的值追加到变量原来的值之后,形成一个新的值。例如,VAR +=
new_value,如果VAR在之前没有被赋值,那么VAR的值就为new_value,如果VAR在之前被赋值为
old_value,那么VAR的值就为old_value new_value
$符的其他用法:
$^ 表示所有的依赖文件
$@ 表示生成的目标文件
$< 代表第一个依赖文件
d.注释和换行符
采用#进行一行注释
采用\作为续行符
e.变量的替换引用
语法格式是:
$(var:a=b)或${var:a=b}
表示把变量var的值中的a后缀替换成b后缀。例如:
src := a.c b.c c.c
obj := $(src:c=o)
把变量src的值中的.c后缀替换成.o后缀,赋值给变量obj,结果是:
obj := a.o b.o c.o
举例:
# 这是一个Makefile的注释
TARGET = hello #TARGET延迟赋值hello
CC := gcc #CC立即赋值gcc
CC += -g #CC追加赋值-g, gcc -g表示添加调试信息,可用于gdb的调试
SRC = hello.c
OBJ = $(SRC:.c=.o) #变量的替换引用,把hello.c的.c替换成.o
debug :
@echo "hello world"
echo $(SRC)
echo $(OBJ)
$(TARGET): $(SRC)
$(CC) -o $@ $<
# $(CC) -o ${TARGET} hello.c
compile: $(TARGET)
clean:
@rm hello hello.o -r
.PHONY: clean compile
f.常见函数
Makefile函数的基本格式是:$( )或者是${ },其中,是函数名,是函数的参数,参数之间要用逗号分隔
开,参数和函数名之间使用空格分开。调用函数的时候要使用字符“$”,后面可以跟小括号或者大括号。
1) wildcard 通配符:
Makefile中的wildcard 是一个函数,用于扩展通配符,返回与通配符匹配的文件列表。通配符是一种特
殊的字符,可以表示多个文件名或目录名,常见的通配符有 * 和 ?,分别表示任意长度的任意字符和单个
任意字符。格式如下:
$(wildcard argments)
比如*.c 表示所有以 .c 结尾的文件名,a?.txt 表示所有以 a 开头,中间有一个任意字符,以 .txt 结尾的文
件名。例如:
SRC = $(wildcard src/*.c)
表示查找并返回src目录下所有的.c文件, *表示通配符, 匹配一个或者多个任意字符
2)shell:
$(shell <cmd> <args>)
cmd: 执行命令名称
args:参数列表
返回值: 返回命令执行结果
例如:
SRC = $(shell find . -name *.c)
表示查找当前目录及子目录下的所有.c文件结尾的代码源文件
3) patsubst替换函数:
$(patsubst pattern,replacement,text)
pattern: 是一个包含通配符 % 的模式,表示匹配任意长度的任意字符
replacement: 是一个替换字符串,也可以包含 %,表示用 pattern 中匹配的字符替换。
text: 是一个要处理的文本,可以包含多个以空格分隔的单词。
返回值:patsubst 函数会在 text 中找到所有符合 pattern 的单词,并用 replacement 替换它们,然后
返回替换后的文本。
例如,如果有一个变量 src,它的值是:
src = a.c b.c c.c
想把它的值中的所有 .c 后缀替换成 .o 后缀,可以这样写:
obj = $(patsubst %.c,%.o,$(src))
这样,obj 的值就是:
obj = a.o b.o c.o
4) subst替换函数
$(subst from,to,text)
from: 是要被替换的字符或单词
to: 是替换后的字符或单词
text: 是要处理的字符串。
返回值:subst 函数会在 text 中找到所有的 from,并用 to 替换它们,然后返回替换后的字符串。
例如
$(subst ee,EE,feet on the street)
返回:
fEEt on the strEEt
综合举例,测试工程代码目录:
test@test:~/makefiletest$ tree
.
├── Makefile
└── src
└── test.c
Makefile内容:
CC = gcc
CC += -g
SRC := $(shell find . -name *.c)
TARGET := $(patsubst %.c, %,$(subst src,obj, $(SRC)))
debug:
@echo "hello world"
echo $(SRC)
echo $(TARGET)
$(TARGET): $(SRC)
mkdir -p obj
$(CC) -o $@ $<
compile: $(TARGET)
clean:
@rm obj -r
.PHONY: clean compile
test.c内容:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
执行:
make compile
生成obj/test:
pg@pg-Default-string:~/makefiletest$ tree -a
.
├── Makefile
├── obj
│ └── test
└── src
└── test.c
5)dir函数:
$(dir NAMES...)
dir 函数是一个用于从文件名序列中提取目录部分的函数
优化Makefile内容:
CC = gcc
CC += -g
SRC := $(shell find . -name *.c)
TARGET := $(patsubst %.c, %,$(subst src,obj, $(SRC)))
debug:
@echo "hello world"
echo $(SRC)
echo $(TARGET)
$(TARGET): $(SRC)
mkdir -p $(dir $(TARGET))
$(CC) -o $@ $<
compile: $(TARGET)
clean:
@rm $(dir $(TARGET)) -r
.PHONY: clean compile
6)suffix函数
$(suffix <names...>)
功能:从文件名序列中取出各个文件名的后缀。
返回值:返回文件名序列的后缀序列,如果文件没有后缀,则返回空字串。
例如:
$(suffix src/foo.c src-1.0/bar.c hacks)
返回:
.c .c
7)basename函数
格式:
$(basename <names...>)
功能:从文件名序列中取出各个文件名的前缀部分。
返回值:返回文件名序列的前缀序列,如果文件没有前缀,则返回空字串。
例如:
$(basename src/foo.c src-1.0/bar.c hacks)
返回:
src/foo src-1.0/bar hacks
8) addsuffix函数
$(addsuffix <suffix>,<names...>)
功能:把后缀加到中的每个单词后面。
返回:返回加过后缀的文件名序列。
例如:
$(addsuffix .c,foo bar)
返回值:
foo.c bar.c
9)addprefix函数
功能:把前缀加到中的每个单词后面。
返回值:返回加过前缀的文件名序列。
例如:
$(addprefix src/,foo bar)
返回值:
src/foo src/bar
10)foreach函数
$(foreach <var>,<list>,<text>)
把list中使用空格分割的单词依次取出并赋值给变量var, 然后执行text表达式
例如:
files := foo bar baz
files-with-c := $(foreach file,$(files),$(file).c)
11)条件判断语言
Makefile条件判断有下面几种:
ifeq/ifneq语句:
ifeq语句 : 判断参数 是否相等,相等为 true, 否则是 false.
ifeq (arg1, arg2)
#arg1 arg2 相等执行这里的语句
else
#arg1 arg2 不相等执行这里的语句
endif
ifneq语句:判断参数 是否不等,不等为 true, 否则为 false.
ifneq (arg1, arg2)
#arg1 arg2 不相等执行这里的语句
else
#arg1 arg2 相等执行这里的语句
endif
ifdef/ifndef语句
ifdef 语句: 判断参数 是否有值 ,有值为 true, 否则是 false
ifndef : 判断参数 是否没有值 ,没有值为 true, 否则为 false.
ifdef:
ifdef var
#如果定义了var,执行这里的内容
else
#如果没定义var,执行这里的内容
endif
ifndef:
infdef var
#如果没定义var,执行这里的内容
else
#如果定义var,执行这里的内容
endif
4.交叉编译wiringOP库
在之前《3.1 wiringPi外设SDK安装》里,我们是直接在香橙派里直接编译的wiringOP库,这一节讲解利
用《6.2交叉编译工具链配置》配置出来的交叉编译工具编译一直wiringOP库。
安装wiringOP库
cd ~
git clone https://github.com/orangepi-xunlong/wiringOP -b master #下载源码
cd wiringOP #进入文件夹
4.1.修改build脚本,在echo "WiringPi Library" 之前添加:
修改wiringOP库,编译出RAM上运行格式的外设
vi build
mkdir $PWD/_INSTALL/usr/local/bin -p
mkdir $PWD/_INSTALL/usr/local/include -p
mkdir $PWD/_INSTALL/usr/local/lib -p
4.2.所有的修改Makefile
通过vscode去查找替换
devLib/Makefile
examples/Makefile
examples/Gertboard/Makefile
examples/PiFace/Makefile
examples/PiGlow/Makefile
examples/q2w/Makefile
examples/scrollPhat/Makefile
gpio/Makefile
wiringPi/Makefile
wiringPiD/Makefile
将所有Makefile中的CC = gcc 改成 CC = aarch64-none-linux-gnu-gcc
4.3.修改devLib/Makefile、gpio/Makefile、wiringPiD/Makefile 、wiringPi/Makefile
修改DESTDIR?=/usr 替换为DESTDIR?= $(shell pwd)/../_INSTALL/usr
$(shell pwd)是指makefile的当前目录
4.4.更正文件路径
- 修改wiringPi/Makefile
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so
修改成
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPi.so
- 修改devLib/Makefile
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPiDev.so.$(VERSION) $(DESTDIR)/lib/libwiringPiDev.so
修改成:
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPiDev.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPiDev.so
4.5.devLib/Makefile
INCLUDE = -I. 修改为INCLUDE = -I. -I$(DESTDIR)$(PREFIX)/include
4.6.编译
./build
然后输入26(选择板子为修改DESTDIR?=/usr 替换为orangepizero2)
这时候,就会wiringOP-master下生成_INSTALL目录,里面有完整编译出来的库文件和头文件
kevin@kevin-virtual-machine:~/wiringOP/_INSTALL$ tree -a
.
└── usr
└── local
├── bin
│ └── gpio
├── include
│ ├── ads1115.h
│ ├── bmp180.h
│ ├── drcNet.h
│ ├── drcSerial.h
│ ├── ds1302.h
│ ├── ds18b20.h
│ ├── font.h
│ ├── gertboard.h
│ ├── htu21d.h
│ ├── lcd128x64.h
│ ├── lcd.h
│ ├── max31855.h
│ ├── max5322.h
│ ├── maxdetect.h
│ ├── mcp23008.h
│ ├── mcp23016.h
│ ├── mcp23016reg.h
│ ├── mcp23017.h
│ ├── mcp23s08.h
│ ├── mcp23s17.h
│ ├── mcp23x0817.h
│ ├── mcp23x08.h
│ ├── mcp3002.h
│ ├── mcp3004.h
│ ├── mcp3422.h
│ ├── mcp4802.h
│ ├── oled.h
│ ├── OrangePi.h
│ ├── pcf8574.h
│ ├── pcf8591.h
│ ├── piFace.h
│ ├── piGlow.h
│ ├── piNes.h
│ ├── pseudoPins.h
│ ├── rht03.h
│ ├── scrollPhat.h
│ ├── sn3218.h
│ ├── softPwm.h
│ ├── softServo.h
│ ├── softTone.h
│ ├── sr595.h
│ ├── w25q64.h
│ ├── wiringPi.h
│ ├── wiringPiI2C.h
│ ├── wiringPiSPI.h
│ ├── wiringSerial.h
│ ├── wiringShift.h
│ └── wpiExtensions.h
├── lib
│ ├── libwiringPiDev.so -> /home/kevin/wiringOP/devLib/../_INSTALL/usr/local/lib/libwiringPiDev.so.2.46
│ ├── libwiringPiDev.so.2.46
│ ├── libwiringPi.so -> /home/kevin/wiringOP/wiringPi/../_INSTALL/usr/local/lib/libwiringPi.so.2.46
│ └── libwiringPi.so.2.46
└── share
└── man
└── man1
└── gpio.1
后面我们就可以把_INSTALL里的内容拷贝到香橙派的根目录下,然后执行
重写依赖
scp -r ~/wiringOP/_INSTALL orangepi@192.168.4.129:/home/orangepi
sudo ldconfig
就可以使用该库了,可以使用
sudo gpio readall
测试库是否链接正常。
5.交叉编译智能垃圾分类工程代码
原有的目录结构
kevin@kevin-virtual-machine:~/garbage$ tree
.
├── garbage.c
├── garbage.h
├── garbage.py
├── main.c
├── myoled.c
├── myoled.h
├── pwm.c
├── pwm.h
├── socket.c
├── socket.h
├── uartTool.c
└── uartTool.h
调整后的目录结构
kevin@kevin-virtual-machine:~/garbage$ tree
.
├── inc
│ ├── garbage.h
│ ├── myoled.h
│ ├── pwm.h
│ ├── socket.h
│ └── uartTool.h
└── src
├── garbage.c
├── garbage.py
├── main.c
├── myoled.c
├── pwm.c
├── socket.c
└── uartTool.c
将_INSTALL拷贝到项目3rd下
cp -r ~/wiringOP/_INSTALL/* ~/garbage/3rd/
增加3rd目录,用于存放wiringOP和python3.10等第三方依赖库和头文件。需增加如下几个依赖库.
首先,从香橙派上利用apt download下载依赖包的头文件和库文件,并拷贝到宿主机里:
sudo apt update
sudo apt download zlib1g zlib1g-dev libpython3.10 libpython3.10-dev libexpat1 libexpat1-dev libcrypt1 libcrypt-dev
scp *.deb kevin@192.168.4.120:/home/kevin #kevin为宿主机用户名, 192.168.4.120为宿主机ip
然后,利用dpkg -x命令解压deb文件到garbage/3rd目录下:
dpkg -x libpython3.10_3.10.12-1~22.04.9_arm64.deb garbage/3rd
dpkg -x libpython3.10-dev_3.10.12-1~22.04.9_arm64.deb garbage/3rd/
dpkg -x libexpat1_2.4.7-1ubuntu0.6_arm64.deb garbage/3rd/
dpkg -x libexpat1-dev_2.4.7-1ubuntu0.6_arm64.deb garbage/3rd/
dpkg -x libcrypt1_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x libcrypt-dev_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x zlib1g_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
dpkg -x zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
因为默认提供的aarch64-none-linux-gnu-gcc 9.2.0的版本编译是, 如果去加载上面的依赖库是, 会出
现库版本的依赖问题, 因此。 宿主机安装aarch64-linux-gnu-gc 11.2版本并使用该交叉编译工具:
sudo apt install gcc-aarch64-linux-gnu
香橙派主机查询软链:
ls -l /lib/aarch64-linux-gnu/libz*
编译主机手动创建软链:
cd /home/kevin/garbage/3rd/lib/aarch64-linux-gnu
ln -s libcrypt.so.1.1.0 libcrypt.so
ln -s libexpat.so.1.8.7 libexpat.so
ln -s libz.so.1.2.11 libz.so
Makefile 文件内容如下:
cc := aarch64-linux-gnu-gcc
SRC := $(shell find src -name "*.c")
INC := ./inc \
./3rd/usr/include \
./3rd/usr/include/python3.10 \
./3rd/usr/include/aarch64-linux-gnu \
./3rd/usr/include/aarch64-linux-gnu/python3.10 \
OBJ := $(subst src/,obj/,$(SRC:.c=.o))
TARGET = obj/garbage
CFLAGS := $(foreach item,$(INC),-I$(item)) #-I./3rd/usr/include
LIBS_PAHT := ./3rd/lib/aarch64-linux-gnu \
./3rd/usr/lib/aarch64-linux-gnu \
./3rd/usr/lib/python3.10
LDFLAGS := $(foreach item,$(LIBS_PAHT),-L$(item)) #-L./3rd/usr/local/lib
LIBS := -lwiringPi -lpython3.10 -lpthread -lexpat -lz -lcrypt
obj/%.o:src/%.c
mkdir -p obj
$(CC) -o $@ -c $< $(CFLAGS)
$(TARGET) :$(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
compile : $(TARGET)
clean :
rm $(TARGET) obj $(OBJ) -rf
debug:
echo $(CC)
echo $(SRC)
echo $(INC)
echo $(OBJ)
echo $(TARGET)
echo $(CFLAGS)
echo $(LDFLAGS)
echo $(LIBS)
.PHONY clean compile debug
就会在obj目录下生成garbage文件, 将该文件拷贝到香橙派里即可执行
scp /home/kevin/garbage/obj/garbage orangepi@192.168.4.129:/home/orangepi
scp /home/kevin/garbage/src/garbage.py orangepi@192.168.4.129:/home/orangepi


浙公网安备 33010602011771号