书接上文,上次把U-Boot移植完成了,有兴趣的小伙伴可以通过传送门过去。 Linux系统的移植已经完成,但是果然还是移植没时间整理资料,没办法,2年级的娃真的很难辅导…… 现在我对野火开发板的移植已经完成了纯净Linux系统、Busybox根文件系统、SDL+OpenGL、Python3.6,下一步开始移植音频、WIFI、蓝牙、以及按键系统,但是音频已经搞了两天了,移植找不到设备,看了无数遍源码,都无果,后来换上火哥提供的5月份的FullQt,依然是音频设备错误,技术客服回答可能是音频模块坏了,这两天会给我送一块新的板子来,希望一切顺利吧。 这篇里面先说说我的Linux和根文件系统的移植吧,以及关于Linux内核烧入eMMC和远程加载的几种方式,关于SDL的坎坷……先不挖坑了,有空再整理吧。
书归正传。 火哥提供的Linux没看,貌似集成的内容太多了,不够纯,因为我比较喜欢处,所以就从NXP官方已经准备好的系统开始移植吧。 其实NXP提供的系统源码基本是可以用的,要修改的东西比较少,那就直接动手烧录他的系统吧。 一、 NXP官方系统烧录测试NXP的系统可以从官网下载,或者从我提供的连接中下载都可以。 命令如下: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16 第一行命令用于清除工程中之前编译的残留文件,最好这样做,否则有惊喜。 第二行命令用于指定配置文件使用imx_v7_defconfig,这是EVK板子自带的东西。 第三行用于编译内核文件,时间比较长,尤其在虚拟机里做,你可以先吃杯泡面,回来就好了。 之后就编译出了Linux的内核文件,在arch/arm/boot中,如果存在zImage和imx6ull-14x14-evk.dtb两个文件表示成功,否则肯定是出问题了。我分析问题可能出现以下几种: 1. 没有安装交叉编译环境,但如果你做了U-Boot移植,问题应该不在这; 2. 没有安装lzop,直接apt-get安装一下即可; 3. 配置文件名称写错了,imx_v7_defconfig; 4. CROSS_COMPILE=arm-linux-gnueabihf- 后面没加空格,这个错误很低级。 如果两个文件都出来了,那么恭喜你,第一关过了。 下一步开始启动,启动前要保证几件事: 1. 已经做好了U-Boot的移植,并且能够正常启动,如果不知道这是啥,去传送门看,先把U-Boot移植好了再回来看这个; 2. 服务器端(Ubuntu或其他Linux端)安装了tftp或者nfs,关于这个教程这里不写了,问度娘吧。 用U-Boot启动NXP的Linux内核 先用tftp启动,把两个文件拷贝到tftp的目录下,启动tftp服务器。 启动U-Boot进入命令行模式,修改bootargs参数 setenv bootargs“console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw” saveenv 设置U-Boot网络参数: setenv ipaddr 192.168.1.55 //开发板IP地址 setenv ethaddr 00:04:9f:04:d2:35 //开发板网卡MAC地址 setenv gatewayip 192.168.1.1 //开发板默认网关 setenv netmask 255.255.255.0 //开发板子网掩码 setenv serverip 192.168.1.128 //服务器地址,也就是Ubuntu地址 saveenv //保存环境变量 然后尝试用tftp加载内核和设备树文件,并启动。 tftp 80800000 zImage tftp 83000000 imx6ull-14x14-evk.dtb bootz 80800000 - 83000000 前两行是通过tftp命令把服务器端的两个文件拉下来放到指定位置,Linux内核放在80800000,设备树放在83000000,6ULL默认从80000000启动,但是这个位置已经放了U-Boot,而且我们U-Boot加载Linux的时候还需要用,所以位置要往后放,这个参数根据自己的喜好设置吧。 或者通过nfs启动也成,先把两个文件放到NFS的目录下,命令如下: nfs 80800000 192.168.31.128:/home/mars/Linux/nfs/zImage nfs 83000000 192.168.31.128:/home/mars/Linux/nfs/imx6ull-14x14-evk.dtb bootz 80800000 - 83000000 通过我测试,我的NFS要比TFTP快很多。 另外就是可以设置bootcmd参数,把启动命令自动化,这样就不用每次进U-Boot启动Linux系统了。 setenv bootcmd “nfs 80800000 192.168.31.128:/home/mars/Linux/nfs/zImage; nfs 83000000 192.168.31.128:/home/mars/Linux/nfs/imx6ull-14x14-evk.dtb;bootz 80800000 - 83000000” 记得用saveenv保存参数。 这里有个小插曲,我觉得是大家可能会才到的坑,就是NFS加载的时候会出现ERROR:File lookup fail的错误,这是因为uboot中使用的NFS版本是V2,而ubuntu的NFS版本为V3或V4及以上版本,导致uboot不能在NFS服务器中找到文件,所以需要修改ubuntu中NFS的兼容。 打开/etc/default/nfs-kernel-server文件,改三行内容: RPCNFSDCOUNT="-V 2 8" RPCMOUNTDOPTS="-V 2 --manage-gids" RPCSVCGSSDOPTS="--nfs-version 2,3,4 --debug --syslog" 改完之后重启nfs就可以了。 Linux内核启动后控制台会蹦出一堆的内核加载信息,但到了最后发现加载不过去了,提示“Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)”,这是没有根文件系统造成的,这个先忽略,后面会讲到。到了这里表示你的原始内核已经移植成功了,吃杯泡面奖励一下自己吧。 二、 改造自己的Linux内核这部分内容对于野火用户来说非常友好,因为野火的开发板基本参考了NXP官方的板子,要改的东西不是很多,也没有太深奥的地方,甚至比隔壁家的还好弄。 2.1 添加自己的开发板配置文件配置之前,先用make distclean清理一下工程,否则看着太乱。 上一节中我们编译官方内核的时候使用的是imx_v7_defconfig这个配置,这个文件在arch/arm/configs中,我们直接复制一份,重命名为imx_embedfire_emmc_defconfig,这里面是一些模块配置项,后面在移植声卡网卡一类的东西的时候需要改动,在这我们先不动了,永远是的就可以。 复制设备树文件,Linux内核中所有的设备树都存放在arch/arm/boot/dts中,素有imx6ull-开头的都是关于我们这块CPU的设备树,也是NXP官方已经写好的东西,我们从imx6ull-14x14-evk.dts直接入手。 复制这个文件,改名为imx6ull-embedfire-emmc.dts,今后涉及到设备树修改的,都需要在这里进行,本小结中先不动丫。 设备树文件有了,我们还希望在Makefile中能够找到他。 打开arch/arm/boot/dts/Makefile文件,搜索一下dtb-$(CONFIG_SOC_IMX6ULL),在最下面加入我们设备树的名字即可,这样在进行编译的时候就会按照我们的设备树文件编译出imx6ull-embedfire-emmc.dtb文件了。 至此,配置文件基本全部搞定,重新编译并通过U-Boot远程启动测试一下。 记得,在编译的时候使用imx_embedfire_emmc_defconfig这个配置。 2.2 修改eMMC驱动在Linux内核源码中,eMMC采用的是4线模式的,而野火iMX6ULL Pro开发板用的是8线的,不改变也能用,但既然人家提供了8车道,为啥还要在4车道堵车呢!改丫的! 打开imx6ull-embedfire-emmc.dtb设备树文件,找到&usdhc2标签,修改成一下内容: pinctrl-names = "default" , "state_100mhz" , "state_200hmz"; pinctrl-0 = <&pinctrl_usdhc2_8bit>; pinctrl-1 = <&pinctrl_usdhc2_8bit_100hmz>; pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>; bus-width = <8>; non-removable; status = "okay"; 2.3 修改LCD驱动LCD是在硬件开发中比较常用的一种设备,在U-Boot移植的文章中,我们已经做了野火7寸LCD的移植,在Linux下,可以搭配SDL、QT这样的GUI库制作出精美的UI界面。 在Linux中,应用程序是需要通过操作LCD实现字符、图片等内容的显示,在裸机开发中我们可以随意分配一块内存给LCD作为显存用,但是在Linux中,系统对内存管理是很严格的,对于系统内存和用户内存有着明确的划分,正常情况下是不予许随意访问的,而在我们的LCD编程中,我们的驱动程序和应用程序都需要访问同一款叫做“显存”的虚拟内存实现绘制,所以为了解决这个问题,FrameBuffer应运而生,系统内核通过FrameBuffer对显存进行控制,对界面操作最终都是基于FB进行编程的。在Linux一切接文件的中心思想引领下,我们可以在/dev目录下找到显存对应的fbX的一系列文件,我们今天要做的LCD显示用的是/dev/fb0。 LCD的驱动有很多,NXP官方和野火及隔壁家的开发板都是使用的RGB888的协议,驱动NXP官方已经写好了,会在/dev下面生成一个fb0的设备,如果有多个显示设备的话还会出现fb1、fb2…。 过多的理论性内容网上一大堆,不啰嗦了,开始实战。 在Linux配置外设,无非就是操作设备树文件,对于相同协议的LCD,驱动基本上都是一样的,只需要根据不同的LCD硬件调整参数。在移植U-Boot的时候,对于LCD的移植已经讲得很清楚了,就是修改类似控制器hspw、hbp、hfp等等一些时间相关的参数。 打开imx6ull.dtsi文件,找到cdif:lcdif@021c8000这个节点,这里所有的配置项就是用于控制LCD显示的,这个节点在I.MX6ULL平台中是通用的,既然是通用也就意味着丫是不完整的,所以还需要我们在自己的imx6ull-embedfire-emmc.dts中做更进一步的配置。 我们先看imx6ull.dtsi文件中关于LCD节点的描述。compatible,这个字段在配置文件中是通用的,表示兼容性,LCD的兼容属性是"fsl,imx6ul-lcdif"和"fsl,imx28-cldi",在原文件中搜索就可以看到相关适配驱动的信息,有兴趣的可以读读源码。 打开imx6ull-embedfire-emmc.dts,找到pinctrl_lcdif_dat段,这部分是关于LCD用到引脚的配置,野火开发板和NXP开发板的引脚结构是相同的,所以这里基本不用改,而且建议大家以后做实际项目的时候尽量也用这些官方推荐的引脚。 第二个要修改的是&lcdif段,这里是关于LCD具体参数的配置,这里改的东西比较多,大部分需要根据你手头上用到的屏幕主板参数进行配置。 这里再次招来GT911的数据手册。
1. Pinctrl-0:这里面配置了引脚的具体情况,这里用不到复位,所以要删除pinctrl_lcdif_rest 2. Bits-per-pixel:像素格式,我们采用的是RGB888的协议,所以宽度为24bit 3. bus-width:线宽,根据自己板子的DATA信号线对应,野火7寸屏用的是DATA0~DATA23,所以我的是24线 4. clock-frequency:像素时钟,搜侧重是33.3MHz,所以应该是33300000 5. hactive:X轴像素数,800 6. vactive:Y轴像素数 7. hfront-porch,HFP,210 8. hback-porch,HBP,46 9. hsync-len,HSPW,1 10. vback-porch,VBP,23 11. vfront-porch,VFP,7 12. vsync-len,VSPW,1 13. hsync-active,HSYNC数据线极性,0 14. vsync-active,VSYNC数据线极性,0 15. de-active,DE数据线极性,1 16. pixelclk-active,时钟数据线极性,0 这些参数设置好之后LCD就能正常显示了,如果出现花屏或者黑屏的情况,很有可能是某个参数写错了,尤其是宽高。 第二步就是配置背光。 NXP官方板子和野火用的都是GPIO1_IO08控制背光,所以关于pinctrl_pwm1这段也不需要修改,关于pwm1这个节点的信息,在imx6ull.dtsi文件中可以找到,如果找不到就直接在imx6ull-embedfire-emmc.dts中重写一个,尽量不要去改动imx6ull.dtsi,毕竟人家是通用的设备树信息。 在imx6ull-embedfire-emmc.dts文件中可找到&pwm1的段,status设置为okay启用背光,通过阅读Documentation/devicetree/indings/video/backlight/pwm-backlight.txt得知,节点backlight就是背光的设置段,compatible属性设置为pwm-backlight,对应的驱动文件是drivers/video/backlight/pwm_bl.c。背光的PWM频率官方推荐是5KHz,这个我们就不改他了,除非屏幕闪烁厉害。 brightness-levels属性描述了屏幕的亮度级别,原文件中只给出了几个值,我们把他扩展到0~255,0表示PWM占空比为0%,背光完全关闭,255表示背光占空比为100%,背光全亮。当然,这个值可以任意写,只要不超过255就行。 default-brightness-level表示当前亮度级别,随便设置啥都行,这个值表示的是brightness-levels的Index值。 调整完毕后重新编译,,启动新的内核,这时候如果屏幕上出现了小企鹅,恭喜你,LCD移植成功。 如果你的小企鹅没出来,看看menuconfig中Device Drivers -> Graphics support -> Bootup logo下面的三个选项是不是都选中了。 可以通过/sys/devices/platform/backlight/backlight/backlight下面的文件操作背光显示,需要注意的是,这个文件必须在开发板的系统下才能看到,在Ubuntu下是看不到这个文件系统的。当然,这是后话,因为这时候还没一直根文件系统涅。 这个目录下的max_brightness表示最大级别,也就是default-brightness-level的Index值,如果这里面我们设置了7个值,那max_brightness最大就是7,而不是255,不知道有没有表达清楚。 brightness表示当前的背光级别。 2.4 LCD的额外设置和LOGO修改最喜欢的环节,改LOGO。 在你的Ubuntu系统中先装个软件爱你 netpbm,用apt-get可以直接下载安装。 做好你的LOGO,bmp和png都可以,然后用这个软件转换成ppm格式的。 具体命令如下: bmptopnm rainbow.bmp > rainbow.pnm pnmquant 224 rainbow.pnm > rainbow_224.pnm pnmtoplainpnm rainbow_224.pnm > logo_linux_clut224.ppm 第一行可以换成pngtopnm,第二行命令要求源文件和目的文件不能重名,第三行尽量保持同名。 最后把 logo_linux_clut224.ppm复制到源码devices/video/logo/下替换原来的文件,并删除logo_linux_clut224.c和logo_linux_clut224.o。最好是在编译前清理一下工程,这样保证不会出问题。 这样LOGO就改成我们自己的了。 在U-Boot中,设置bootargs,加一个console=tty1的输出,即setenv bootargs 'console=tty1 console=ttymxc0,115200’,这样屏幕上就可以看到控制台输出内容了。 等移植完根文件系统之后,在修改etc/inittab文件,加入tty1::askfirst:-/bin/sh,这样我们的I.MX6ULL主板就可以接收到剪片的输入了。 在默认情况下,10分钟后LCD会黑屏,如果需要增长这个时间,或者是要设置永久亮屏,只需要修改源码drivers/tty/vt/vt.c文件中的blankinterval白能量即可,0表示常亮。 另外,进入系统后可以通过fbset查看屏幕的参数信息。 2.5 修改RTCRTC也就是系统实时时钟,用于记录系统的时间,在野火I.MX6ULL Pro开发板上有一块纽扣电池专门用于在系统掉电后维持系统时间。而在Linux驱动中也已经写好了RTC的驱动程序,NXP已经帮我们最好了移植,所以这块我们就不用在动了,直接用就行。 进入系统后时间是错乱的,所以要通过date -s “2020-11-24 17:25:30”命令来设置系统时间,设置完毕后再用date命令查询时间,发现一切OK。 But,重启是否发现时钟有他娘的归零了!! 不要着急,吃桶泡面稳定一下情绪。 在date设置完之后,你还需要hwclock -w写入到RTC芯片中,这样你的时钟就保存下来了,而且他会自己运行。
|