首页
论坛
官方网站
English
跳转至:
导航
,
搜索
查看“RK3399 Linux Manual”的源代码
←
RK3399 Linux Manual
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
[[Category:开发板]] ==编译Linux+QT== ===安装依赖包=== 使用如下命令安装所需的软件包: sudo apt-get update sudo apt-get install git-core gnupg flex bison gperf libsdl1.2-dev libwxgtk3.0-dev build-essential zip curl zlib1g-dev gcc-multilib g++-multilib genromfs libc6-dev-i386 libncurses5-dev x11proto-core-dev libx11-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip gperf lsb-core lib32z1-dev lib32ncurses5-dev lzop ===编译uboot=== 说明:QT系统使用的uboot与内核与安卓完全相同,如果编译过android的uboot和内核,则本小节步骤可以省略。 在android源码目录下执行如下命令编译uboot,编译完成后映像文件<nowiki>RK3399MiniLoaderAll_V1.05.bi</nowiki>n(因版本不同,名称不一定相同)以及<nowiki>uboot.im</nowiki>g会释放到out/release目录。 .<nowiki>/mk.sh</nowiki> -u ===编译android内核=== 说明:QT系统使用的uboot与内核与安卓完全相同,如果编译过android的uboot和内核,则本小节步骤可以省略。 在android源码目录下执行如下命令编译linux内核,编译完成后映像文件<nowiki>kernel.im</nowiki>g、<nowiki>resource.im</nowiki>g会释放到out/release目录。 .<nowiki>/mk.sh</nowiki> -k ===编译文件系统=== 在android源码目录下执行如下命令编译linux映像文件,编译完成后linux映像文件<nowiki>linux-rootfs.im</nowiki>g会释放到out/release目录。 .<nowiki>/mk.sh</nowiki> -b 在执行./<nowiki>mk.sh</nowiki> -b编译buildroot时,默认编译会少一些插件或库,会弹出一些错误信息。 [[image:Rk3288-buildroot-git.png|800x74px]] 该提示信息表明编译需要git包,执行如下指令安装: sudo apt-get install git [[image:Rk3288-buildroot-libc++.png|799x202px]] 该提示表明标准的C++库没有安装,执行如下指令安装: sudo apt-get install lib32stdc++-4.9-dev [[image:Rk3288-buildroot-libz.png|800x152px]] 该提示表明缺少libz库,执行如下指令安装: sudo apt-get install lib32z1 再执行.<nowiki>/mk.sh</nowiki> -b指令即可正常编译了。编译完成后,最终打包好的文件系统<nowiki>linux-rootfs.im</nowiki>g存放在out/release目录下。它包含了QT5.6的标准库,以及一些常用的QT示例。 ===生成<nowiki>update-linux.im</nowiki>g文件系统=== 在android源码目录下执行如下命令生成单一android映像文件<nowiki>update-linux.im</nowiki>g: .<nowiki>/mk.sh</nowiki> -U update-<nowiki>linux.im</nowiki>g为整个QT系统升级文件的单一映像,包括了uboot,内核,文件系统等。注意,生成update-<nowiki>linux.im</nowiki>g的先决条件是已经成功编译了uboot,内核和linux文件系统,缺一不可。 ==烧写linux QT映像== ===Windows下烧写映像文件=== ===驱动安装=== 解压光盘tools\x3399烧写工具\windows目录下的<nowiki>DriverAssitant_v4.5.zi</nowiki>p文件,打开“<nowiki>DriverInstall.ex</nowiki>e”,点击“驱动安装”,提示安装驱动成功即可。 <center>[[image:Rktools-driver.png|399 × 192px]]</center> <center>[[image:Rktool-driver-ok.png|533 × 257px]]</center> 注意事项: 1.目前支持的操作系统包括:XP,Win7_32,Win7_64,Win8_32,Win8_64。 2.XP系统在驱动安装完后,若还提示“发现新设备”, 安装驱动时选择“自动安装”。 3.若之前已经安装过老版本驱动,请先点击“驱动卸载”后再进行“驱动安装”。 ===生成统一固件<nowiki>update-linux.im</nowiki>g=== 我们已经在mk脚本中集成了生成统一固件的方法,在编译linux文件系统时(.<nowiki>/mk.sh</nowiki> -b -U),会自动生成<nowiki>update-android.im</nowiki>g,并释放到out/release目录。 ===烧录固件<nowiki>update-linux.im</nowiki>g=== 解压光盘tools\x3399烧写工具\windows目录下的<nowiki>AndroidTool_Release_v2.38.zi</nowiki>p文件,得到AndroidTool_Release_v2.38文件夹,打开<nowiki>AndroidTool.ex</nowiki>e,选择“升级固件”选项卡,点击“固件”,在弹出窗口中选择已经生成的<nowiki>update-linux.im</nowiki>g文件,如下图所示。 <center>[[image:3399RKtool.png|905 × 456px]]</center> 工具配置好后,插上开发板的TypeC线、串口线以及5V DC电源线,按下RECOVERY(VOL+)键不放的同时,长按POWER键开机,在串口终端会有如下打印: <center>[[image:RK3399serial.png|1,075 × 706px]]</center> 当uboot检测到RECOVERY键按下时,会有“rockusb key pressed”的打印提示,这时,在烧录工具界面会提示发现一个LOADER设备,然后点击升级,即可开始升级过程(注:如果提示发现一个ADB设备,点击切换按钮切换成LOADER设备即可)。 <center>[[image:RK3399tool1.png|905 × 456px]]</center> 点击升级,稍等片刻,烧写成功界面如下: <center>[[image:RK3399tool2.png|905 × 456px]]</center> ===多设备升级固件<nowiki>update-linux.im</nowiki>g=== 该工具适合用户批量刷机,可以同时给多台设备烧录固件。 解压光盘tools\x3399烧写工具\windows目录下的<nowiki>FactoryTool-v1.42e.ra</nowiki>r文件,打开<nowiki>FactoryTool.ex</nowiki>e,点击“固件”选择<nowiki>update-android.im</nowiki>g,勾选“升级”,点击“启动”,如下图所示: 步骤1 点击固件,选择需要使用的<nowiki>update-linux.im</nowiki>g; 步骤2 点击启动(选择升级按钮); 步骤3 连接开发板USB、DC电源,按下recovery键(对应VOL+键),对应USB口发现设备,并实现自动升级;然后重复步骤3即可同时升级第二台、第三台设备,升级成功或者失败的设备会在两边的列表中列出,移除成功或者失败的设备后可以继续连接需要升级的设备。 <center>[[image:Update-fireware-multi-device.png|998 × 753px]]</center> ===linux下烧写映像文件=== ===生成固件update-linux.img=== 我们已经在mk脚本中集成了生成统一固件的方法,在编译android文件系统时(.<nowiki>/mk.sh</nowiki> -s),会自动生成<nowiki>update-linux.im</nowiki>g,并释放到out/release目录。 ===烧录固件update-linux.img=== 工具路径:tools\x3399烧写工具\linux\ <nowiki>Linux_Upgrade_Tool_v1.24.zi</nowiki>p 在升级之前将update-linux.img拷贝到upgrade_tool相同目录下,运行upgrade_tool(需要sudo) work@ubuntu:~/3288/Linux_Upgrade_Tool_v1.2/cp rockdev<nowiki>/update.im</nowiki>g . work@ubuntu:~/3288/Linux_Upgrade_Tool_v1.2$ sudo ./upgrade_tool 执行结果如下图,发现设备列表,输入要升级的DevNo(设备号)选择设备: [[image:DevNo.png|662x134px]] 选择设备后弹出工具使用菜单如下图,左侧是功能描述,右侧是命令语法,升级相关操作都在upgrade command列表下,忘记命令语法可以输入H进行查看,清屏输入CS,退出按Q。 [[image:DevNo1.png|699x588px]] *CD 命令: 选择设备, 当执行的命令有包含设备重启操作时, 需重新选择设备,当改变操作设备时需重新选择 *SD 命令:msc 切换到 rockusb 升级模式。 当切换执行成功后, 需要重新选择设备 *UF 命令:升级完整 update.img 固件,当执行成功后需要重新选择设备 *UL 命令:升级 loader 功能,当执行成功后需要重新选择设备 *DI 命令:下载单独 image 镜像到指定扇区,例如升级 kernel.img 或者 system.img 都可以 直接使用此功能.例如下载 kernel.img: DI -k kernel.img parameter //如果之前通过 DI 下 载过 parameter,则再下载 kernel.img 时就可以不用指定最后的 parameter 参数 *DB 命令:下载 boot,在 maskrom状态下,可以通过此功能, 让 maskrom设备进行 Rockusb协议通讯 *EF 命令:擦除整个 nandflash *LF 命令:低格保留块后面区域,只有在 loader 模式下使用 执行uf update-linux.img开始更新固件,下图为更新过程截图: Rockusb>uf update-linux.img [[image:DevNo2.png|661x108px]] 备注:也可通过配置<nowiki>config.in</nowiki>i文件配置升级映像文件,只需输入UF即可升级,请用户自行尝试。 ===使用upgrade_tool指令烧写映像=== 上一节我们介绍了通过upgrade_tool烧写统一固件update-<nowiki>linux.im</nowiki>g的方法,熟悉三星平台的开发者会发现,这种方法并不是很高效,真正操作起来,它远没有fastboot工具来的迅速。其实,upgrade_tool工具同样支持类似于fastboot的烧写方式。 为了烧写方便,可以在mk脚本中,默认在编译系统时,将烧写工具upgrade_tool拷贝到out/release目录。 第一步:打开串口终端,并打开minicom,用于适时监控串口调试信息; 第二步:按住RECOVERY键,连接USB OTG线和电源线,这时uboot打印信息将会提示已经进入USB下载模式。如果接通电源后没来得及按住RECOVERY键,在按住RECOVERY键的同时,再按下复位键即可。 第二步:打开第二个串口终端,进入out/release目录; 第三步:在out/release目录下敲击如下指令,烧写相应的映像。 <pre><nowiki> sudo upgrade_tool di –k <nowiki>kernel.im</nowiki>g(烧写内核) sudo upgrade_tool di –s <nowiki>system.im</nowiki>g(烧写文件系统) sudo upgrade_tool di resource <nowiki>resource.im</nowiki>g(烧写资源文件) sudo upgrade_tool di –r <nowiki>recovery.im</nowiki>g(烧写急救文件) sudo upgrade_tool ul <nowiki>RK3399MiniLoaderAll_V1.05.bi</nowiki>n (烧写bootloader) sudo upgrade_tool di uboot <nowiki>uboot.im</nowiki>g <nowiki>parameter.tx</nowiki>t(烧写uboot,必须指定<nowiki>parameter.tx</nowiki>t) sudo upgrade_tool di trust <nowiki>trust.im</nowiki>g <nowiki>parameter.tx</nowiki>t(烧写trust,必须指定<nowiki>parameter.tx</nowiki>t) sudo upgrade_tool uf update-<nowiki>linux.im</nowiki>g(烧写统一固件) </pre> ===Rkflashkit=== rkflashkit 有图形界面,后加了命令行支持,更是好用。 <pre><nowiki> work@ubuntu~/rktool$ sudo apt-get install build-essential fakeroot work@ubuntu~/rktool$ git clone <nowiki>https//github.com/linuxerwang/rkflashkit</nowiki> work@ubuntu~/rktool$ cd rkflashkit work@ubuntu~/rktool$ ./waf debian work@ubuntu~/rktool$ sudo apt-get install python-gtk2 work@ubuntu~/rktool$ sudo dpkg -i <nowiki>rkflashkit_0.1.4_all.de</nowiki>b </pre> 注意:<nowiki>rkflashkit_0.1.4_all.de</nowiki>b会因版本更新,版本数字可能会有所变化,如果执行失败,执行ls命令查看下即可。 work@ubuntu~/rktool/$ sudo rkflashkit 如下是图形界面,在Devices下选择设备,选择要烧写的分区和对应的映像文件,点击Flash image即可。 [[image:RK3399linux-tool.png|947 × 684px]] 该工具也支持命令行,使用help命令查看使用方法 <pre><nowiki> work@ubuntu~/rktool/rkflashkit$ rkflashkit --help Usage<cmd<nowiki>> [</nowiki>args<nowiki>] [<</nowiki>cmd<nowiki>> [</nowiki>args]...] part List partition flash @<PARTITION> <IMAGE FILE> Flash partition with image file cmp @<PARTITION> <IMAGE FILE> Compare partition with image file backup @<PARTITION> <IMAGE FILE> Backup partition to image file erase @<PARTITION> Erase partition reboot Reboot device For example, flash device with <nowiki>boot.im</nowiki>g and <nowiki>kernel.im</nowiki>g, then reboot sudo rkflashkit flash @boot <nowiki>boot.im</nowiki>g @<nowiki>kernel.im</nowiki>g <nowiki>kernel.im</nowiki>g reboot work@ubuntu~/rktool/rkflashkit$ </pre> ==QT文件系统的搭建== 前面章节的介绍,都是九鼎创展工程师已经移植的文件系统包,如果换一个平台,一切从零开始,我们如何构建linux QT文件系统呢?本章节将会带您一步步搭建linux文件系统。 ===下载buildroot=== 在buildroot官网下载最新的buildroot包,下载地址如下: [http//buildroot.uclibc.org/download.html http//buildroot.uclibc.org/download.html] 本文使用的是buildroot 2016.02,用户下载最新版本与本文介绍版本配置可能略有不同,根据下文配置适当修改即可。 ===配置buildroot=== 将下载的buildroot包拷贝到ubuntu系统用户目录并解压,得到buildroot目录,通过命令终端进入buildroot目录,执行make menuconfig,进入配置界面: [[image:RK3399qt.png|1,456 × 938px]] 进入Target options菜单, [[image:RK3399qt1.png|1,456 × 938px]] 在Target Architecture中选择ARM(little endian),在Target Binary Format中选择ELF,退回上一级,进入Toolchain目录,按下图配置: [[image:RK3399qt2.png|1,456 × 938px]] 退回上一级,进入System configuration目录,作如下配置: [[image:RK3399qt3.png|1,456 × 938px]] 退回上一级,进入Target packages目录,再进入Graphic libraries and applications (graphic/text)目录,选择Qt5,如下图所示: [[image:RK3399qt4.png|1,456 × 938px]] 注意不要选Qt,它对应QT4.8版本。进入Qt5菜单,按下图配置: [[image:RK3399qt5.png|1,456 × 938px]] [[image:RK3399qt6.png|1,456 × 938px]] 退回menuconfig的开始界面,进入Filesystem images菜单,作如下配置: [[image:RK3399qt7.png|1,456 × 938px]] 到此,buildroot配置完成。默认配置保存在buildroot根目录的.config中,我们可以备份该配置文件,以防后续配置出错。执行如下指令备份配置文件: cp .config x3399_defconfig ===编译buildroot=== 配置完成后,执行make指令即可编译buildroot了。编译buildroot会会依赖一些第三方插件和库,在第一章的编译文件系统小节中,已经给出了需要安装的包,在编译之前需要提前安装,否则会报错。 编译完成后,文件系统映像<nowiki>rootfs.ex</nowiki>t2会生成到output/images目录。 === 测试QT5.1默认示例 === 将uboot,内核,文件系统烧写进开发板,进入linux文件系统后,可以进入/usr/lib/qt/examples目录测试QT示例。 进入gui/analogclock目录,执行analogclock文件,指令如下: ./analogclock & 这时,在开发板上可以看到有一个时钟图案被绘制出来(会覆盖默认的QTTEST程序),如下图所示: [[image:QT5.1-default.png|635x472px]] 进入gui/rasterwindow目录,执行rasterwindow文件,指令如下: ./ rasterwindow & 这时,在开发板上可以看到一个标注有QWindow的图案被绘制出来,如下图所示: [[image:QT5.1-default1.png|635x472px]] 进入qpa/windows目录,执行windows文件,指令如下: ./windows & 这时,在开发板上可以看到有三幅图案被绘制出来,如下图所示: [[image:QT5.1-default2.png|635x472px]] 进入sql/drilldown目录,执行如下指令: ./drilldown & 这时,在开发板上可以看到有四个QT画面被绘制出来,如下图所示: [[image:QT5.1-default3.png|635x472px]] 进入sql/books目录,执行如下指令: ./books & 这时,在开发板上可以看到有一个对话框被绘制出来,如下图所示: [[image:QT5.1-default4.png|635x472px]] 进入sql/masterdetail目录,执行如下指令: ./masterdetail & 这时,在开发板上可以看到有一个对话框绘制出来,如下图所示: [[image:QT5.1-default5.png|635x472px]] 默认buildroot编译出了很多示例,这里不带一一列举,有兴趣的读者可以自行尝试。 === 安装QT Creator=== 通常我们使用QT Creator创建基于QT的工程。在QT官网下载最新的QT安装包,下载地址如下: [http://download.qt.io/official_releases/qt/ http://download.qt.io/official_releases/qt/] 打开链接页面如下: [[image:QT-Creator-install.png|800x407px]] 点击5.1,下载最新的安装包,得到名为<nowiki>qt-linux-opensource-5.1.1-x86-offline.ru</nowiki>n的文件,将它拷贝到ubuntu的用户目录,使用如下指令安装: ./ <nowiki>qt-linux-opensource-5.1.1-x86-offline.ru</nowiki>n 安装完成后,QT Creator也就安装完成了。 === 编译QT Creator默认示例 === 点击ubuntu图标,输入qt,将会查找含有qt的文件,同时,安装好的QT Creator也会被列出来,如下图所示: [[image:Build-QT-Creator-default.png|674x599px]] 点击QT图标,QT Creator将会运行,如下图所示: [[image:Build-QT-Creator-default1.png|674x599px]] 默认QT的配置是针对X86架构的,这时编译出来的示例只能在PC机上运行。我们打开Image Composition Example示例,它是一个图片叠加显示的示例,找到该示例,单击即可。打开后的界面如下: [[image:Build-QT-Creator-default2.png|674x599px]] 点击左下脚绿色的三脚箭头,开始编译工程。在Compile Output栏会显示编译的整个过程。编译完成后,提示如下: [[image:Build-QT-Creator-default3.png|674x599px]] 编译完成后,编译出来的映像会自动运行,一个叠加的蝴蝶图像界面显示出来了,界面如下: [[image:Build-QT-Creator-default4.png|674x599px]] 下面我们将该示例编译到开发板上运行。使用QT Creator打开上面的示例工程,如下图所示: [[image:Build-QT-Creator-default5.png|674x599px]] 选择Projects一栏,可以看到最顶端的框图1,显示Desktop Qt 5.1.1 GCC 64bit,表明它通过64位的GCC编译,框图2表明在debug模式下编译,相对release模式,debug模式下含有大量调试信息,编译出来的映像会比较大。通常发布映像时,我们选择release模式。框图3指定了编译的路径。框图4指定了qmake和交叉编译工具。框图5为调试按键,第一个用于选择编译模式为debug或release,第二个为运行按钮,第三个为单步调试按钮,第四个为编译按钮。框图6为一些输出信息,如Compile Output,会给出整个编译的信息。 在框图1中,点击Tools->Options,如下图: [[image:Build-QT-Creator-default6.png|674x599px]] 在左测对话框中选择Build & Run,在后边选择Qt Versions,默认Manual为空,Auto-detected选择的QT5.1默认的qmake,它将运行在X86平台的linux系统上,因此我们要手动添加在ARM平台上运行的qmake。 在buildroot编译文件系统时,我们选中QT5后,将会在buildroot的output/host/usr/bin目录生成支持ARM平台的qmake,点击Add,指向该路径的qmake: [[image:Build-QT-Creator-default7.png|674x599px]] 点击Open,即在Manual中添加了支持ARM平台的qmake。再选择Compilers一栏,如下图所示: [[image:Build-QT-Creator-default8.png|674x599px]] 默认Manual为空,Auto-detected为支持X86 32位和64位的GCC,这将直接导致编译出来只能在PC机上运行。点击Add,选择GCC,如下图所示: [[image:Build-QT-Creator-default9.png|674x599px]] 在Name中重命名,以区别ARM和PC平台,如我们命名为GCC-ARM-LINUX,它将会直接显示在前面QT工程界面的框图1中,到时我们编译QT工程时,能够一目了然,编译出来的到底是PC平台还是ARM平台。在Compiler path中指定交叉编译工具,在buildroot中默认已经自动下载并安装了交叉编译工具,我们指定到如下路径即可: buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-g++ 设置完成后,点击OK,完成设置。 再回到QT的工程界面,我们发现框图1中的配置仍然针对PC机,点击框图1中的Manage Kits,如下图所示: [[image:Build-QT-Creator-default10.png|674x599px]] 注意,这时默认Manual仍然为空,点击Add,会弹出一个有很多选项的对话框,我们按如下方式配置: [[image:Build-QT-Creator-default11.png|674x599px]] 这里的Name,我们可以点击Qt Versions,选择Manual中的qmake,下面就会有名称出来,将它拷贝过来即可,如下图所示: [[image:Build-QT-Creator-default12.png|674x599px]] 在框图一中,点击设置编译环境的下拉箭头,如下图所示: [[image:Build-QT-Creator-default13.png|674x599px]] 选择Change Kit->Qt5.1.1(System),更改后的界面如下: [[image:Build-QT-Creator-default14.png|674x599px]] 在框图2中选择release,更改后的界面如下: [[image:Build-QT-Creator-default15.png|674x599px]] 到此,配置完毕,点击框图5中的编译按钮,在Compile Output中可以看到编译信息如下: [[image:Build-QT-Creator-default16.png|674x599px]] 这时,在框图2中指定的目录中已经生成了能够在ARM平台运行的映像了,如下图所示: [[image:Build-QT-Creator-default17.png|674x599px]] 将该文件拷贝到x3399开发板上运行,可以看到美丽的蝴蝶图案显示出来了。 [[image:Build-QT-Creator-default18.png|674x599px]] ==qttest测试程序== ===使用QT_demo测试LED灯=== [[image:RK3399LED.jpg|1,024 × 600px|led]] 点击上面的四盏灯可以看到开发板led的灯的亮和灭。 ===使用QT_demo测试蜂鸣器=== 进入QT5.6.1系统后,默认会运行我们自主编写的测试demo,测试界面如下: [[image:QTtest-demo1-beep.png|1,024 × 600px]] 按住Beep键时,蜂鸣器鸣叫,松开时,蜂鸣器停止鸣叫。 ===使用QT_demo调节背光=== 测试界面如下: [[image:QTtest-demo2-backlight.png|1,024 × 600px]] 滑动圆形滑轮,可对开发板背光进行亮暗调节。 ===使用QT_demo测试按键=== 测试界面如下: [[image:QTtest-demo3-key.png|1,024 × 600px]] 按下开发板任一独立按键,图中界面即会显示相应键值,同时,按下时提示<nowiki>[</nowiki>keydown],抬起时提示<nowiki>[</nowiki>keyup]。 ===使用QT_demo测试音频=== 将喇叭或耳机接到开发板的对应接口,点击下图中的Play Sound按钮,会播放测试歌曲: [[image:QTtest-demo5-audio.png|800x469px]] ===使用QT_demo测试触摸屏=== 进入如下界面: [[image:RK3399touch.jpg|1,024 × 600px|ts]] 单击黄色矩形框,界面会进入全屏模式,这时我们可以任意书写来测试触摸屏了,测试示例图片如下: [[image:RK3399touch1.jpg|1,024 × 600px|ts1]] ===使用QT_demo测试网络=== 将网线连接开发板的有线以太网接口,点击界面中的Network Test按钮,如果网络已经连通,则会添加DNS,如果没有连通,则会提示相应错误,如下图所示: [[image:QTtest-demo9-internet.png|1,024 × 600px]] 连接网线后测试时,会有如下提示: [[image:QTtest-demo10-internet1.png|1,024 × 600px]] ===使用QT_demo测试TF卡=== [[image:RK3399tf.jpg|1,024 × 600px|tf]] [[image:RK3399tf1.jpg|1,024 × 600px|tf]] 将SD卡插入开发板的SD卡槽,点击Tfcard Test,界面上会列出SD卡中的内容。 [[image:QTtest-demo12-U.png|1,024 × 600px|tf1]] ===使用QT_demo测试重启=== 点击Reboot按钮,开发板将重启。 [[image:RK3399reboot.jpg|1,024 × 600px|reboot]] ===使用QT_demo测试关机=== 点击Poweroff按钮,开发板将会关机。 [[image:RK3399poweroff.jpg|1,024 × 600px|poweroff]] ==linux底层开发示例== ===播放mp3=== ===注:linux系统缺省登录账户为root,密码:123456=== 将存放有mp3文件的TF卡插到开发板的任意卡槽,使用如下命令挂载TF卡: <pre><nowiki> cd / mkdir sdcard mount /dev/mmcblk1p1 /sdcard cd sdcard </pre> 使用如下命令播放: ./mplayer *.avi ./mplayer *.mp3 连接串口后,可以通过PC键盘的0或9调节音量。也可以使用madplayer播放音乐。 ===在后台运行程序=== 在上一节中给出了播放音乐的示例,但是这时候mplayer已经占据了终端控制台,在音乐播放完之前,我们无法再使用终端控制台了。又比如我们开发一款产品时,就需要在启动文件系统后运行一个应用程序,如果运行了一个程序,终端控制台就被占用了,那将极大的限制我们的功能。为止,我们可以将程序放在后台运行。使用方法很简单,我们只需在执行的指令后面添加一个”&”即可。如播放音乐时使用如下命令: ./mplayer *.mp3 & ===中止程序的运行=== 中止程序的运行有多种方式,最直接的方式就是直接按ctrl+c。如前面我们正在播放一段音频文件,我们可以按ctrl+c退出程序。但是如果程序在后台运行,那么我们按ctrl+c就不管用了。这时我们可以使用kill命令。 kill+===PID=== kill+===文件名=== ===屏幕抓图=== 本文档中的各个图片,都是采用gsnap这个工具进行抓图的。进入QT图形界面后,我们能在LCD上看到丰富多彩的人机交互界面。通过gsnap可以抓取到图形界面精彩的瞬间。在控制台终端输入如下命令: gsnap <nowiki>test_pic.jp</nowiki>g /dev/fb0 这时在当前目录将会保存<nowiki>test_pic.jp</nowiki>g图像文件。详细的gsnap移植步骤在后面会有详细描述。 ===挂载TF卡=== 进入QT图形界面后,在命令终端会有控制台出现,这时可以通过控制台查看文件系统的内容。将TF卡插到开发板的任意卡槽,串口终端会有如下提示: <center>[[image:RK3399linux-1.png|1,899 × 299px]]</center> 这时在文件系统的/dev目录将会自动生成一个名叫mmcblk1p1的块设备文件。它就是对应的TF卡的设备文件,使用如下命令挂载TF卡到/sdcard目录: mkdir /sdcard mount /dev/mmcblk1p1 /sdcard 查看/scard目录下的内容,即是我们TF卡中的内容,如下图所示: <center>[[image:RK3399linux-2|1,905 × 378px]]</center> ===挂载U盘=== 进入QT图形界面后,在命令终端会有控制台出现,这时可以通过控制台查看文件系统的内容。插入U盘后,串口终端会有如下提示: <center>[[image:RK3399linux-3.png|1,882 × 304px]]</center> 这时在文件系统的/dev目录将会自动生成一个名叫sda4的块设备文件。它就是对应的U盘设备文件,使用如下命令挂载U盘到/udisk目录: mkdir /udisk mount /dev/sda4 /udisk 查看/udisk目录下的内容,即是我们U盘中的内容,如下图所示: <center>[[image:RK3399linux-4.png|1,873 × 241px]]</center> ===保存系统时钟=== Linux可以使用date指令更改时间日期。例如: date -s 201607211433 设置为2016年7月21日14:33分 hwclock -w 把刚设置的时间存入RTC寄存器 hwclock -s 恢复linux系统时钟为RTC寄存器值,一般将该指令放在rcS中开机自动执行。 [[image:RK3399linux-5.png|1,123 × 139px]] ===掉电保存数据到flash=== 由于本系统采用了ext4文件系统,因此可以很方便的保存数据,确保掉电后数据不丢失。如我们从U盘中拷备一首歌曲到/root目录: cp /udisk<nowiki>/muyangqu.mp</nowiki>3 / 重启开发板,我们发现在root目录仍然存在刚才拷备的这首歌曲,说明掉电后数据并没有丢失。 ===设置开机自动运行程序=== 借助启动脚本可以设置各种程序开机后自动运行,这点很类似于WINDOWS的Autobat自动批处理文件。启动脚本位于/etc/init.d/rcS中,我们可以将自己想要开机运行的程序或是开机执行的指令放在rcS里面。比如我们想制作一个简单的开机音乐,我们就完全可以在rcS中添加如下语句: ./mplayer <nowiki>start.mp</nowiki>3 & 这时,开机后就会播放名叫<nowiki>start.mp</nowiki>3的音乐了。注意<nowiki>start.mp</nowiki>3需要在当前执行指令所在目录。 ===查看开发板内存信息=== X3399开发板默认配置2GB LPDDR3 SDRAM,在uboot启动时,打印信息上会给出RAM大小信息: <center>[[image:RK3399linux-6.png|1,096 × 570px]]</center> 在进入文件系统后,可以通过cat命令查询Linux系统分配到的SDRAM大小。执行如下命令: cat /proc/meminfo <center>[[image:RK3399linux-7.png|1,106 × 525px]]</center> ==linux应用开发示例== 本手册给出的所有应用程序全部在九鼎创展x3399开发板上运行,这里仅给出了一些比较基础,常用的应用程序,旨在为用户打开Linux世界奇妙的大门,用户定能举一反三,编写出属于自己的更加丰富完美的程序。 声明:以下所有应用程序全部为九鼎创展科技有限公司原创作品,所有内容全经我们严格测试,建议用户按照下面步骤动手编译一遍,以增强自己的理解,不推荐直接使用我们提供好的文件。另外,敬请商业人士勿侵犯版权。 ===Hello World=== 第一步:生成可执行文件 在x3399_marshmallow目录新建app-ex目录,在app-ex目录新建hello目录,然后在hello目录下新建hello.c和makefile两个文件: vim hello.c <center>[[image:RK3399linux-app1.png|307 × 109px]]</center> 这是一个最基础的应用程序,如果我们声明了交叉编译工具(export PATH=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/bin$PATH)(这里我们用到buildroot中的交叉编译工具),可以直接敲入命令进行编译(由于开发板环境缺少c库,编译时需要加上-static静态编译): arm-linux-gcc-4.4.3 -o hello hello.c -static 说明:由于开发板文件系统缺少标准函数库,编译时加上-static选项;使用的编译器为aarch64-linux-gnu-gcc。 编译完成后,在当前目录会生成hello可执行文件,我们可以使用file命令查询执行文件是否为ARM体系文件: [[image:RK3399linux-app2.png|1,123 × 74px]] 第二步:将可执行文件下载到开发板运行 比较常用的方式有以下四种: *通过串口和sz/rz工具 *复制到存储媒介,如SD卡,U盘等 *通过NFS挂载文件系统,这时不用将可执行文件拷备到开发板了,推荐调试使用这种方式! *通过ftp传输 这里介绍第二种方法,以TF卡为例,其他方法请读者自行尝试。 将生成的hello文件拷备到TF卡,再将TF卡插入开发板的TF卡接口,将TF卡mount到/mnt目录: cd / mount /dev/mmcblk1p1 /mnt 进入mnt目录,可以看到刚才拷贝的hello文件了: [[image:RK3399linux-app3.png|948 × 85px]] 运行hello: ./hello 打印信息如下: <center>[[image:RK3399linux-app4.png|967 × 135px]]</center> 表明,程序已经成功运行。 前面编译文件我们需要通过手敲命令执行,我们可以通过编写makefile来代替手敲的动作。 在hello目录下新建makefile文件:vim makefile hello aarch64-linux-gnu-gcc –o hello hello.c –static clean rm –f hello *.o 直接在hello目录下敲make就可以生成hello文件。运行的效果和前面的完全相同。 ===数学函数库调用=== 建立程序编译路径: <pre><nowiki> mkdir math cd math vim math.c </pre> 编辑如下内容: <pre><nowiki> <nowiki>include <</nowiki>stdio.h> <nowiki>include <</nowiki>stdlib.h> <nowiki>include <</nowiki>math.h> int main(void) { double a=9.0; printf("sqrt(%f)=%f\n",a,sqrt(a)); return 0; }</pre> 编辑makefile文件,内容如下: <pre><nowiki> OBJS=math.o LDFLAGS = -lm -static CC = yourtoolchainpath/bin/aarch64-linux-gnu-gcc math${OBJS} ${CC} -o $@ $^ $(LDFLAGS) clean rm -f math *.o </pre> 执行make,将生成的可执行文件math下载到开发板上运行,如下图所示: [[image:RK3399linux-app5.png|958 × 99px]] ===多线程编程示例=== 建立程序编译路径: <pre><nowiki> mkdir thread cd thread vim thread.c </pre> 编辑如下内容: <pre><nowiki> <nowiki>include<</nowiki>stddef.h> <nowiki>include<</nowiki>stdio.h> <nowiki>include<</nowiki>unistd.h> <nowiki></nowiki>include"pthread.h" void function1(void); void function2(void); int func_flag=0; pthread_mutex_t mutex; main() { pthread_t reader; pthread_mutex_init(&mutex,NULL); pthread_create(&reader,NULL,(void*)&function1,NULL); function2(); } void function2(void) { while(1) { pthread_mutex_lock(&mutex); if(func_flag==0) { printf("excute function2.\n"); func_flag=1; } pthread_mutex_unlock(&mutex); } } void function1(void) { while(1) { pthread_mutex_lock(&mutex); if(func_flag==1) { printf("excute function1.\n"); func_flag=0; } pthread_mutex_unlock(&mutex); } } </pre> 编辑makefile文件,内容如下: <pre><nowiki> OBJS=thread.o LDFLAGS = -lpthread -static CC = yourtoolchainpath/bin/aarch64-linux-gnu-gcc thread${OBJS} ${CC} -o $@ $^ $(LDFLAGS) clean rm -f thread *.o </pre> 执行make,将生成的可执行文件thread下载到开发板上运行,如下图所示: <center>[[image:RK3399linux-app6.png|821 × 125px]]</center> ===多进程编程示例=== 在Linux下通用调用fork函数创建新的进程。调用fork时,系统将产生一个与当前进程相同的进程。它与原有的进程具有相同的数据,连接关系和在程序同一处执行时的连续性。通常将原有的进程叫父进程,新创建的进程叫子进程。 fork调用将分两次返回,从父子进程返回。进程创建语法如下: <pre><nowiki> <nowiki>include <</nowiki>unistd.h> pid_t pid; pid = fork(); </pre> 如果pid返回0,表示说明从子进程返回,否则从父进程返回,此时返回的是进程的ID号。我们可以通过getpid()函数来获得进程的ID号。 首先建立程序编译目录: <pre><nowiki> mkdir process cd process vim process.c </pre> 编辑如下内容: <pre><nowiki> <nowiki>include<</nowiki>stdio.h> <nowiki>include<</nowiki>unistd.h> <nowiki>include<sys/</nowiki>types.h> main() { pid_t pid; pid=fork(); if (pid<0) { printf("fork is error!\n"); return 1; } else if (pid == 0) { while (1) { printf("the child process is running <nowiki>now.pi</nowiki>d=%d\n",getpid()); sleep(1);//linux延时函数,延时1秒 } } else { while (1) { printf("the perent process is running <nowiki>now.pi</nowiki>d=%d\n",getpid()); sleep(1); } } return 0; } </pre> 编辑makefile文件,内容如下: <pre><nowiki> OBJS=process.o LDFLAGS = -lpthread -static CC = yourtoolchainpath/bin/aarch64-linux-gnu-gcc process${OBJS} ${CC} -o $@ $^ $(LDFLAGS) clean rm -f process *.o </pre> 执行make编译,将生成的可执行文件下载到开发板运行,仔细观察串口监控信息: <center>[[image:RK3399linux-app7.png|967 × 210px]]</center> ===makefile编程示例=== 在上面的很多测试程序实例中,我们都编写了一些简单的makefile文件。下面我们介绍makefile的基本的语法。 makefile就好比批处理文件,里面写了一系列集合,当运行make编译时,便会按makefile提供的命令及顺序完成编译。 这里我们给出三个文件:main.c,func.c,func.h。主程序在main.c中,在main.c中程序会调用func.c中的函数,func.c中的函数又会用到func.h中定义的变量。 main.c文件内容如下: <pre><nowiki> <nowiki>include "</nowiki>func.h" extern int fd; int main(int argc,char **argv) { fd = open(DEVICE_NAME,0);//打开设备 if(fd == -1) { printf("open device %s error \n",DEVICE_NAME); return 0; } else { printf("open device %s ok! \n",DEVICE_NAME); } while(1) { glint_led(); } close(fd); return 0; } </pre> 该文件会调用glint_led ()函数,这个函数在func.c中。func.c的内容如下: <pre><nowiki> <nowiki>include "</nowiki>func.h" void glint_led(void) { ioctl(fd,LED_ON); sleep(1); ioctl(fd,LED_OFF); sleep(1); } </pre> 这里仅仅是一个读取按键的函数,供main函数调用。该函数需要用到了一些变量,另外还需要一些头文件支持,这些都存放在func.h中,其内容如下: <pre><nowiki> <nowiki>include <</nowiki>stdio.h> <nowiki>include <</nowiki>stdlib.h> <nowiki>include <</nowiki>unistd.h> <nowiki>include <sys/</nowiki>ioctl.h> <nowiki>define DEVICE_NAME</nowiki> "/dev/vib" <nowiki>define LED_ON 0x11</nowiki> <nowiki>define LED_OFF 0x22</nowiki> int fd; </pre> 很明显,这是基于LED测试程序,人为的分成的三个文件。我们的目的不在于分离代码,而在于学习makefile的编写方法。 当不使用makefile时,我们使用如下指令编译: aarch64-linux-gnu-gcc-gcc -o mkfile main.c func.c 编译完成后,将会生成可执行文件mkfile。将它下载到开发板上运行,和前面的按键测试完全相同。现在我们尝试编写第一个属于自己的makefile <pre><nowiki> mkfilemain.o func.o aarch64-linux-gnu-gcc -o mkfilemain.o func.o main.omain.c aarch64-linux-gnu-gcc -c main.c -o main.o func.ofunc.c func.h aarch64-linux-gnu-gcc -c func.c -o func.o clean rm -f mkfile *.o </pre> 执行make后,编译器会依次编译main.c和func.c文件,生成main.o和func.o文件,最后将这两个.o文件打包到可执行文件mkfile中。这时将mkfile文件下载到开发板运行,效果和前面的是一样的。我们可以执行make clean指令清除生成的.o文件和可执行文件。 makefile具有很强大的推理功能,我们完全可以简化上面的代码。优化后的代码如下: <pre><nowiki> OBJS=main.o func.o CC= aarch64-linux-gnu-gcc mkfile${OBJS} ${CC} -o $@ $^ main.o func.ofunc.h clean rm -f mkfile *.o </pre> 可见,这次比上面的完整版要简化多了。前面通过变量OBJS定义了要编译的源文件,变量CC给出了交叉编译工具。$@ 表示目标文件的全称,即mkfile,$^表示所有被依赖的文件,并以空格分开,即main.o func.o。后面的clean为清除指令,执行make clean后会执行 clean后面的指令。需要注意的是,rm指令后面千万不要使用$@符号来表征我们要删除的目标文件,因为这时候$@已经不再表示mkfile了,而表示clean。同样,使用make指令编译,一样能够生成我们需要的目录文件mkfile。 上面的makefile使用了变量以及预定义变量。第一句即定义了变量OBJS,将它赋值为main.o func.o,第二句定义了变量CC,将它赋值为一个交叉编译工具定义。引用变量时,通过${*}表示,这里*表示前面定义的变量。 上面使用了$@和$^两个预定义变量,GNU make主要有以下七种预定义变量: {| class="wikitable" |- | <center>$*</center> | 不包含扩展名的目标文件名称 |- | <center>$+</center> | 所有的依赖文件,以空格分开,以出现的先后为序,可能包含重复的依赖文件 |- | <center>$<</center> | 第一个依赖文件的名称 |- | <center>$?</center> | 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚 |- | <center>$@</center> | 目标的完整名称 |- | <center>$^</center> | 所有的依赖文件,以空格分开,不包含重复的依赖文件 |- | <center>$%</center> | 如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称为<nowiki>mytarget.so</nowiki>(image.o),则$@ 为<nowiki>mytarget.so</nowiki>,而$% 为image.o。 |} 对比以上几种编译方式,我们不然发现,其实最简的还是第一种,因为它就一句话就搞定了。那么在makefile中,我们是否也可以精简到只有一句话呢?答案是肯定的。我们继续利用makefile强大的推理功能进行简化,得到如下makefile代码: <pre><nowiki> OBJS=main.o func.o CC= aarch64-linux-gnu-gcc mkfile${OBJS} ===${CC} -o $@ $^=== clean rm -f mkfile *.o </pre> 这次,makefile真正编译的代码,就只有上面红色部分一条指令了。和前面比较,不难发现,单独对main.c和func.c两个文件编译的指令已经去掉了。前面我们提到,makefile具有强大的推理功能,我们在生成目标文件mkfile时,makefile会推理出它需要main.c和func.c两个文件,因此它首先就会去编译这两个文件,最后再执行目标文件的生成。因此我们完全可以将它们省去。 这里只是makefile的一点基础,读者可以借助于其他书籍对makefile作更深一层的了解。 ===mplayer移植=== 有两种移植mplayer,第一种方法就是直接下载mplayer源码包,手动配置编译环境,再通过交叉编译环境编译。该方法比较传统,我们有更方便的方法,直接在buildroot中选中mplayer,再make即可,buildroot会自动下载mplayer源码包,自动配置编译环境并编译。 在buildroot的menuconfig配置选项中,进入Target packages-> Audio and video applications选项,选中mplayer,如下图所示: [[image:RK3399linux-app8.png|1,366 × 768px]] 保存退出,在buildroot下直接make,生成文件系统后更新到开发板,mplayer就打包进文件系统了。 ===madplayer移植=== madplayer的移植方法和mplayer的移植方法完全雷同,直接在buildroot中选中madplayer的选项,再make即可。 ===屏幕抓图工具gsnap移植=== 屏幕抓图的方法有多种,有不少爱好者自己动手写抓图小程序。这里我们使用JPEG库来处理。具体用到了<nowiki>jpegsrc.v6b.tar.gz</nowiki>和<nowiki>gsnap.tar.gz</nowiki>两个源码包(这2个压缩包请读者自己到网络上面下载)。 一:安装libjpeg 解压jpeg库源码包,进入根目录: tar zxf <nowiki>jpegsrc.v6b.tar.gz</nowiki> cd jpeg-6b 二:配置编译环境: <pre><nowiki> ./configure --prefix=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain --exec-prefix=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain --target=arm-linux --enable-shared --enable-static CC=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu-gcc AR=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu-ar rc AR2=/home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu-ranlib </pre> 三:配置好之后,make编译,如果提示缺少libtool文件: [[image:RK3399linux-app9.png|1,292 × 76px]] 下载<nowiki>libtool-2.2.6a.tar.gz</nowiki>,解压编译获得libtool工具。 [[image:RK3399linux-app10.png|1,122 × 47px]] 再make clean,重复之前的第二步:配置编译环境。 四:在x3399_marshmallow/buildroot/output/host/opt/ext-toolchain下建立man/man1目录: cd x3399_marshmallow/buildroot/output/host/opt/ext-toolchain mkdir -p man/man1 五:编译,安装 make make install 这时,在x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/man/man1目录下将会生成以下文件: cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 wrjpgcom.1 在x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/lib目录下生成以下文件: libjpeg.a <nowiki>libjpeg.la</nowiki> <nowiki>libjpeg.so</nowiki> <nowiki>libjpeg.so</nowiki>.62 <nowiki>libjpeg.so</nowiki>.62.0.0 六:解压gsnap tar zxf <nowiki>gsnap.tar.gz</nowiki> cd gsnap 七:修改makefile <pre><nowiki> all /home/lixu/projects/3399/x3399_marshmallow/buildroot/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu-gcc -g gsnap.c -ljpeg -o gsnap –static clean rm -f gsnap </pre> 八:编译,得到可执行文件gsnap make 九:将jpeg库文件复制到文件系统的lib目录,注意保持文件的链接属性 cp -a libjpeg.s* “文件系统路径”/lib 十:将可执行文件gsnap复制到文件系统的sbin目录 cp gsnap “文件系统路径”/sbin 十一:重新制作文件系统,下载到开发板上,使用如下命令即可截获图形界面: gsnap <nowiki>1.jp</nowiki>g /dev/fb0 同样可以将图片保持为bmp,png等其他格式。
返回至
RK3399 Linux Manual
。