imx6学习笔记

imx6学习笔记

前言

接触linux大概有两年,接触imx6大概有1年,简单驱动也写过一些,简单的应用也弄过不少,然而使用linux的大型项目还真没怎么接触。但是在这两年多的使用过程中还是有不少心得的。特意写这样一个笔记来供其它新手参考。

linux环境搭建

实体机虚拟机都行,能跑linux就OK,再不行那就用msys2将就一下吧。

Linux文件系统基本的目录

这个没什么好说的,自己装一个虚拟机然后安装一个linux,然后自己多看看,基本慢慢就认识了

Linux基本指令

ls
cd 
grep 
find
chmod
chown
rm 
mv
cp
touch
mkdir
mkfs
dd
tar
ln

先就这些吧

vim编辑器

不要用文件管理器,不要用gedit,不要用leafpad,就用vim,自己安装插件,自己网上查配置,把下面的操作坚持一个月,基本就差不多了。

复制
粘贴
剪切
选择
列选择
撤销
查找
替换
跳转到首行
跳转到尾行
跳转到指定行
这些暂时够用了
tab多文件操作

能修改基本的配置文件

profile(/etc/profile或者~/.bash_profile)---主要修改环境变量和一些随终端启动的命令
~/.vimrc---vim配置
/etc/sudoers---用户权限
/etc/hostname---主机名
/etc/hosts---hosts表,有时候科学上网会用到
/etc/locale.gen和/etc/locale.conf---系统语言配置
~/.xinit开机启动(xinit,如果时用dm启动的则无效,不过有相对应的文件,请自行百度)

好了,下面进入正篇环节。

imx6开发

如果你的开发板常用的外设跟freescale官方的imx6评估版区别不大的话,那么直接下载官方源码,编译烧录后基本可以运行了。

源码下载

http://git.freescale.com/git/
uboot地址是:imx组的uboot-imx.git仓库
kernel地址是:imx组的linux-imx.git仓库
注意:关于freescale git仓库的uboot和kernel命名规则:
1. 由于这个仓库集合了linux使用的uboot和kernel,同时也有android使用的uboot和kernel,这两个命名是不同的
2. linux版本的统一命名为rel_imx_内核版本号_小版本号_beta/ga,不论是uboot还是kernel的版本号,命名都是依据kenel的版本号命名。比如我下载了一个rel_imx_4.1.15_2.1.0.ga版本的kernel,那么我是用的uboot的版本需要也是这个版本,uboot的版本和linux的版本务必保持一致。以上版本的意思是,我使用的这一系列软件使用与imx系列的cpu,配套的linux版本是4.1.15,发布版本是2.1.0(该版本有freescla发布人员设定)的伽马版本(gamma)。至于像n7.1.2还有m6.0.1以及l5.0.0这样的很明显就是安卓版本嘛。n7.1.2就是android n(7.1.2),其他类推。不过安卓的内核大部分是放在linux-2.6-imx.git仓库中。

交叉编译环境配置

下载交叉编译器
https://releases.linaro.org/components/toolchain/binaries/latest/
对应版本下载,64位linux就下载x86_64的,32位就下载i686的
将编译器拷贝到虚拟机,怎么拷贝自己想办法,方法很多,实在不知道的单独问我。
解压压缩表,将拷贝进来的压缩包解压出来,然后移动到想要安装软件的地方,比如我通常将第三方软件安卓到/usr/share目录下,涉及指令有tar/mv(cp)/

[xml@qiuzhiqian download]$ tar xvf gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
...
[xml@qiuzhiqian download]$ sudo mv gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /usr/share/

然后编辑profile文件添加环境变量。

vim ~/.bash_profile

注意:环境变量的文件不一定就是.bash_profile,可能是.profile

export PATH=$PATH:/usr/share/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnu eabihf/bin

关闭终端后重新打开,或者执行一下命令是的环境变量立即生效

source ~/.bash_profile

到此交叉编译器安装成功,我们测试一下

[xml@qiuzhiqian download]$ aarm-linux-gnueabihf-gcc -v

如果出现类似一下信息则说明安装成功

Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/share/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/6.3.1/lto-wrapper
Target: arm-linux-gnueabihf
....
gcc version 6.3.1 20170109 (Linaro GCC 6.3-2017.02)

源码编译

编译其实都是一些固定的命令,linux和uboot都差不多。
下面我已一块imx6ul开发板为例来做说明。

编译uboot

解压uboot源码

[xml@qiuzhiqian ~/download]$ tar xvzf uboot-imx-rel_imx_4.1.15_2.0.0_ga

我们知道编译uboot是需要用make命令的,而make又是使用Makefile的.
如果我们稍微阅读一下Makefile的内容就会发现,make会检测当前运行的arch环境,然后根据arch环境来调用合适的gcc编译器来编译源码。
如果我们不做任何修改的话,arch检测出来的结果是ARCH=x86,因为我们是在x86的pc机上面运行的make的,然后Makefile会根据检测的ARCH的值给CROSS_COMPILE这个变量赋值这个值是编译器的前缀,比如x86电脑是没有前缀的直接就是gcc所以这个值通常为空。
因此我们大概知道了Makefile的大致工作流程。
1、检测是否定义了ARCH变量,如果没有定义,则使用本机的ARCH,本机通常就是电脑的ARCH,即x86
2、检测是否定义了CROSS_COMPILE变量,如果没有定义则使用与ARCH相匹配的值,x86电脑通常位空,即无前缀
3、根据ARCH和CROSS_COMPILE调用相应的编译器(比如${ARCH}gcc)编译相应的文件(比如arch/x86目录下的文件)
所以说
ARCH变量决定了编译那一部分源代码:即通用代码+ARCH代码
CROSS_COMPILE决定了使用那个编译器编译源代码
看到这我们基本就清楚了:我们要用我们前面安装的交叉编译器来编译适用与arm架构的源码(即通用源码部分+arm源码部分)
我们先看看交叉编译器的前缀:
找到我们之前安装的交叉编译器下的bin目录,查看一下文件

[xml@qiuzhiqian ~/download/uboot-imx-rel_imx_4.1.15_2.0.0_ga/arch]$ ls /usr/share/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/
arm-linux-gnueabihf-addr2line  arm-linux-gnueabihf-g++         arm-linux-gnueabihf-gdb       arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ar         arm-linux-gnueabihf-gcc         arm-linux-gnueabihf-gfortran  arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-as         arm-linux-gnueabihf-gcc-6.3.1   arm-linux-gnueabihf-gprof     arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-c++        arm-linux-gnueabihf-gcc-ar      arm-linux-gnueabihf-ld        arm-linux-gnueabihf-size
arm-linux-gnueabihf-c++filt    arm-linux-gnueabihf-gcc-nm      arm-linux-gnueabihf-ld.bfd    arm-linux-gnueabihf-strings
arm-linux-gnueabihf-cpp        arm-linux-gnueabihf-gcc-ranlib  arm-linux-gnueabihf-ld.gold   arm-linux-gnueabihf-strip
arm-linux-gnueabihf-dwp        arm-linux-gnueabihf-gcov        arm-linux-gnueabihf-nm        gdbserver
arm-linux-gnueabihf-elfedit    arm-linux-gnueabihf-gcov-tool   arm-linux-gnueabihf-objcopy   runtest

可以看到我们的交叉编译器是以arm-linux-gnueabihf-
所以我们要修改Makefile的
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
这两个变量相当于是全局变量,所以我们定义在Makefile文件的开头

VERSION = 2016 
PATCHLEVEL = 03
SUBLEVEL =
EXTRAVERSION =
NAME =

ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-

这两个变量修改了之后我们就可以正常编译了
编译分为三个部分
1、导入配置
2、修改配置
3、根据配置编译源码
由于Linux本身就是一个很灵活的东西,比如我源码使用哪个型号的以太网驱动,使用那个型号的rtc驱动,这些都是可以选择的。而这些都是由配置文件决定的。比如配置文件中说明了使用DS3232这个型号的RTC,那么便宜代码的时候就是编译DS3232的驱动,而其他的RTC驱动就不会编译也不会使用。
那么这个配置文件怎么写?由于一个Linux由上千甚至上万个配置选项,如果让我们自己写那真是无从下手,所以Linux源码一般都会附带一些配置模板供我们使用,同时芯片厂商也会提供一些配比模板。我们只需要简单的修改一下配置模板就可以直接使用了。
uboot的配置模板是放在configs目录下,我们可以查看一下imx6ul的配置模板

[xml@qiuzhiqian ~/download/uboot-imx-rel_imx_4.1.15_2.0.0_ga]$ ls configs/ |grep mx6ul
mx6ul_14x14_ddr3_arm2_defconfig
mx6ul_14x14_ddr3_arm2_eimnor_defconfig
mx6ul_14x14_ddr3_arm2_emmc_defconfig
mx6ul_14x14_ddr3_arm2_nand_defconfig
mx6ul_14x14_ddr3_arm2_qspi1_defconfig
mx6ul_14x14_ddr3_arm2_spinor_defconfig
mx6ul_14x14_evk_ddr_eol_brillo_defconfig
mx6ul_14x14_evk_ddr_eol_defconfig
mx6ul_14x14_evk_ddr_eol_qspi1_defconfig
mx6ul_14x14_evk_defconfig
mx6ul_14x14_evk_emmc_defconfig
mx6ul_14x14_evk_nand_defconfig
mx6ul_14x14_evk_qspi1_defconfig
mx6ul_14x14_lpddr2_arm2_defconfig
mx6ul_14x14_lpddr2_arm2_eimnor_defconfig
mx6ul_9x9_evk_defconfig
mx6ul_9x9_evk_qspi1_defconfig
mx6ull_14x14_ddr3_arm2_defconfig
mx6ull_14x14_ddr3_arm2_emmc_defconfig
mx6ull_14x14_ddr3_arm2_epdc_defconfig
mx6ull_14x14_ddr3_arm2_nand_defconfig
mx6ull_14x14_ddr3_arm2_qspi1_defconfig
mx6ull_14x14_ddr3_arm2_spinor_defconfig
mx6ull_14x14_ddr3_arm2_tsc_defconfig
mx6ull_14x14_evk_defconfig
mx6ull_14x14_evk_emmc_defconfig
mx6ull_14x14_evk_nand_defconfig
mx6ull_14x14_evk_qspi1_defconfig
mx6ull_9x9_evk_defconfig
mx6ull_9x9_evk_qspi1_defconfig
picosom-imx6ul_defconfig
picosom-imx6ul-qspi_defconfig

可以看到配置模板都是以defconfig后缀结尾,比如我们要导入mx6ul_14x14_evk_nand_defconfig这个配置模板,执行的命令就是:

make mx6ul_14x14_evk_nand_defconfig

这条命令的作用其实很简单,就是将我们指定的配置文件复制到uboot根目录下,然后重命名为.config。
因为生效的永远只要根目录下的.config配置文件。
然后就是修改配置文件

make menuconfig

这条指令会读取uboot中的所有配置选项,然后生成一个图形界面。每次修改好保存配置时,会将启用的配置选项保存到.config文件中,所以每次通过make menuconfig更改配置好.config文件也会修改。
然后就是编译了

make

然后就会执行编译了。可以从编译输出信息中可以看出arch下面的文件都是编译的arm目录下的文件,这就是之前的ARCH=arm来设定的。

  CHK     include/generated/asm-offsets.h
  HOSTCC  tools/mkenvimage.o
  HOSTLD  tools/mkenvimage
  HOSTCC  tools/image-host.o
  HOSTCC  tools/dumpimage.o
  HOSTLD  tools/dumpimage
  HOSTCC  tools/mkimage.o
  HOSTLD  tools/mkimage
  LD      arch/arm/cpu/built-in.o
  CC      arch/arm/cpu/armv7/cache_v7.o
  CC      arch/arm/cpu/armv7/cpu.o
  CC      arch/arm/cpu/armv7/cp15.o
  CC      arch/arm/cpu/armv7/syslib.o
  AS      arch/arm/cpu/armv7/lowlevel_init.o
  CC      arch/arm/cpu/armv7/mx6/soc.o
  CC      arch/arm/cpu/armv7/mx6/clock.o
  CC      arch/arm/cpu/armv7/mx6/module_fuse.o
  LD      arch/arm/cpu/armv7/mx6/built-in.o
  LD      arch/arm/cpu/armv7/built-in.o
...
  OBJCOPY examples/standalone/hello_world.srec
  OBJCOPY examples/standalone/hello_world.bin
  LDS     u-boot.lds
  LD      u-boot
  OBJCOPY u-boot-nodtb.bin
  COPY    u-boot.bin
  CFGS    board/freescale/mx6ul_14x14_evk/imximage.cfg.cfgtmp
  MKIMAGE u-boot.imx
  OBJCOPY u-boot.srec
  SYM     u-boot.sym
  CFG     u-boot.cfg

然后就可以看到生成了uboot镜像文件了。
关于选择哪个配置模板,这个要看你的开发板启动方式了,如果是从emmc启动,就选带emmc的,nand就选带nand的,启动这几个可以随便选一个,然后自己改一下。不过为了避免麻烦还是对应着选吧。
uboot部分介绍完了,Linux部分就是一样的啦。
不过linux的配置模板的位置不太一样,比如arm部分的配置模板实在arch/arm/configs/目录下面。

[xml@qiuzhiqian ~/download/linux-imx-rel_imx_4.1.15_2.0.0_ga]$ ls arch/arm/configs/ |grep imx
imx_v4_v5_defconfig
imx_v6_v7_defconfig
imx_v7_defconfig
imx_v7_mfg_defconfig

v4、v5、v6、v7可能是硬件上略微有点差别,我们就用v7吧,有问题再改就是了。
同样先修改Makefile,添加ARCH和CROSS_COMPILE这两个变量,然后

make imx_v7_defconfig

这样会生成.config文件
接着

make menuconfig

使用图形界面对内核进行配置
配置完成退出保存
然后就是编译输出,编译输出根据输出的内容不同,命令不同

make zImage
这是编译源码,同时生成zImage的镜像
make modules
这是编译驱动模块(暂时不用关注)
make modules_install
这是安装驱动模块(暂时不用关注)
make xxx.dtb

说一下dtb编译,dtb是由dts通过dtc编译而来的,arm的dts(设备树文件)位于arch/arm/boot/dts/下面,比如

[xml@qiuzhiqian ~/download/linux-imx-rel_imx_4.1.15_2.0.0_ga]$ ls arch/arm/boot/dts/ |grep imx6ul-14x14
imx6ul-14x14-ddr3-arm2.dts
imx6ul-14x14-ddr3-arm2-emmc.dts
imx6ul-14x14-ddr3-arm2-flexcan2.dts
imx6ul-14x14-ddr3-arm2-gpmi-weim.dts
imx6ul-14x14-ddr3-arm2-mqs.dts
imx6ul-14x14-ddr3-arm2-spdif.dts
imx6ul-14x14-ddr3-arm2-wm8958.dts
imx6ul-14x14-evk-btwifi.dts
imx6ul-14x14-evk-csi.dts
imx6ul-14x14-evk.dts
imx6ul-14x14-evk-emmc.dts
imx6ul-14x14-evk-gpmi-weim.dts
imx6ul-14x14-evk-usb-certi.dts
imx6ul-14x14-lpddr2-arm2.dts

比如我们是从nand启动,那么就编译imx6ul-14x14-evk-gpmi-weim.dts,即

make imx6ul-14x14-evk-gpmi-weim.dtb

这样就会在linux源码根目录下生成dtb文件了
注意是dtb,不是dts

文件系统构建

待完成

镜像下载

待完成

设备树配置

待完成

驱动设计

待完成

应用设计

待完成

猜你喜欢

转载自blog.csdn.net/qiuzhiqian1990/article/details/78146324