热度 4|||
当然,本人已经不是电子控制器开发的新手了。从事单片机,DSP开发十多年,但是一直没有接触过嵌入式linux。2014年初由于公司的项目需要,决定引入嵌入式linux的平台进行产品研发,从这个时候开始正式接触嵌入式linux,并开始在linux上进行工作。到现在差不多1年半,现在将这个过程重新整理出来,和大家一起分享,同时也给自己留一个记录。
“嵌入式linux新手入门手记”会是一个系列,记录我从第一次正式开始在linux平台工作,到完成项目的过程中各问题的解决过程。当然,作为工作经历的记录,这个手记的系列不讨论理论方面的知识,只是忠实的记录问题,以及问题的解决过程和方法。
首先在这里介绍一下我的开发平台:TI的AM335x的平台,硬件已经调试完成,在本手记中将不进行硬件方面的记录。主要需要的功能是:USB接口单点触摸屏,1024*768 TFT-LCD显示,GUI的用户程序实现人机交互,100M以太网,不需要3D以及图形加速,256M DDR2,256M nand,一个SD卡槽,一个RS232接口。
要进行嵌入式linux开发,当然需要搭建计算机的工作平台,考虑工作的方便和效率,决定在计算机上安装独立linux系统,和window做成双引导。
2010年时用过一段时间的ubuntu,所以决定还是使用ubuntu,在ubuntu的官网上下载32位版本的14.04(64位的系统驱动程序比较难找)。使用ubuntu推荐的Universal-USB-Installer-1.9.5.9工具,将ubuntu的安装镜像写入到一个标准的4GU盘上(标准的意思是指不要有乱七八糟的功能,可能会导致兼容性问题而无法启动ubuntu安装程序。写入时会导致U盘的内容全部丢失,需要先备份U盘的文件)。
在windows7的计算机管理中启动磁盘管理器,我的计算机硬盘是500G的,分为2个分区,并格式化为2个磁盘:C(190G)和D(其余空间),在磁盘管理器中对D分区进行压缩,压缩出100G的磁盘空间出来,对这个压缩出来的100G空间不要做其他处理,退出磁盘管理器。
重新启动计算机并进入到BIOS中设置启动顺序,使计算机能够从U盘启动。使用制作好的Ubuntu安装U盘启动计算机后,将进入到ubuntu的体验系统中,选择安装,然后根据安装的提示进行,这里需要注意2点,一是语言的选择,最好在安装时选择中文,这样避免后续设置ubuntu时显示、输入法等的问题。二是最好不要手动指定安装分区,有ubuntu安装程序自动对之前划分出来的100G空间进行管理,我的计算机安装有6G的内存,所以安装程序将100G空间划分为一个6G的交换分区,其他用于安装ubuntu。然后ubuntu会询问是否和其他操作系统共存时,一定要选择和其他操作系统共存,否则会导致安装完ubuntu后无法启动windows的问题。
ubuntu14.04的安装还是比较智能的,基本不需要自己的其他干涉,就自动安装完成了。
在安装完成后,需要对ubuntu进行一些设置,这里就不再过多描述,下面仅对一些和后续嵌入式linux开发有关的进行说明:
另外,我使用的shell是bash,而ubuntu14.04安装后默认用的是dash,需要修改为默认使用bash。
1、安装tftp服务。嵌入式linux开发,尤其是uboot和kernel相关的开发,需要不断的修改MLO,u-boot,uImage等,这些文件是需要写入到am335x的板载flash上的,如果每次都是用SD,CCS,烧写工具等,是一个很麻烦的事情。由于uboot支持tftp下载文件并烧写flash,这是一个较为便捷的方式。
在自己工作目录home/XXXX下建立一个空目录,取名为tftp;
给这个目录赋予读写等权限:sudo chmod 777 ./tftp;
安装tftp服务:sudo apt-get install xinetd tftpd-hpa tftp-hpa;
安装完成后,会自动重新启动xinetd,这时在/etc下会出现xinetd.d目录;
进入到这个目录中,执行sudo touch tftpd;
然后执行sudo gedit ./tftpd,在tftpd文件中添加以下内容并保存退出:
service tftp
{
disable=no
socket_type=dgram
wait=no
user=root
protocol=udp
server=/usr/sbin/in.tftpd
server_args=-s /home/XXXX/tftp
log_on_success=PID HOST DURATION
log_on_failure=HOST
}
修改/etc/inetd.conf文件:sudo gedit /etc/inetd.conf,增加以下内容:
tftp dgram udp wait
root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /home/XXXX/tftp
修改/etc/default/tftpd-hpa:
#/etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/XXXX/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
#Defaults for tftpd-hpa
RUN_DEAMON="yes"
OPTIONS="-1 -s /home/XXXX/tftp"
保存并退出后,重新启动tftp服务:sudo /etc/init.d/xinetd restart
sudo /etc/init.d/tftpd-hpa restart
2、安装nfs服务。nfs服务是嵌入式linux开发一个非常重要的服务,使用这个服务,可以将计算机上的一个文件目录挂载为am335x运行时的根文件系统,这样避免不断烧写flash。
建立一个文件夹,用于nfs服务,名称为nfs;
为安装nfs服务,修改ubuntu的软件源,如果不是“main server”,修改为“main server”,然后点击close,弹出对话框点击reload,然后等待处理结束;
安装nfs服务,sudo apt-get install portmap nfs-kernel-server
sudo apt-get install portmap nfs-common
配置共享文件,编辑/etc/exports,在文件末尾添加一行:/home/XXXX/nfs *(rw,sync,no_root_squash)。用于设置nfs目录的工作模式,以及用户进入该目录的权限为root;
重新启动nfs服务,sudo /etc/init.d/portmap restart
sudo /etc/init.d/nfs-kernel-server restart
检查nfs服务是否已经配置成功。
3、设置计算机的网卡。为开发嵌入式linux,我的计算机安装了2个网卡,一个USB接口的无线网卡,用于上网。另外一个100M PCI接口的有线以太网卡,用于连接am335x。将有线以太网卡的IP地址设置为固定:192.168.1.50,子网掩码255.255.255.0,其他可以不设置。
4、下载TI的am335x的开发工具包,这里我使用的是2011年获得的开发包,其中uboot是2011版,以及linux3.2.0。配合这个开发包使用的是arm-none-linux-gnueabi和arm-arago-linux-gnueabi交叉编译工具。由于种种原因,公司决定使用TI-SDK-AM335X-01.00.00.00中的交叉编译工具,是arm-linux-gnueabihf-gcc 4.7.3。
将TI的SDK解压缩到/home/XXXX/ti-sdk-am335x-evm-01000000目录;
将uboot2011解压缩到/home/XXXX/uboot目录;
将linux3.2.0解压缩到/home/XXXX/kernel目录;
修改上述目录的权限,使得XXXX拥有对这些目录以及其文件的读写权限。
5、修改环境变量配置,进行第一次编译uboot和kernel。
编辑~/.bashrc文件,将编译uboot和kernel需要的环境变量加入到文件中,并使生效。 下面是需要加入到~/.bashrc中的内容:
PATH=$PATH:/home/XXXX/ti-sdk-am335x-evm-01000000/linux-devkit/sysroots/i686-arago-linux/usr/bin:/home/XXXX/uboot/am335x/tools:
上述/home/XXXX/uboot/am335x/tools目录,在编译uboot时,会生成后续用于制作uImage文件的工具,用来编译kernel,所以在这里要加入到PATH中。否则后续编译kernel时会出现错误。
编译uboot时会生成用于制作kernel的image的工具,这些工具在编译kernel是被make调用,所以在编译kernel时,必须保证之前已经正确编译或uboot,并且没有对uboot执行过clean。
6、进入到uboot的目录中,编辑两个sh文件,用于后续工作使用。
mkclean.sh,用于执行clean操作:
#/bin/sh
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm O=am335x distclean
上述执行的命令,使用arm-linux-gnueabihf交叉编译器,arm体系的CPU,输出文件保存到./am335x目录,执行distclean清除所以之前的临时文件。
mkboot.sh,用于执行编译操作:
#/bin/sh
make -j4 CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm O=am335x am335x_evm
上述执行编译uboot,其中-j4告诉编译器使用4线程进行编译,这个设置取决于计算机CPU的核心数,能够加快编译的过程。
ARCH=arm指定目标CPU的体系架构。O=am335x指定文件输出目录为./am335x,编译结束后,能够在这个目录下找到MLO,u-boot.img等文件。
am335x_evm选项告知编译器使用这个板的配置对uboot进行编译。
7、进入到kernel目录中,编辑三个sh文件,用于后续编译和安装kernel:
mkcln.sh,用于执行clean操作:
#/bin/sh
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm distclean
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm am335x_evm_defconfig
这个sh将进行清除临时文件的操作,然后使用arm335x_evm_defconfig文件对kernel进行编译配置。
mkkn.sh,用于执行编译操作:
#/bin/sh
make -j4 CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm uImage
make -j4 CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm modules
交叉编译kernel并生成uImage文件。
交叉编译可动态加载的modules。
mkins.sh,用于安装kernel:
#/bin/sh
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm modules_install INSTALL_MOD_PATH=/home/XXXX/nfs
cp ./arch/arm/boot/uImage /home/XXXX/nfs/boot
将编译好的内核uImage和modules文件安装到nfs文件目录中。
在编译完成后,在kernel/arch/arm/boot目录下会生成uImage文件,这个是linux kernel可引导文件,需要将这个文件拷贝到nfs或者tftp目录中。(不过现在新版本的uboot2014开始使用zImage,而不是uImage.)
8、编译后的几个重要文件:
编译uboot将会生成2个重要文件,MLO和u-boot.img。其中MLO是第二次引导程序,am335x复位后,内部otp中的引导程序会启动,然后根据LCD_DATA管脚的设置来加载指定存储器上的MLO。
MLO运行后,将加载相应存储器上的u-boot.img。
u-boot.img启动后,将根据bootargs和bootcmd环境变量设置的参数,选择加载uImage,并启动uImage。
uImage是kernel的可执行内核镜像文件。
9、开发嵌入式linux,需要将am335x通过串口和计算机连接,并使用计算机的超级终端 进行操作。ubuntu下的minicom比较好用。
现在的计算机一般都没有标准的RS232接口,我自己设计了一块CH340T的通信转接板,一端连接am335x的UART0,另外一端接计算机的USB口,在芯恒的官网能够下载到ubuntu的驱动程序,下载下来后insmod成功后,/dev下能够看到ttyUSBX(X取决于计算机,一般为ttyUSB0)。
这样使用USB模拟串口和am335x通信,方便使用。
下一篇将讲述第一次启动am335x。
(原创文章,转载请注明出处)
(未经本人同意,不得用于商业用途)