多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

第324篇 嵌入式Linux系统开发

第324篇 嵌入式Linux系统开发 上篇聊了EtherCAT工业以太网。这篇聊嵌入式Linux——当MCU的性能不够用需要跑复杂的算法视觉、SLAM、运动规划时就得用嵌入式Linux。面试中嵌入式Linux的题目覆盖面很广内核裁剪、设备树、驱动框架、根文件系统每个方向都能深挖。为什么要用嵌入式LinuxMCU比如STM32跑RTOS适合实时控制嵌入式Linux跑在MPU比如ARM Cortex-A系列上适合复杂计算。两者的分工很明确实时控制层MCURTOS负责电机控制、传感器采样、安全保护响应时间微秒级计算决策层MPULinux负责视觉处理、路径规划、人机交互需要MMU和大内存在机器人中典型的架构是工控机x86或ARM64跑UbuntuROS2做高层决策通过EtherCAT/CAN/UART连接下层的MCU做实时控制。嵌入式Linux的优势完整的TCP/IP网络栈、丰富的开发工具链、支持复杂文件系统、可以跑Python/C/Rust等高级语言、有成熟的图形界面框架。代价是启动时间较长秒级、实时性不如RTOS毫秒级抖动、系统复杂度更高。启动流程嵌入式Linux的启动流程比桌面Linux复杂得多因为嵌入式没有BIOS/UEFI帮你做硬件初始化。完整的启动链BootROM芯片内置不可修改→ 从预设介质SPI Flash/eMMC/SD卡加载第一级引导BootloaderU-Boot最常见→ 初始化DDR、时钟、外设加载内核和设备树到内存Linux Kernel → 解压、初始化内核子系统、挂载根文件系统init进程systemd或BusyBox init→ 启动用户空间服务和应用U-Boot是嵌入式中最常用的bootloader。它支持多种启动方式TFTP网络启动、SPI Flash、eMMC、SD卡有命令行可以调试支持环境变量和启动脚本。在产品开发中U-Boot的环境变量用来存储MAC地址、序列号、启动参数等信息。U-Boot的启动流程分两个阶段SPLSecondary Program Loader和U-Boot本体。SPL很小几十KB负责初始化DDR和基本时钟然后加载U-Boot本体到DDR中运行。这种两阶段设计是因为BootROM只能加载很小的数据到片内SRAM而U-Boot本体太大放不下。内核启动时的命令行参数bootargs也很关键。常见的参数包括consolettyS0,115200串口控制台、root/dev/mmcblk0p2根分区位置、rootwait等待块设备就绪、rw读写挂载。配置错误的bootargs是启动失败最常见的原因之一。设备树Device Tree是嵌入式Linux的重要概念。它用DTSDevice Tree Source文件描述硬件拓扑——哪些外设存在、挂在哪个总线上、中断号是多少、GPIO复用配置是什么。内核通过设备树了解硬件不需要为每个板子写专用的板级文件。内核裁剪嵌入式Linux的内核需要根据硬件平台裁剪。完整内核有几百万行代码但你的板子可能只需要其中一小部分。裁剪的方法make menuconfig图形化配置内核选项。根据板子的外设选择对应的驱动模块去掉不需要的文件系统和网络协议。设备树裁剪只保留板子上实际使用的外设节点禁用不用的外设。内核模块 vs 内置常用的驱动编译为内置built-in不常用的编译为模块.ko需要时动态加载。裁剪的目标是减小内核体积Flash有限和加快启动时间。一个裁剪好的嵌入式Linux内核可以压缩到2-3MB启动时间控制在1-2秒内。根文件系统根文件系统rootfs是嵌入式Linux启动后挂载的第一个文件系统包含所有用户空间程序和库。常见的构建方式Buildroot轻量级适合简单的嵌入式系统。配置文件简单构建速度快生成的rootfs很小。Yocto/OpenEmbedded功能强大但学习曲线陡峭。适合复杂的产品级系统支持多层叠加、软件包管理、OTA更新。Debian/Ubuntu base直接用现成的arm64根文件系统apt安装软件包。开发方便但体积大。rootfs的关键目录/bin基础命令、/lib共享库、/etc配置文件、/proc和/sys内核虚拟文件系统、/dev设备节点。在嵌入式中/dev通常用devtmpfs自动创建设备节点不需要手动用mknod。在机器人中通常用Ubuntu或Debian base——因为要跑ROS2而ROS2对Ubuntu有官方支持。Buildroot更适合没有复杂应用需求的简单设备。驱动开发框架嵌入式Linux驱动有几种标准框架字符设备驱动最基础的驱动类型。通过file_operations注册open/read/write/ioctl等操作。适合简单的寄存器读写设备。平台设备驱动platform driver跟设备树配合的驱动模型。设备树中定义platform_device内核自动匹配对应的platform_driver。这是现代嵌入式Linux驱动的标准写法。platform driver的核心是probe函数——当设备树中的compatible属性与驱动声明的of_match_table匹配时内核调用probe完成设备初始化。probe中要做的事情ioremap映射物理地址到虚拟地址、申请中断request_irq、注册字符设备或input设备、初始化硬件寄存器。remove函数做相反的清理操作。IIOIndustrial I/O框架专门用于ADC、DAC、加速度计、陀螺仪等传感器。提供统一的sysfs接口和字符设备接口。写传感器驱动首选IIO框架。V4L2Video for Linux 2摄像头和视频采集设备的驱动框架。如果你的机器人有视觉传感器V4L2是必须了解的。面试要点设备树的语法和结构。DTS文件是树形结构用节点和属性描述硬件。每个节点有compatible属性用于匹配驱动、reg属性寄存器地址和大小、interrupts中断配置。面试中可能给你一个原理图让你写出对应的设备树节点。内核模块的加载过程。insmod加载.ko文件到内核→调用module_init注册的初始化函数→注册设备或驱动→创建/dev节点或/sys属性。rmmod卸载时调用module_exit清理资源。modprobe比insmod智能——它会自动加载依赖的模块。启动时间的优化。嵌入式Linux启动时间从十几秒优化到1-2秒关键手段并行初始化异步probe、延迟加载非关键驱动、使用initramfs避免等待块设备就绪、关闭不必要的内核日志和自检。用户空间和内核空间的通信方式。面试常考ioctl最常用自定义命令码、sysfs暴露属性到/sys目录适合简单配置、mmap共享内存适合大数据量传输如图像帧、netlink内核和用户空间的Socket通信适合网络子系统事件通知。每种方式有适用场景选型要看数据量和实时性要求。设备树中的中断描述。interrupts属性用三元组描述中断类型GIC_SPI/GIC_PPI、中断号、触发方式IRQ_TYPE_LEVEL_HIGH/IRQ_TYPE_EDGE_RISING。理解这些描述方式才能正确编写设备树和对应的中断处理驱动。给你的建议嵌入式Linux的学习路径先在一块开发板推荐RK3568或IMX8MM上跑通完整的构建-烧写-启动流程然后逐步深入。Buildroot适合快速入门Yocto适合产品化。驱动开发从字符设备开始——写一个简单的GPIO控制驱动理解file_operations、设备号分配、用户空间交互。然后学platform driver模型理解设备树和驱动的匹配机制。最后学具体的子系统框架IIO、V4L2、input等。调试工具必须掌握dmesg看内核日志、devmem2读写物理地址、strace跟踪系统调用、perf分析性能热点。这些工具在面试中也是常考内容。上一篇第323篇 EtherCAT工业以太网协议下一篇预告第325篇 FPGA在机器人中的应用
返回列表