F1C200S挖坑日记(2)——从零搭建Linux最小系统
1. 为什么选择F1C200S搭建Linux最小系统第一次拿到F1C200S开发板时我对着这个比指甲盖大不了多少的芯片研究了半天。这玩意儿内置64MB DDR内存主频高达900MHz价格却只要一杯奶茶钱。对比我之前用过的STM32F407F1C200S的性能简直是降维打击——跑完整Linux系统还能流畅播放视频而STM32连个像样的GUI都带不动。这块芯片最吸引我的三点优势超高性价比QFN88封装的价格通常在20元以内自带内存省去了外部DDR布线难题完善的Linux支持主线内核已支持USB、LCD、音频等关键外设低功耗表现实测运行Linux时整板功耗仅0.5W电池供电场景特别友好记得第一次成功启动Buildroot系统时看着串口终端里滚动的内核日志那种成就感比当年点亮STM32的LED强烈十倍。不过从零搭建系统的路上坑也不少比如我就曾因为没正确初始化DDR导致系统跑着跑着突然死机后来发现是uboot的DRAM参数配置错了。2. 开发环境搭建指南2.1 硬件准备清单建议备齐这些装备再开工F1C200S开发板推荐荔枝派Nano或LCTech版本USB转TTL串口模块CH340G就行MicroSD卡容量≥256MB速度Class10以上5V/1A电源电流不足会导致系统不稳定2.2 软件工具链安装在Ubuntu 20.04上执行以下命令安装编译工具sudo apt update sudo apt install gcc-arm-linux-gnueabi build-essential bison flex \ libssl-dev libncurses5-dev u-boot-tools dtc python3重点说下交叉编译器的选择早期教程可能推荐arm-linux-gnueabi但实测用arm-linux-gnueabihf带硬件浮点性能更好。我整理好的工具链配置如下export ARCHarm export CROSS_COMPILEarm-linux-gnueabihf- export PATH$PATH:/opt/gcc-linaro-7.5.0/bin3. U-Boot移植实战3.1 源码获取与配置推荐使用全志社区维护的uboot版本git clone https://github.com/Lichee-Pi/u-boot.git -b nano-v2018.01 cd u-boot make licheepi_nano_defconfig关键配置项需要手动调整DRAM参数在include/configs/suniv.h中修改#define CONFIG_SYS_SDRAM_BASE 0x80000000 #define CONFIG_SYS_SDRAM_SIZE SZ_64M启动设备通过menuconfig选择SPI Flash或TF卡启动make menuconfig3.2 常见坑点解决方案DDR初始化失败表现为uboot启动时卡住。解决方法是在board/sunxi/dram_suniv.c中调整时序参数.dx_read_delays 0x0c0c0c0c, .dx_write_delays 0x04040404,TF卡无法识别检查硬件连接后尝试降低时钟频率mmc_set_clock(host, 400000);4. Linux内核定制化4.1 内核配置技巧使用社区优化过的配置模板git clone https://github.com/Lichee-Pi/linux.git -b nano-5.2-tf make licheepi_nano_defconfig几个必选项需要特别注意设备树支持确保选中CONFIG_OF和CONFIG_ARM_APPENDED_DTB关键驱动SPI Flash驱动CONFIG_MTD_M25P80、USB PHYCONFIG_USB_PHY文件系统推荐EXT4和SQUASHFS组合4.2 设备树配置详解以启用SPI Flash为例spi0 { status okay; flash: w25q1280 { compatible winbond,w25q128; reg 0; spi-max-frequency 50000000; }; };遇到过最头疼的问题是LCD显示异常后来发现是设备树里的时序参数不对display-timings { timing0: timing0 { clock-frequency 33000000; hactive 800; vactive 480; hfront-porch 40; hback-porch 40; hsync-len 48; vfront-porch 13; vback-porch 29; vsync-len 3; }; };5. Buildroot根文件系统制作5.1 基础配置使用buildroot-2023.02稳定版make menuconfig关键配置路径Target options→ ARM (little endian)Toolchain→ Custom kernel headers (与内核版本一致)System configuration→ Root password设置为空5.2 实用软件包推荐这些包能让开发更方便调试工具gdb、strace、iperf3文件传输rsync、curl系统监控htop、sysstat我常用的自定义配置保存在configs/licheepi_nano_defconfig中BR2_ARM_CPU_ARMV5y BR2_TOOLCHAIN_BUILDROOT_GLIBCy BR2_PACKAGE_PYTHON3y6. 烧录与启动全流程6.1 TF卡镜像制作使用dd命令写入ubootsudo dd ifu-boot-sunxi-with-spl.bin of/dev/sdX bs1024 seek8分区建议采用以下结构1. 16MB FAT32分区存放内核和设备树 2. 剩余空间EXT4分区根文件系统6.2 系统调试技巧遇到启动失败时按这个顺序排查检查uboot是否加载到DRAMmd 0x80000000确认内核镜像完整性crc32验证查看内核启动日志earlyprintk调试有个特别实用的uboot命令组合setenv bootargs consolettyS0,115200 root/dev/mmcblk0p2 rootwait panic10 fatload mmc 0:1 0x80008000 zImage fatload mmc 0:1 0x80C00000 suniv-f1c100s-licheepi-nano.dtb bootz 0x80008000 - 0x80C000007. 性能优化实战7.1 内存管理技巧由于只有64MB内存需要做这些优化内核配置启用CONFIG_CC_OPTIMIZE_FOR_SIZEBuildroot选择BusyBox的swapon功能系统运行定期执行echo 3 /proc/sys/vm/drop_caches7.2 启动时间优化从原始12秒优化到5秒的秘诀内核裁剪去掉不用的驱动和调试符号使用initramfs减少根文件系统挂载时间并行启动修改/etc/inittab启用并发初始化最终我的内核镜像控制在1.2MB以内arm-linux-gnueabihf-strip -s vmlinux8. 外设驱动开发指南8.1 GPIO控制实例通过sysfs接口操作GPIOecho 1 /sys/class/gpio/export echo out /sys/class/gpio/gpio1/direction echo 1 /sys/class/gpio/gpio1/value更高效的方式是直接操作寄存器#define GPIO_BASE 0x01C20800 void gpio_set(int pin, int value) { volatile uint32_t *reg (uint32_t*)(GPIO_BASE 0x10); if(value) *reg | (1 pin); else *reg ~(1 pin); }8.2 PWM配置方法设备树添加pwm节点pwm { pinctrl-names default; pinctrl-0 pwm0_pins; status okay; };用户空间控制代码echo 100000 /sys/class/pwm/pwmchip0/period echo 50000 /sys/class/pwm/pwmchip0/duty_cycle echo 1 /sys/class/pwm/pwmchip0/enable9. 进阶开发技巧9.1 OverlayFS应用实现只读根文件系统的可写挂载mount -t overlay overlay -o lowerdir/,upperdir/mnt/upper,workdir/mnt/work /new_root9.2 离线包管理使用opkg搭建本地仓库mkdir -p /usr/local/opkg cat /etc/opkg.conf EOF dest root / lists_dir ext /var/opkg-lists arch all 1 arch noarch 1 arch arm 10 EOF10. 真实项目经验分享去年用F1C200S做的智能家居中控项目踩过几个印象深刻的坑SPI Flash寿命问题频繁日志写入导致半年后损坏改用ramlog方案LCD闪烁通过调整VSYNC时序和双缓冲机制解决USB枚举失败硬件上需要添加22Ω串联电阻一个实用的电源管理技巧在无操作时自动进入低功耗模式echo mem /sys/power/state最近发现社区有个超实用的调试工具sunxi-tools可以读取芯片的efuse信息sunxi-fel efuse read 0x00