1、交叉编译(Cross Compile)是什么?为什么要交叉编译?
交叉编译是在一个平台上生成另一个平台上的可执行代码。
我们在Windows上面编写C51代码,并编译成可执行代码,如xxx.hex,是在C51上面运行,不是Windows上运行
我们在Ubuntu 上面编写树莓派的代码,并编译成可执行代码,如a.out,是在树莓派上运行,不是在Ubuntu Linux上面运行
编译:是在一个平台生成该平台上的可执行代码。
Stm32、C51:交叉编译的发生在keil(集成环境上面)
为什么要交叉编译:
平台上不允许或不能安装我们所需要的编译器比如C51
1、因为目的平台上的资源匮乏,无法运行我们所需要编译器
2、树莓派是不是就不需要交叉编译器?
错,也要。
树莓派有时因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。操作系统也是代码,也要把编译!
平台运行至少需要两样东西:bootloader(启动引导代码) 以及 操作系统核心。
宿主机(host):编辑和编译程序的平台,一般基于X86的PC机,通常也被称为主机。
目标机(target):用户开发的系统,通常都是非X86平台。host编译得到的可执行代码在target上运行。
交叉编译需要用到什么工具?
交叉编译器、交叉编译工具链
2、交叉编译工具链的安装
https://github.com/raspberrypi
下载tools-master.zip安装包
将tools-master.zip从共享文件夹拷贝到工作目录/home/Ubuntu的lessonPi文件夹
cp /mnt/hgfs/share/tool-master.zip ~/lessonPi
解压tools-master.zip安装包
unzip tools-master.zip
进入交叉编译工具链所在的文件夹
cd /home/Ubuntu/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
echo $PATH 获取当前环境变量的值
ls指令查看当前文件夹所有文件
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/
toolschain/4.5.1/bin
arm-linux-gnueabihf-gcc为交叉编译命令软链接
2.1临时有效,配置环境变量
PATH 环境变量
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/
toolschain/4.5.1/bin:/home/Ubuntu/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueab
ihf-raspbian-x64/bin
2.2永久有效,配置环境变量
修改工作目录下的./bashrc隐藏文件,配置命令终端
vi ~/.bashrc
在文件最后一行加入:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/
toolschain/4.5.1/bin:/home/Ubuntu/lessonPi/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueab
ihf-raspbian-x64/bin
source ~/.bashrc 加载配置文件,马上生效配置
3、交叉编译服务端客户端
检查交叉编译工具版本对不对
arm-linux-gnueabihf-gcc -v
版本:4.8.3
gcc test.c -o MainPro 使用gcc命令编译
file MainPro 查看文件信息
MainPro: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xdef830dfa0d7056b71d98591c407880070eb0e36, not stripped
MainPro可执行文件只能在x86 64位平台上运行
arm-linux-gnueabihf-gcc test.c -o MainPro 使用arm-linux-gnueabihf-gcc命令交叉编译
file MainPro 查看文件信息
MainPro: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xd107fecdc401c737afa4f9c312ad361ab7f9d151, not stripped
MainPro可执行文件只能在ARM平台上运行,如果在x86 64位平台上运行的话,会发生以下错误。
bash: ./MainPro: cannot execute binary file
如何把编译生成的可执行文件下载到树莓派开发板:
scp clientInPi [email protected]:/home/pi
指令 文件名 开发板用户名@开发板ip地址:开发板的绝对路径
//将MainPro文件传到树莓派/home/pi/Desktop/crocom文件夹中
scp MainPro [email protected]:/home/pi/Desktop/crocom
pi@raspberrypi:~/Desktop/crocom $ ./MainPro
hello linux!
pi@raspberrypi:~/Desktop/crocom $ file MainPro
MainPro: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.26, BuildID[sha1]=cdfe07d137c701c4c3f9a4af1a36ad1251d1f9b7, not stripped
因为树莓派是基于ARM平台,所以MainPro在树莓派上是可以运行的。
4、软连接与硬链接
软链接:
概念:
1、软链接文件有类似于Windows系统的快捷方式
2、在符号连接中,文件实际上是一个文本文件,其中包含的有另一个文件的位置信息
3、你选定的位置上生成一个文件的镜像,不会占用磁盘空间
如何生成:
ln -s libwiringPi.so.2.50 libwiringPi.so
指令 参数 要被链接的文件 软链接文件名字
硬链接
ln libwiringPi.so.2.50 libwiringPi.so
它会在你选定的位置上生成一个和源文件大小相同的文件
源文件被删除时,软链接就不能用了,而硬链接还保存着源文件数据块。如果存在多个硬链接时,直到删除掉最后一个硬链接时,源文件数据块及目录的连接才被释放。
5、带wiringPi库的交叉编译如何进行?
首先,要注意的是链接库的格式对不对,是不是树莓派(目标机)的平台。
我们可以从树莓派上拷贝wiringPi库到Linux系统上。
在/usr/lib找到wiringPi库,文件名为libwiringPi.so.2.50
注意的是不能拷贝libwiringPi.so,它是软链接,不是源文件。
拷贝 libwiringPi.so.2.50
scp libwiringPi.so.2.50 [email protected]:/home/Ubuntu/learn/crocom
拷贝超声波检测距离程序文件:demo.c
scp demo.c [email protected]:/home/Ubuntu/learn/crocom
拷贝wiringPi.h
scp wiringPi.h [email protected]:/home/Ubuntu/learn/crocom
当前路径的所有文件,缺一不可
Ubuntu@Embed_Learn:~/learn/crocom$ ls
demo4.c libwiringPi.so libwiringPi.so.2.50 MainPro wiringPi.h
交叉编译
arm-linux-gnueabihf-gcc demo4.c -lwiringPi -L . -o MainPro
将编译好的文件MainPro拷贝到树莓派
scp MainPro [email protected]:/home/pi/Desktop/crocom
执行MainPro
./MainPro
pi@raspberrypi:~/Desktop/crocom $ ./MainPro
distance = 3.94 cm
distance = 4.01 cm
distance = 4.13 cm
distance = 9.76 cm
distance = 12.26 cm
distance = 29.95 cm
distance = 6.14 cm
distance = 25.08 cm
MainPro在树莓派上是可以正常运行的
文件demo.c
#include "wiringPi.h"
#include
#include
#define Trig 4
#define Echo 5
#define Bee 7
void ultraInit(void)
{
pinMode(Echo, INPUT);
pinMode(Trig, OUTPUT);
pinMode(Bee,OUTPUT);
}
float disMeasure(void)
{
struct timeval tv1; //timeval是time.h中的预定义结构体 其中包含两个一个是秒>,一个是微秒
/*
struct timeval
{
time_t tv_sec; //Seconds.
suseconds_t tv_usec; //Microseconds.
};
*/
struct timeval tv2;
long start, stop;
float dis;
digitalWrite(Trig, LOW);
delayMicroseconds(2);
digitalWrite(Trig, HIGH);
delayMicroseconds(10); //发出超声波脉冲
digitalWrite(Trig, LOW);
while(!(digitalRead(Echo) == 1));
gettimeofday(&tv1, NULL); //获取当前时间 开始接收到返回信号的时候
while(!(digitalRead(Echo) == 0));
gettimeofday(&tv2, NULL); //获取当前时间 最后接收到返回信号的时>候
/*
int gettimeofday(struct timeval *tv, struct timezone *tz);
The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone.
The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL.
*/
start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间
stop = tv2.tv_sec * 1000000 + tv2.tv_usec;
dis = (float)(stop - start) / 1000000 * 34000 / 2; //计算时间差求出距离
return dis;
}
int main(void)
{
float dis;
if(wiringPiSetup() == -1){
//如果初始化失败,就输出错误信息 程序初始化时务>必进行
printf("setup wiringPi failed !");
return -1;
}
ultraInit();
digitalWrite(Bee,HIGH);
while(1){
dis = disMeasure();
printf("distance = %0.2f cm\n",dis);
if(dis<10)
{
digitalWrite(Bee,LOW);
}
else
{
digitalWrite(Bee,HIGH);
}
delay(1000);
}
return 0;
}