全志F1C100s开发实战:从uboot到Linux Kernel与buildroot的完整构建指南
1. 开篇为什么选择全志F1C100s与荔枝派Nano如果你对嵌入式Linux开发感兴趣想找一块成本极低、资料相对丰富、又能玩转完整Linux系统的开发板那么全志F1C100s芯片和基于它的荔枝派Nano绝对是一个绕不开的“明星”组合。我当初入手这块板子就是看中了它几十块钱的价格和“麻雀虽小五脏俱全”的特性。它集成了ARM9核心、32MB DDR内存还能直接驱动RGB液晶屏玩点小项目或者学习嵌入式系统构建性价比简直无敌。但是性价比高的另一面往往意味着“坑”也不少。官方资料可能比较分散社区教程版本新旧不一新手很容易在uboot编译、内核配置、文件系统制作这几个环节卡住最后板子成了“砖头”或者“吃灰神器”。我自己就经历过编译好的内核死活起不来或者系统跑起来了但屏幕不亮这种让人头大的情况。所以这篇文章的目的就是把我自己从零开始给F1C100s构建一套完整可运行系统uboot Linux Kernel buildroot根文件系统的实战过程原原本本地分享出来。这不是一个简单的命令罗列我会重点讲清楚每个步骤背后的“为什么”以及我踩过的那些“坑”和解决办法。我们的目标很明确让你拿到板子后能跟着指南一步步走最终看到一个跑着Linux、能操作命令行的完整系统点亮屏幕获得最初始的成就感。这份指南会尽量做到小白友好即使你之前没怎么玩过ARM Linux也能跟着一步步操作下来。2. 开发环境搭建与源码获取工欲善其事必先利其器。在开始编译之前一个干净、可靠的开发环境是成功的一半。我强烈建议使用Ubuntu 20.04 LTS或22.04 LTS作为开发主机系统无论是实体机还是虚拟机都可以。Windows下的WSL2虽然也能用但在涉及USB设备烧录时可能会多一层麻烦所以首推纯Linux环境。2.1 安装必备的编译工具链第一步我们需要安装ARM架构的交叉编译工具链。所谓交叉编译就是在我们的x86电脑上编译出能在ARM芯片上运行的代码。打开终端执行以下命令来安装sudo apt update sudo apt install gcc-arm-linux-gnueabi g-arm-linux-gnueabi -y安装完成后可以验证一下arm-linux-gnueabi-gcc --version如果能看到类似arm-linux-gnueabi-gcc (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0的输出说明工具链安装成功了。这里我们用的是gnueabi而非gnueabihf因为F1C100s的ARM926EJ-S核心不支持硬件浮点单元需要用软浮点工具链。接下来安装其他必要的开发工具比如用于内核配置的ncurses库以及后续烧录会用到的libusbsudo apt install build-essential libncurses5-dev libusb-1.0-0-dev git wget bc -y2.2 获取三大核心源码我们需要三份关键的源代码uboot系统引导程序、Linux内核、以及buildroot用于生成根文件系统。为了保证网络通畅和速度我们优先使用国内镜像仓库。获取uboot源码git clone https://gitee.com/LicheePiNano/u-boot.git cd u-boot # 查看所有分支我们需要切换到针对Nano板子的分支 git branch -a git checkout nano-v2020.01 # 或者 nano-lcd800480根据你的屏幕来后面会详述这里有个关键点uboot的版本和分支选择很重要。太老的版本可能缺少对新屏幕的支持太新的版本又可能不稳定。我实测下来nano-v2020.01这个分支比较稳定通用。如果你有特定的屏幕比如800x480也可以选择对应的分支。获取Linux内核源码git clone https://gitee.com/LicheePiNano/Linux.git cd Linux # 内核源码一般使用特定的配置分支先不用切换默认的master分支通常就包含了我们需要的配置这个仓库是社区维护的已经为F1C100s和荔枝派Nano做了很多适配工作省去了我们从头配置的巨量工作。获取buildroot源码 Buildroot是一个自动化程度很高的工具它帮你管理交叉编译链、编译各种库和软件最终打包成一个完整的根文件系统。我们下载一个长期支持版本wget https://buildroot.org/downloads/buildroot-2021.02.4.tar.gz tar xvf buildroot-2021.02.4.tar.gz cd buildroot-2021.02.4为什么选2021.02.4因为它比较稳定与F1C100s的社区支持状态匹配良好不容易出现新版本带来的兼容性问题。当然你也可以尝试更新的版本但可能需要自己解决一些依赖问题。环境准备好源码也拉取完毕我们的“食材”就备齐了。接下来开始第一道“硬菜”编译和配置uboot。3. U-Boot的配置、编译与屏幕适配U-Boot相当于嵌入式系统的“BIOS”它负责初始化最基础的硬件如DDR内存、时钟、存储设备然后加载并启动Linux内核。对于F1C100suboot还需要负责初始化SPI Flash因为我们的系统通常就烧录在里面。3.1 基础配置与编译进入之前克隆的u-boot目录首先应用一个针对荔枝派Nano的默认配置make ARCHarm CROSS_COMPILEarm-linux-gnueabi- f1c100s_nano_uboot_defconfig这条命令告诉make系统目标架构是ARM使用的交叉编译工具前缀是arm-linux-gnueabi-并应用名为f1c100s_nano_uboot_defconfig的默认配置。这个配置默认支持从SPI Flash启动。如果你的板子是最早的版本可能只支持从TF卡启动那么可以尝试licheepi_nano_defconfig。应用默认配置后我们可以进行更细致的图形化配置make ARCHarm menuconfig一个基于ncurses的配置界面会弹出来。在这里你可以浏览和修改成百上千个配置项。对于新手我建议先不要乱动除非你有明确的需求。我们本次编译的核心目标之一是让LCD屏幕显示出来。3.2 关键步骤让LCD屏幕亮起来屏幕不亮是新手遇到最多的问题之一。问题往往出在uboot和内核两边的配置不匹配。我们首先解决uboot这边的显示支持。在make menuconfig的界面中你需要找到以下关键配置项并启用进入ARM architecture菜单。找到Enable graphical uboot console on HDMI, LCD or VGA选项按Y键将其编译进uboot显示为[*]。找到LCD panel timing details选项它可能在同一级菜单或子菜单下。这里需要输入你屏幕的详细时序参数。这是一个大坑参数不对屏幕要么无显示要么花屏。以最常见的800x480分辨率屏幕为例你需要将LCD panel timing details设置为x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:40,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0我来解释一下这些参数xy 分辨率宽和高。depth 颜色深度18表示18位色RGB666这是很多廉价屏的配置。如果是16位色RGB565则填16。pclk_khz 像素时钟频率单位KHz这个值至关重要必须从你的屏幕数据手册datasheet里找到。33000即33MHz是很多800x480屏的典型值但不保证是你的屏的值。leriuplo 分别对应水平/垂直的左右/上下边沿Back porch Front porch。这些时序参数也请务必查阅屏幕手册。hsvs 行同步和场同步脉冲宽度。sync和vmode 同步极性模式通常填3和0。怎么获取这些参数最好的方法是找到屏幕的规格书。如果找不到可以尝试在荔枝派社区搜索你的屏幕型号或者使用卖家提供的参数。实在不行对于800x480屏可以先用上面这组参数试试有概率成功。配置完成后保存退出。接下来就可以开始编译了make ARCHarm CROSS_COMPILEarm-linux-gnueabi- -j$(nproc)-j$(nproc)表示使用你电脑所有的CPU核心进行并行编译加快速度。编译成功后在u-boot目录下会生成一个非常重要的文件u-boot-sunxi-with-spl.bin。这个文件包含了SPLSecondary Program Loader相当于uboot的前置引导和主uboot是我们要烧录到SPI Flash最前端的镜像。至此uboot部分暂时告一段落。我们得到了一个希望能驱动屏幕的引导程序。接下来我们需要一个能和这个uboot配合工作的Linux内核。4. Linux内核的配置、编译与设备树修改如果说uboot是引路人那么Linux内核就是系统的大脑和中枢神经。它管理着所有的硬件资源为应用程序提供运行环境。为F1C100s编译内核核心在于两点一是选择正确的CPU架构和驱动二是正确配置设备树Device Tree来描述我们的硬件。4.1 应用默认配置与内核编译进入Linux内核源码目录首先应用为F1C100s准备好的默认配置make ARCHarm f1c100s_nano_linux_defconfig这个配置已经包含了F1C100s芯片的基本驱动如UART、SPI、MMC/SD卡等。同样我们也可以进行图形化配置但初期建议先使用默认配置确保能启动起来。make ARCHarm menuconfig在图形界面里你可以浏览驱动模块比如如果需要USB网络、声卡等可以在这里按M编译为模块或按Y直接编译进内核。对于初学保持默认即可。接下来是漫长的编译过程分为三步编译内核镜像make ARCHarm CROSS_COMPILEarm-linux-gnueabi- -j$(nproc)编译内核模块make ARCHarm CROSS_COMPILEarm-linux-gnueabi- -j$(nproc) INSTALL_MOD_PATH./output modules安装模块到指定目录为后续打包进文件系统做准备make ARCHarm CROSS_COMPILEarm-linux-gnueabi- -j$(nproc) INSTALL_MOD_PATH./output modules_install编译完成后在arch/arm/boot/目录下会生成压缩的内核镜像文件zImage。这就是我们要烧录的Linux内核。4.2 设备树Device Tree的奥秘与修改设备树是嵌入式Linux中一个非常重要的概念。你可以把它理解成一份写给内核的“硬件说明书”以.dts文件的形式存在编译后生成二进制的.dtb文件。内核在启动时会读取这份“说明书”从而知道这块板子上有什么硬件、地址在哪里、如何初始化。对于荔枝派Nano设备树文件通常是arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts要让内核驱动我们的LCD屏幕必须修改这个设备树文件。用编辑器打开它找到描述显示接口的部分。通常它会有一个panel节点。我们需要将compatible属性修改为内核中已有的、匹配我们屏幕的驱动。例如对于很多800x480的LCD屏幕可以修改为panel: panel { compatible lg,lb070wv8, simple-panel; // ... 其他属性如 backlight, enable-gpios 等 };这里的lg,lb070wv8是一个具体的屏幕型号标识内核里可能有对应的驱动。simple-panel是一个通用面板驱动。修改这里的目的是让内核在启动时能成功匹配并初始化你的屏幕。另一个关键点你还需要在设备树中确认或修改display子系统和framebuffer的配置确保它指向正确的panel节点并且时序参数display-timings与你的屏幕匹配。时序参数的意义和uboot里类似同样需要从屏幕手册获取。很多时候uboot能点亮但内核点不亮就是因为两边的时序参数不一致。修改完设备树后需要重新编译设备树make ARCHarm CROSS_COMPILEarm-linux-gnueabi- dtbs编译后在arch/arm/boot/dts/目录下会生成对应的suniv-f1c100s-licheepi-nano.dtb文件。至此我们得到了内核镜像zImage和设备树二进制文件.dtb。它们和uboot一样都是系统启动的必需品。接下来我们需要为系统创造一个“家”——根文件系统。5. 使用Buildroot构建轻量级根文件系统内核启动后需要挂载一个根文件系统Root Filesystem里面包含了系统运行所必需的所有目录结构、配置文件、系统工具如lscp和用户程序。自己从头制作一个文件系统非常复杂而Buildroot正是用来简化这个过程的利器。它像是一个自动化工厂你通过菜单选择需要的软件包和配置它就能帮你从头编译出一个完整的、可定制的根文件系统。5.1 Buildroot基础配置进入buildroot目录首先启动配置界面make menuconfig这里选项非常多我们聚焦几个最关键的Target optionsTarget Architecture- 选择ARM (little endian)Target Variant- 选择arm926t对应F1C100s的ARM9核心ToolchainToolchain type- 选择Buildroot toolchain使用Buildroot自带的交叉工具链更省心C library- 选择musl。强烈推荐musl是一个极其轻量化的C库相比glibc它能显著减少最终根文件系统的大小对于只有32MB内存的F1C100s来说这是非常重要的优化。System configurationRoot password- 设置一个你喜欢的root用户密码比如licheepi。Run a getty (login prompt) after boot-务必启用。这样系统启动后才会在串口终端显示登录提示。/dev management- 选择Dynamic using devtmpfs mdev。这是设备文件管理方式mdev是Busybox提供的轻量级方案适合小系统。Target packages 这里是软件包选择的天地。你可以根据需求勾选Busybox 默认已选它是嵌入式系统的“瑞士军刀”提供了精简版的绝大多数常用命令。Linux kernel不要在这里选因为我们已经在外部手动编译了内核。你可以按需添加dropbearSSH服务器、wireless-toolsWiFi工具、alsa-utils音频工具等。5.2 编译与输出配置完成后保存退出。接下来就是执行编译这个过程会比较长因为Buildroot要从网上下载各种软件包的源码并逐个编译make泡杯咖啡等待编译完成。成功后在output/images/目录下你会找到几个重要的文件rootfs.tar 这是我们需要的根文件系统打包文件。可能还有rootfs.ext2rootfs.jffs2等不同格式的镜像。对于SPI Flash我们通常使用jffs2或squashfs这类支持压缩、适合只读存储的文件系统格式。但Buildroot默认生成的rootfs.tar是通用的我们可以用它来制作jffs2镜像。现在uboot、内核、文件系统这“三驾马车”我们都准备好了。最后一步也是最考验耐心的一步就是把它们正确地“安装”到板子的SPI Flash里。6. 系统烧录使用sunxi-tools将镜像写入SPI FlashF1C100s芯片有一个非常方便的“FEL模式”。在这个模式下芯片可以通过USB接口接受来自电脑的指令直接对SPI Flash进行编程相当于一个内置的“编程器”。我们需要的工具就是sunxi-tools。6.1 编译和安装sunxi-tools首先获取针对F1C100s SPI Flash支持的sunxi-tools分支git clone https://github.com/Icenowy/sunxi-tools.git -b f1c100s-spiflash cd sunxi-tools make sudo make install安装后系统里就会有sunxi-fel这个关键工具。6.2 进入FEL模式与烧录这是整个流程中最“物理”的一步找到板子上SPI Flash芯片的第一脚通常有个小圆点标记。用杜邦线将这一脚与板子上的GND地引脚短接。在短接状态下给板子上电通过USB口供电。上电后保持短接约1-2秒然后断开。此时板子就进入了FEL模式。在电脑上打开终端输入sudo sunxi-fel ver如果看到类似AWUSBFEX soc00001663的芯片信息输出恭喜你电脑已经成功识别到处于FEL模式的F1C100s了接下来按照严格的顺序烧录三个镜像烧录U-Boot(到Flash的0地址)sudo sunxi-fel -p spiflash-write 0 /path/to/your/u-boot/u-boot-sunxi-with-spl.bin-p参数表示显示进度条。这一步会把uboot写到Flash的最开头。烧录设备树DTB文件(到0x100000地址即1MB偏移处)sudo sunxi-fel -p spiflash-write 0x100000 /path/to/your/Linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb烧录Linux内核zImage(到0x110000地址紧接着DTB之后)sudo sunxi-fel -p spiflash-write 0x110000 /path/to/your/Linux/arch/arm/boot/zImage6.3 制作并烧录JFFS2根文件系统镜像Buildroot生成的rootfs.tar不能直接烧录需要转换成SPI Flash友好的jffs2格式。 首先将rootfs.tar解压到一个临时目录mkdir rootfs sudo tar -xvf output/images/rootfs.tar -C ./rootfs然后使用mkfs.jffs2工具制作镜像。这里的参数非常关键-s 0x100 页大小Page Size对于大多数SPI Nor Flash是256字节0x100。-e 0x10000 擦除块大小Erase Block Size通常是64KB0x10000。这个值必须和你的Flash芯片规格一致请查阅你的Flash芯片数据手册如W25Q128。--pad0xAF0000 指定最终镜像文件的大小。这个大小决定了文件系统在Flash中的分区大小。需要根据你的Flash总容量和前面uboot、内核占用的空间来计算。例如总容量8MB0x800000uboot内核dtb约占1.1MB那么给根文件系统预留约6.9MB0xAF0000是合理的。-d rootfs/ 输入目录。-o jffs2.img 输出镜像文件名。sudo mkfs.jffs2 -s 0x100 -e 0x10000 --pad0xAF0000 -d rootfs/ -o jffs2.img最后烧录这个根文件系统镜像到Flash的尾部区域例如从0x510000开始sudo sunxi-fel -p spiflash-write 0x510000 ./jffs2.img烧录全部完成后断开USB线再重新上电。此时板子应该从SPI Flash正常启动。如果你连接了串口调试工具强烈建议会在串口终端看到uboot的启动日志接着是Linux内核的启动信息最后如果一切顺利会出现登录提示符licheepi login:。输入root和你设置的密码你就成功进入了自己构建的Linux系统7. 常见问题排查与实战经验分享即使按照步骤一步步来也难免会遇到问题。这里分享几个我踩过的“坑”和解决办法。问题一内核启动后卡住提示“No working init found”或直接重启。这是最令人沮丧的错误之一。根本原因是内核找不到、或者无法执行根文件系统里的/sbin/init或/bin/sh。可能的原因和排查步骤根文件系统镜像制作错误 确保mkfs.jffs2的-e擦除块大小参数完全匹配你的Flash芯片。参数不对会导致文件系统无法挂载。用sudo sunxi-fel spiflash-read 0x510000 0x10000 read_back.bin命令读回一段Flash数据用hex编辑器看看开头是否是jffs2的文件系统魔数。内核启动参数错误 uboot需要告诉内核根文件系统在哪里。检查uboot环境变量中的bootargs。对于SPI Flash上的JFFS2通常需要类似root/dev/mtdblock2 rootfstypejffs2 rw consolettyS0,115200这样的参数。确保mtdblock的编号对应正确的Flash分区。文件系统不完整 确保rootfs.tar解压和制作镜像过程没有报错并且包含了必要的/sbin/init/bin/sh/dev/console等文件。问题二屏幕在uboot阶段有显示进入内核后黑屏。这几乎是时序参数或设备树配置问题。核对时序 确保内核设备树display-timings里的时序参数和uboot里配置的LCD panel timing details完全一致。哪怕一个参数对不上都可能导致显示异常。检查内核驱动 在内核的make menuconfig中确认Device Drivers - Graphics support - Frame buffer Devices - Support for frame buffer devices以及其下的Simple framebuffer driver或Framebuffer Console support已启用。同时检查Device Drivers - Staging drivers下是否有你屏幕的特定驱动如lg,lb070wv8并启用。查看内核日志 通过串口查看内核启动日志搜索fbpaneldisplay等关键词看是否有驱动加载失败或 probe 错误的信息。问题三uboot无法从SPI Flash启动。确认uboot配置 编译uboot时是否使用了f1c100s_nano_uboot_defconfig支持SPI Flash启动如果用了licheepi_nano_defconfig它可能默认是从SD卡启动的。检查Flash型号支持 不同的SPI Flash芯片如Winbond的W25Q系列GD的GD25Q系列指令集略有差异。uboot的驱动可能没有默认支持你的Flash。需要查看drivers/mtd/spi/spi_flash_ids.c等文件添加你的Flash芯片ID。这是一个比较深入的问题但社区通常有补丁。问题四系统运行不稳定频繁死机。电源问题 F1C100s和外围电路尤其是屏幕对电源要求不低。确保你的USB电源能提供至少1A的稳定电流。使用质量差的USB线或电源适配器可能导致电压跌落引起系统复位。散热问题 芯片跑在900MHz时可能会发热。如果环境温度高可以尝试加个小散热片或者在内核中通过配置适当降低CPU频率。嵌入式开发就是一个不断遇到问题、分析日志、查找资料、尝试解决的过程。每次成功解决一个难题你对系统的理解就会加深一层。建议一定要连接串口调试工具uboot和内核的启动日志是排查问题的黄金线索。多利用社区资源荔枝派的相关论坛和GitHub仓库里藏着无数前辈们填坑的经验。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2413054.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!