在学习嵌入式Linux开发之前,我们首先需要做一些准备工作,搭建硬件、软件开发环境。
一、硬件环境搭建
1.1 交叉开发模式
在开发PC机程序时,可以直接在PC机上编辑、编译、调试软件,最终发布的软件也可以在PC机运行。而对于嵌入式开发,最初的嵌入式设备是一个空白的系统,需要通过主机为它构建基本的软件系统,并烧写到设备中。另外,嵌入式设备的资源并不足以用来开发软件。所以需要用到交叉开发模式:在主机上编辑、编译软件,然后在目标机上运行、验证程序。
1.2 硬件要求
首先我们需要有一个PC主机、目前的PC机基本都可以满足我们的开发要求,就不做过多的介绍。
其次我们需要有一块开发板。目前市面上的开发板有很多,这里我们就以友善之臂Mini2440开发板为例,主要是因为我们还处于学习阶段,而这款芯片毕竟经典,网上资料也很多,方便我们学习。
二、软件环境搭建
2.1 VMware安装
双击VMware-workstation-full-15.0.0-10134415.exe运行安装,点击下一步:
勾选我接受许可协议中的条款,点击下一步:
点击更改选择软件安装路径,点击下一步:
选择需要安装的快捷方式,点击下一步:
点击安装按钮开始安装:
完成中,安装完成后点击许可证按钮:
2.2 ubuntu安装
嵌入式linux开发以及深度学习开发一般使用ubuntu居多,而centos一般作为web服务器使用。本节以ubuntu20.04.2.0安装为例,下载地址http://mirrors.163.com/ubuntu-releases/。
(1) 打开WMware,在vmware主界面的“主页”标签点击创建虚拟机向导。如下图所示。
(2) 向导界面选择“自定义高级”,如下图所示:
(3) 然后下一步,兼容性选择当前vmware版本,比如本人是15版就选择15版。如果要分发虚拟机给别人使用,就选择别人的版本。如下所示。
(4) 下一步,选择稍后安装操作系统,如下所示
(5) 选择客户机操作系统:
(6) 下一步,虚拟机名称可以随便取。“位置”就是将来虚拟机文件所在的目录,因为虚拟机文件比较大,要选择一个磁盘空间比较大的目录
(7) 下一步,设置要分配给虚拟机的CPU,电脑配置高的可以往上调,如果要同时运行两个以上虚拟机就少分配一点,一般采用默认值就可以:
(8) 下一步,Ubuntu内存配置:
(9)、网络配置,采用桥接网络:
(10) 硬盘控制器,没有特殊情况就选默认值:
(11) 硬盘类型,没有特殊情况就选默认值:
(12) 创一个新的磁盘,如果使用单独物理磁盘的选第三项:
(13) 磁盘空间,一般默认20G就够了,如果要装的软件特别多就多分配一点,一般空的Ubuntu16装完占用10G左右,剩10G软件空间:
(14)、磁盘文件名,没有什么影响随便去一个就好了
(15) 到这一步就创建完一个虚拟机了,如下。如果对刚才的配置不满意可以点“自定义”进一步修改:
(16) 在启动虚拟机前进行虚拟机设置:
要在这里选择你的iso文件。然后启动操作系统,开始真正的系统安装。
(16) 语言选择简体中文,点击安装ubuntu:
(17) 点击继续:
(18) 然后选择清除整个磁盘并安装ubuntu:
(19) 点击继续:
(19) 设置登录密码为123456:
等待完成之后重启就行了!!!
三、ubuntu配置
3.1 修改root密码
修改root密码(123456aa):
sudo passwd root
sudo 它允许系统管理员分配给普通用户一些合理的权力,让他们执行一些只有超级用户或者其他特权用户才能完成的任务。比如 mount、halt、su,useradd等命令,sudo权限分配是通过文件/etc/sudoers配置的。
我们每次重启系统只能通过zhengyang账号登录,如果想使用root用户登录系统,参考Ubuntu18.04中设置使用root用户登录图形界面。
3.2 网络设置
WMware网络设置支持三种模式:
- bridged(桥接模式):虚拟机能得到一个独立IP地址,网络能提供多个IP地址;虚拟机可以访问外部网络,外部网络也可以访问虚拟机
- NAT(网络地址转换模式) : 如果网络中只提供一个IP地址,虚拟机和主机使用一个IP地址;虚拟机可以外部网络,但是外部网络访问不了虚拟机
- 主机模式 (主机没有联网):相当于把主机和虚拟机通过一根网线连接在一起;
之前我们在安装ubuntu的时候选择了桥接模式。我们需要设置ubuntu和主机在同一网段内。由于我的windows操作系统的IP为192.168.0.101:
查看ubuntu的网络配置:
可以看到,本例中的网卡为“ens33”,同时可以看到相应的IP信息等。
不同的linux系统,网卡配置文件是不同的,这里ubuntu的网卡配置文件是/etc/network/interfaces:
我们首先安装vim:
sudo apt install vim
输入下面命令进行编辑网卡文件:
sudo vim /etc/network/interfaces
默认的文件内容如下:
auto lo
iface lo inet loopback
修改内容如下:下面的ens33需要改成自己的网卡名称。ip地址,掩码网关自己合理配置就行了。记得wq!保存退出:
auto ens33
iface ens33 inet static
address 192.168.0.200
netmask 255.255.255.0
gateway 192.168.0.1
配置DNS,在终端输入命令:
sudo vim /etc/resolv.conf
在其中添加192.168.1.1这个和物理机要保持一致:
nameserver 192.168.1.1
然后重启ubuntu服务器,运行ifconfig可以看到ip地址已经改为192.168.0.200:
3.3 SSH服务搭建
安装ssh-server服务,用于ssh工具远程连接:
sudo apt-get install openssh-server
查看ssh是否已经启动:
ps -ef | grep ssh
我们通过ssh工具连接ubuntu服务器,如果发现连接不上的话。在ubuntu终端下,切换到root用户:
su root
vim /etc/ssh/sshd_config
进入该文件,找到PermitRootLogin prohibit-password那一行进行注释掉(有的时候默认是注释掉的),并在下面添加一行
PermitRootLogin yes
保存后,重启ssh服务:
service ssh restart
再次通过ssh工具连接,我们就可以连接成功了:
3.4 FTP服务搭建
FTP是用来下载远程文件的最简单网络协议,在嵌入式开发中,由于嵌入式开发板资源有限,不能进行文件编译,因此我们都是将写好都代码在宿主机(Linux虚拟机)上进行调试编译好后生成二进制文件,然后通过ftp或NFS来进行传输到开发板上运行。也就是ARM开发板当做客户端, 使用虚拟机 Ubuntu来当做服务器。
执行以下安装命令,安装后即会自动运行:
sudo apt-get install vsftpd
修改vsftpd的配置文件/etc/vsftpd.conf:
sudo vim /etc/vsftpd.conf
将下面几行前面的#去掉:
修改完成后,执行重启命令:
sudo /etc/init.d/vsftpd restart
3.5 安装TFTP
u-boot支持通过TFTP的方式加载内核,ubuntu上运行TFTP服务器,u-boot向服务器请求其参数指定的文件,主机收到请求后将TFTP传输目录下的相应文件通过网络传输给u-boot。这需要主机具有TFTP环境。搭建过程分一下几个步骤:
安装TFTP:
sudo apt install tftp-hpa tftpd-hpa
建立TFTP传输目录
cd /work/
mkdir tftpboot
chmod 0777 tftpboot
修改TFTP配置文件/etc/default/tftpd-hpa:
TFTP_USERNAME="tftp"
# TFTP传输目录
TFTP_DIRECTORY="/work/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
# -c表示可以上传文件,-s表示指定TFTP传输目录,上面已经指定
TFTP_OPTIONS="-l -c -s"
重启TFTP服务:
service tftpd-hpa restart
为了确保环境搭建成功,可以做一些测试。在上文设置的tftp传输目录下创建文件test。然后进入某个目录,假设是/work目录,运行如下命令:
#localhost 表示本机
tftp localhost
此时进入TFTP的命令行,输入如下命令:
tftp> get test
tftp> put test
Error code 0: Permission denied
tftp> q
/work目录下出现文件test,表示TFTP服务器安装成功。
3.6 NFS服务搭建
NFS 就是 Network FileSystem 的缩写,最早之前是由sun 这家公司所发展出来的。它最大的功能就是可以透过网络,让不同的机器、不同的操作系统、可以彼此分享文件。NFS可以让你的PC通过网络将远端的NFS 服务器共享出来的文件mount到自己的系统中,在客户端看来使用NFS的远端文件就象是在使用本地文件一样。 使用NFS可以使应用程序的开发变得十分方便, 客户端不需要大容量的存储器,更不需要进行映像文件的烧录和下载,只要mount到服务器端的特定目录下,然后运行该目录下的程序即可观察到结果。嵌入式项目中常用nfs来挂载文件系统。
执行以下安装命令,安装后即会自动运行:
sudo apt-get install nfs-kernel-server portmap
它的配置文件为/etc/exports,添加共享目录:
格式 : /tmp *(rw, sync, no_root_squash)
共享文件 可访问用户 权限 写回源文件? 客户端使用root,则想要root权限
我们创建一个目录/work/nfs_root,配置/etc/exports:
/work/nfs_root *(rw,sync,no_root_squash)
修改完毕之后,启动NFS服务器
sudo /etc/init.d/nfs-kernel-server restart/start/stop
查看是否启动:
netstat -a | grep nfs
为了确保nfs环境搭建成功,不妨做一下测试。挂接nfs共享目录到/mnt/rootfs路径下,即执行如下命令,其中,-t选项用于指定文件系统的类型为nfs。
mkdir -p /mnt/rootfs
mount -t nfs localhost:/work/nfs_root /mnt/rootfs
然后访问/mnt/rootfs,可见/work/nfs_root目录下的内容出现在/mnt/rootfs目录下,说明环境搭建成功。
root@zhengyang:~# ls /mnt/rootfs
test
我这里在/work/nfs_root路径下创建了一个test文件。
共享目录使用结束之后,卸载共享目录,运行以下命令:
umount /mnt/rootfs
3.7 搭建samba服务器
因为我是在windows上开发,Ubuntu编译。因此windwows之间的文件共享是非常重要的。通常有两种方式:samba服务器或者共享文件夹。
Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。它可以实现windows和Unix-Like两个平台之间互相分享文档和数据。 Samba服务器的工作原理是:客户端向Samba服务器发起请求,请求访问共享目录,Samba服务器接收请求,查询smb.conf文件,查看共享目录是否存在,以及来访者的访问权限,如果来访者具有相应的权限,则允许客户端访问,最后将访问过程中系统的信息以及采集的用户访问行为信息存放在日志文件中。
安装samba:
sudo apt-get install samba
测试是否安装成功:
smb[按TAB TAB补全]
配置samba:
cd /work
mkdir sambashare
cd /etc/samba/
sudo cp smb.conf smb.cong.bkp //备份samba配置文件
sudo vi smb.conf
输入如下内容:
[share]
comment=samba
path=/work/sambashare
public=yes
create mask=0777
directory mask=0777
writable=yes
available=yes
forceuser=root
forcegroup=root
重启samba:
sudo /etc/init.d/smbd restart
windows下访问samba服务器:
步骤:网络--->\\192.168.0.200--->Enter回车键:发现出现了一个share文件夹
测试:
- 步骤1:在share文件夹下创建一个test.txt。
- 步骤2:ubuntu中 cd /worksambashare/,ls发现出现了一个test.txt
3.8 安装基本开发环境
安装build-essential软件包,build-essential作用是提供编译程序必须软件包的列表信息:
sudo apt-get install build-essential
安装bison、flex,它们分别是语法、词法分析器:
sudo apt-get install bison flex
安装C函数库的man手册,这样就可以通过类似"man read"命令查看函数的作用:
sudo apt-get install manpages-dev
3.9 安装交叉编译环境arm-linux-gcc
交叉编译环境可以在ARM官网下载:https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads ,或者到http://releases.linaro.org/components/toolchain/binaries/下载。
选择交叉编译环境这一步需要慎重,我们首先要知道我们自己使用的开发板采用的ARM架构是哪一个?ARM目前总共发布了8种架构:ARMv1、ARMv2、ARMv3、ARMv4、ARMv5、ARMv6、ARMv7、ARMv8。
确认了ARM架构之后,选择支持该架构的交叉编译环境。可以参考GNU Arm Embedded Toolchain官网中的文档和说明来确定march支持的版本。在ARM官方提供的文档中,可以查看到march选项支持的处理器架构和对应的版本。例如,使用arm-linux-gcc --march=armv8-a命令编译代码时,表示编译针对于Cortex-A53处理器。
由于我后面学习使用的是Mini2440开发板,其采用的samsung SoC型号为s3c2440基于ARM9,采用的ARMv4架构,因此这里我选择了arm-linux-gcc-4.3.2,当然也可以选择高版本的,只要其支持ARMv4即可。
下载安装包并把文件放在linux系统的路径/work/sambashare路径下:
注:
- 如果想安装高版本交叉编译工具比如arm-linux-gcc 4.8.3,可以参考博客Mini2440之linux内核移植第2.10小节内容。
然后将arm-linux-gcc-4.3.2移动到/opt/tools目录下,使用一下命令进行解压:
mkdir /opt/tools
mv /work/sambashare/arm-linux-gcc-4.3.2.tgz /opt/tools/
cd /opt/tools/
tar -xzvf arm-linux-gcc-4.3.2.tgz -C /
执行该命令,将把arm-linux-gcc 自动安装到/usr/loca/arm/4.3.2 目录:
接下来配置系统环境变量,把交叉编译工具链的路径添加到环境变量PATH中去,这样就可以在任何目录下使用这些工具:
编辑profile文件,添加环境变量。
vim /etc/profile
添加如下代码:
export PATH=$PATH:/usr/local/arm/4.3.2/bin
接下来使用命令:source /etc/profile,使修改后的profile文件生效。
然后,使用命令:arm-none-linux-gnueabi-gcc -v查看当前交叉编译链工具的版本信息,arm-none-linux-gnueabi-gcc和arm-linux-gcc命令意义一样:
如果出现错误:arm-none-linux-gnueabi-gcc: No such file or directory。
是因为ubuntu是64位的,但arm-linux-gcc是32位的,需要安装如下包:
sudo apt-get install lib32ncurses5
需要观察:arm-none-linux-gnueabi-gcc -v输出时是否默认配置了-march=armv4t,如果有这个,那说明这个编译器只能用来编译armv4t指令集的处理器。
然后验证交叉编译工具链是否安装成功并且可以使用,随便找一个目录编辑一个hello源代码,vim hello.c:
编辑好hello.c文件后,保存退出。然后使用交叉编译器对hello.c进行编译,并生成可执行文件hello:
这里生成的hello文件并不能像gcc编译出来的文件那样直接使用“./hello”命令执行并显示内容,因为它是一个二进制文件,只能下载到开发板上执行!
如何知道我们编译器默认指定的-march是什么呢?可以通过如下命令查看可执行文件的平台属性信息:
root@zhengyang:/work/tool# arm-linux-readelf -A hello
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "5TE"
Tag_CPU_arch: v5TE // 架构armv5t
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_rounding: Needed
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
3.10 安装调试工具arm-linux-gdb
下载arm-linux-gdb-7.5.tar.gz,,使用一下命令进行解压:
mv /work/sambashare/arm-linux-gdb-7.5.tar.gz /opt/tools/
cd /opt/tools/
tar xzvf arm-linux-gdb-7.5.tar.gz -C /usr/local
进入arm-linux-gdb-7.5,解压并配置:
cd arm-linux-gdb-7.5
tar -ivzxf gdb-7.5.tar.gz
cd gdb-7.5
./configure --target=arm-linux --disable-werror --prefix=/usr/local/gdb -v
注:--target=arm-linux意思是说目标平台是运行于ARM体系结构的linux内核;--prefix是指生成的可执行文件安装在哪个目录,这个目录需要根据实际情况作选择。如果该目录不存在,会自动创建,当然,权限足够的话。
然后编译安装:
make
make install
编译会出现如下错误:
上述错误的原因是:缺少前置文件,执行安装:
sudo apt-get install libncurses5-dev
安装过程如果出现texinfo相关的错误,则请执行:
sudo apt-get install texinfo
再次编译安装,正确安装后,会在指定安装路径下生成:bin、include、lib、share文件夹。
配置/etc/profile,最后加上:
vim /etc/profile
export PATH=$PATH:/user/local/gdb/bin
使刚配置的环境变量生效:
source /etc/profile
注意如果之前安装的arm-linux-gcc里面也存在gdb的话,为了使用刚刚安装的7.5版本gdb,应将gdb7.5添加在gcc的环境变量前面。保证优先使用gdb7.5而不是gcc套件里的gdb。
四、安装Jlink
4.1 下载jlink
在JLink官网下载deb后缀,https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack:
需要注意的这里我没有下载最新的,我下载的版本是JLink_Linux_V434a.tgz。如果官网不找不到,请到其他资源查找。
4.2、上传到linux服务器
下载完成之后,利用samba服务器上传至linux服务器。
4.3、安装程序
在ubuntu可视化界面上,利用命令安装:
mv /work/sambashare/JLink_Linux_V434a.tgz /opt/tools
cd /opt/tools
tar -zvxf JLink_Linux_V434a.tgz -C /usr/local
进入/usr/local/JLink_Linux_V434a路径,然后执行命令 cp -d libjlinkarm.so.4* /usr/lib -f 将库复制到lib里面
cd /usr/local/JLink_Linux_V434a
cp -d libjlinkarm.so.4 /usr/lib -f
最后执行 ./JLinkGDBServer:
./JLinkGDBServer
如果出现如下错误:
动态链接库缺失,安装libusb-dev:i386
sudo apt install libusb-dev:i386
Ubuntu机连接好Jlink后,再次运行./JLinkGDBServer,此时会出现正常连接上jlink的提示,并且会显示ID和ARM9的字样,说明安装驱动成功:
参考文章
[1] 嵌入式Linux开发环境搭建