【Linux 驱动开发】嵌入式 Linux 开发概念

嵌入式 Linux 驱动开发

  • 一、单片机的基本组成
    • [1.1. 单片机与嵌入式 Linux 开发](#1.1. 单片机与嵌入式 Linux 开发)
  • 二、单片机的工作原理
  • 三、常见的单片机类型
  • 四、单片机的应用领域
  • 五、单片机的开发流程
  • 六、单片机与微处理器(MPU)的区别
  • 七、学习单片机的建议
  • [八、嵌入式 Linux 根文件系统制作(以 S5PV210 示例)](#八、嵌入式 Linux 根文件系统制作(以 S5PV210 示例))
    • [8.1 前期准备](#8.1 前期准备)
    • [8.2 创建根文件系统目录骨架](#8.2 创建根文件系统目录骨架)
    • [8.3 利用busybox来生成 Linux系统命令 和 祖先进程](#8.3 利用busybox来生成 Linux系统命令 和 祖先进程)
    • [8.4 从交叉编译工具链中拷贝lib库(仅动态链接 BusyBox 时)](#8.4 从交叉编译工具链中拷贝lib库(仅动态链接 BusyBox 时))
    • [8.5 编写`myrootfs/etc`目录下的脚本文件和配置文件](#8.5 编写myrootfs/etc目录下的脚本文件和配置文件)
    • [8.6 制作设备节点(若未在 rcS 中创建)](#8.6 制作设备节点(若未在 rcS 中创建))
    • [8.7 验证根文件系统](#8.7 验证根文件系统)
  • 九、Linux环境构建(使用自己的根文件系统)
  • [十、制作可烧录的根文件系统镜像(NAND Flash 驱动移植与内核配置)](#十、制作可烧录的根文件系统镜像(NAND Flash 驱动移植与内核配置))
    • [10.1 nandflash驱动移植](#10.1 nandflash驱动移植)
    • [10.2 制作并烧录根文件系统镜像](#10.2 制作并烧录根文件系统镜像)
  • [十一、混合烧录 & 验证 NAND 分区](#十一、混合烧录 & 验证 NAND 分区)
    • [11.1 混合烧录](#11.1 混合烧录)
    • [11.2 验证 NAND 分区](#11.2 验证 NAND 分区)
    • [11.3 启动与验证](#11.3 启动与验证)

单片机(Single-Chip Microcomputer)是一种 集成在一块芯片上的微型计算机系统, 它将中央处理器(CPU)、存储器(内存 RAM 和外存 ROM/EPROM 等)、输入 / 输出(I/O)接口电路、定时器 / 计数器等功能部件集成在一块半导体芯片上,具有体积小、成本低、可靠性高、易于开发等特点,被广泛应用于各种控制领域。

以下是关于单片机的详细介绍:

一、单片机的基本组成

  1. 中央处理器(CPU) 是单片机的核心部件,负责执行指令、处理数据,相当于人的 "大脑"。

    可完成算术运算(如加、减、乘、除)和逻辑运算(如与、或、非),并控制各部件协调工作。

  2. 存储器 程序存储器(ROM/EPROM/Flash ):用于存储用户编写的程序,掉电后数据不丢失。

    数据存储器(RAM):用于临时存储程序运行时的数据和中间结果,掉电后数据丢失。

  3. 输入 / 输出(I/O)接口 用于连接外部设备,如按键、LED、传感器、显示器等。

    常见的 I/O 接口类型包括:

    • 并行 I/O 口(如 P0、P1 等,可同时传输多位数据);
    • 串行 I/O 口(如 UART、SPI、I²C 等,逐位传输数据)。
  4. 定时器 / 计数器 用于产生精确的时间基准或对外部事件进行计数,如定时中断、脉宽调制(PWM)等。
  5. 其他功能模块 部分单片机还集成了模数转换器(ADC)、数模转换器(DAC)、看门狗定时器、通信接口(如 USB、CAN)等。

嵌入式系统

嵌入式Linux开发:

1.1. 单片机与嵌入式 Linux 开发

本文在原有资料基础上进行了结构化整理与补充,兼顾"快速建立直觉"与"深入理解原理"两种学习节奏,帮助初学者在掌握单片机基础的同时,顺利过渡到嵌入式 Linux 根文件系统的制作与部署。

MCU 是嵌入式系统的常见硬件载体;当硬件性能允许并需要复杂 OS 支撑时,就会选择嵌入式 Linux。两者并非对立,而是构成硬件架构从"裸机 → RTOS → Linux"逐步演进的连续谱。

名称 核心定义 典型特征 常见场景
单片机(MCU) 将 CPU、存储器、外设控制器集成在同一芯片上的微型计算机 低成本、低功耗、实时响应快 家电控制、工业仪表、传感器节点
嵌入式 Linux 在具备 MMU 的处理器上运行的裁剪版 Linux 操作系统 多任务、文件系统、网络协议栈丰富 工控网关、智能网关、消费电子

在此之前,我想说说 文章 本身在 理论学习上存在的痛点与改进思路(本文仅提供视角、框架、流程、和解决问题的思路),剩下更多的部分也需要大家自行扩展。

文章学习中存在的痛点 优化建议
直接讲解寄存器或驱动细节,缺乏场景可视化 找到"10 分钟速览"讲清模块用途、输入输出、为什么需要此技术,再深入寄存器与调用栈
课堂思路与项目实践环节中存在断层,代码无业务关联感 寻找可以采用"左列业务流程 / 右列代码实现"并行展示,让业务 与 代码 可以清晰地把控制需求映射到代码结构上
缺乏拓展知识点和工具链说明,学习边界模糊 所以我会尽量在每个知识点后方添加上"进阶阅读 / 常见替代方案 / 调试工具"小节,帮助你深化与自学

二、单片机的工作原理

先建立对 单片机(MCU)的基础模块与快速直觉 (先看整体,再看细节) :

  1. CPU:执行指令,相当于控制核心。
  2. 存储器:程序永久存放在 Flash/ROM,运行时数据靠 RAM。
  3. I/O 接口:把 MCU 与外界(传感器、执行器、通信模块)连接起来。
  4. 定时器/计数器:实现定时触发、频率测量、PWM 等常见控制。
  5. 其他外设:ADC/DAC 转换模拟与数字信号;通信接口(UART/SPI/I²C/CAN 等)实现数据交换;看门狗保障系统稳定。

程序执行过程:
用户通过编程软件(如 Keil、IAR、vscode)编写程序,编译成机器码后下载到单片机的程序存储器中。

单片机通电后,CPU 从程序存储器的起始地址开始,逐条读取指令并执行,通过控制 I/O 接口来实现对外部设备的控制。

核心工作机制:
时钟信号:由晶振或内部振荡器提供,决定单片机的工作频率(如 12MHz、48MHz), 频率越高,运算速度越快。
指令周期:执行一条指令所需的时间, 通常由若干个 时钟周期 组成。

一句话记忆:单片机就是一个"自带基础外设的小电脑",只要供电 + 程序,就能按你的控制逻辑执行。


核心模块:

复制代码
● CPU:可执行算术/逻辑运算,包含中断控制器和指令流水线。
● 存储器: 
	  ○ 程序存储器(Flash/ROM):掉电不丢失。
	  ○ 数据存储器(RAM):运行临时数据,掉电丢失。
● I/O 接口: 
	  ○ 并行 I/O(GPIO):可一次读写多位信号。
	  ○ 串行接口:UART(文本通信)、SPI(高速同步,常接 Flash/显示屏)、I²C(双线总线,挂载传感器)。
● 定时器 / 计数器: 
	  ○ 定时中断:周期执行任务、软定时器。
	  ○ PWM 输出:电机调速、亮度调节。
● 外设扩展: 
	  ○ ADC:模拟量 → 数字量(如温度、电压采集)。
	  ○ DAC:数字量 → 模拟量(波形输出)。
	  ○ 看门狗:软件异常时自动复位。
	  ○ 通信接口:USB、CAN、Ethernet 等。

三、常见的单片机类型

类型 代表型号 特点 应用场景
51 系列 AT89C51、STC89C52 经典入门级单片机,结构简单,开发成本低,学习资料丰富。 教学实验、简单控制设备
AVR 系列 ATmega328、ATtiny 低功耗、高性能,支持在线编程(ISP),广泛应用于开源项目(如Arduino)。 物联网传感器、智能家居
PIC 系列 PIC16F、PIC18F 哈佛总线结构,抗干扰能力强,适合工业控制。 汽车电子、工业仪表
STM32(ARM Cortex-M) STM32F103、STM32F4 基于 ARM 内核,性能强大,外设丰富,支持高速运算和复杂功能。 机器人、无人机、嵌入式系统
MSP430 MSP430G2553 超低功耗,适合电池供电设备,如传感器节点、医疗设备。 低功耗物联网、便携式仪器
RISC-V MCU GD32VF103、ESP32-C3 开源指令集、生态兴起 物联网、科创

拓展阅读:

复制代码
	● ARM Cortex-M 内核架构详解
	● FreeRTOS 与裸机对比
	● RISC-V 微控制器调试工具链

四、单片机的应用领域

复制代码
消费电子:洗衣机、空调、微波炉、遥控器等家电的控制核心。
工业控制:PLC(可编程逻辑控制器)、电机调速、温度控制、自动化生产线。
医疗设备:心电图仪、血压计、血糖仪等便携式医疗仪器。
汽车电子:发动机控制、ABS 防抱死系统、车载传感器、车载娱乐系统。
物联网(IoT):智能传感器、智能家居设备(如智能门锁、环境监测节点)。
嵌入式系统:机器人、无人机、智能仪表、手持设备(如 POS 机)。

五、单片机的开发流程

需求分析: 明确控制目标和功能要求,确定输入传感器、输出执行器、控制逻辑。
硬件选型与原理图设计: 选择合适的单片机型号,设计电路原理图(如电源、晶振、I/O 接口电路)。
软件编程: 使用 C 语言或汇编语言编写程序,实现控制逻辑( 软件架构设计 + 模块化编程)。
调试与测试: 通过仿真器或下载器将程序烧录到单片机中,调试硬件和软件问题。(驱动开发与单元测试:UART、GPIO、ADC 等依次验证)
产品实现: 制作 PCB 电路板,完成整机装配和测试。(系统联调:软硬件协同调试、异常处理。)
量产与维护: 固件升级策略、在线调试接口、测试夹具。

代码编程时的思路(示例):

业务思维与代码关联示例(左:业务需求 / 右:代码模块)

业务 对应程序模块
温度超过阈值时启动风扇 sensors_read() + fan_pwm_ctrl()

| 每秒刷新显示数值 | 定时器中断回调 + 显示驱动 |

六、单片机与微处理器(MPU)的区别

对比项 单片机(MCU) 微处理器(MPU,如 Intel x86、ARM Cortex-A)
集成度 集成 CPU、存储器、I/O 等,单芯片系统。 仅包含 CPU,需外接存储器、外设等芯片。
性能 运算速度较低(数十 MHz 级别),适合简单控制。 性能强大(GHz 级别),适合运行操作系统和复杂应用。
功耗 低功耗,适合电池供电设备。 功耗较高,需散热设计。
成本 成本低,适合嵌入式控制场景。 成本高,多用于 PC、服务器、智能手机等。

七、学习单片机的建议

单片机作为嵌入式系统的核心部件,是实现 "智能化控制" 的基础。从简单的玩具到复杂的工业设备,它的身影无处不在,掌握单片机技术对电子工程、自动化、物联网等领域的学习和工作具有重要意义。

入门选择: 推荐从 51 系列(如 STC89C52)或 Arduino(基于 AVR 单片机)入手,开发工具简单,资料丰富。
必备知识: 学习 C 语言编程、数字电路基础、单片机引脚功能和寄存器配置。
实践项目: 通过搭建简单电路(如 LED 闪烁、按键控制、串口通信)积累经验,逐步挑战复杂项目(如温度采集、电机控制)。
开发工具: 使用 Keil(51 系列)、Arduino IDE(开源平台)、STM32CubeIDE(STM32 系列)等软件。


接下来 本文通过 针对 Linux标准根文件系统的制作 流程进入 Linux 底层驱动开发:

  1. Linux标准根文件系统的制作
  2. Linux环境构建(使用自己的根文件系统)
  3. 制作可烧录的根文件系统镜像
    • 1 > nandflash驱动移植
    • 2 > 制作并烧录根文件系统镜像
    • 3 > 混合烧录
    • 4 > Linux内核烧录

八、嵌入式 Linux 根文件系统制作(以 S5PV210 示例)

8.1 前期准备

软件环境:Ubuntu、交叉编译工具链(如 arm-none-linux-gnueabi-)、BusyBox 源码、mtd-utils

目录规划:

bash 复制代码
~/S5pv210/
├── busybox-1.17.3/
├── myrootfs/
└── toolchain/  (例如 /opt/toolchain-4.5.1-farsight/)

8.2 创建根文件系统目录骨架

bash 复制代码
mkdir -p ~/S5pv210/myrootfs/{bin,sbin,etc,lib,usr/{bin,sbin,lib},proc,sys,dev,tmp,home,var/log}
chmod 755 ~/S5pv210/myrootfs/tmp  # tmp 目录建议可写

补充:usr/ 层级及 var/ 目录虽非强制,但有助于与 Linux FHS 格式对齐,方便移植和维护。

8.3 利用busybox来生成 Linux系统命令 和 祖先进程

bash 复制代码
tar -xvf busybox-1.17.3.tar.bz2
  1. 配置交叉编译工具链:
bash 复制代码
164 CROSS_COMPILE ?= arm-none-linux-gnueabi-
190 ARCH ?= arm
  1. 关键配置:执行make menuconfig
bash 复制代码
Busybox Settings  ---> 
Build Options  --->
 [*] Build BusyBox as a static binary (no shared libs)
Installation Options  --->   
 [*] Don't use /usr                                                                                   x x
       Applets links (as soft-links)  --->                                                              x x
       (./_install) BusyBox installation prefix (NEW) 
  • BusyBox Settings → Build Options → [*] Build BusyBox as a static binary(若要极简且不依赖共享库;如需精简体积,也可用动态链接,在第 8.4 节复制库文件)
  • BusyBox Settings → Installation Options → (../_install) 指定安装路径
  1. 编译与安装:
bash 复制代码
make -j$(nproc)
make install
cp -a _install/* ~/S5pv210/myrootfs/ # 拷贝到myrootfs

此处易错点:

  • cp -raf * 会把 BusyBox 源码整个拷贝过去,应仅复制 _install/*
  • 若启用动态链接,需要确保 lib/ld-linux.so.* 等库同步。

8.4 从交叉编译工具链中拷贝lib库(仅动态链接 BusyBox 时)

bash 复制代码
//拷贝
farsight@ubuntu:/opt/toolchain-4.5.1-farsight/arm-none-linux-gnueabi/lib$ cp -raf * ~/S5pv210/myrootfs/lib/
//查看大小
farsight@ubuntu:~/S5pv210/myrootfs$ du -sh lib
18M     lib
//修改权限
farsight@ubuntu:~/S5pv210/myrootfs/lib$ chmod a+w *
//压缩
farsight@ubuntu:~/S5pv210/myrootfs/lib$ arm-none-linux-gnueabi-strip *
arm-none-linux-gnueabi-strip:libgcc_s.so: File format not recognized
arm-none-linux-gnueabi-strip:libgomp.spec: File format not recognized
arm-none-linux-gnueabi-strip:libstdc++.so.6.0.14-gdb.py: File format not recognized
//再次查看大小
farsight@ubuntu:~/S5pv210/myrootfs$ du -sh lib
5.2M    lib

使用 arm-none-linux-gnueabi-strip 精简体积时,需仅对 ELF 动态库执行。对于 .spec.py 等文本文件不要 strip

8.5 编写myrootfs/etc目录下的脚本文件和配置文件

  1. myrootfs/etc目录创建 inittab //参考:/busybox-1.17.3/examples/inittab
bash 复制代码
farsight@ubuntu:~/S5pv210/myrootfs/etc$ touch inittab

Format for each entry: <id>:<runlevels>:<action>:<process>
//在inittab文件中增加如下内容即可:
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init

sysinit:初始化的时候执行
askfirst:提示"Please press Enter to activate this console.",确认执行后面的shell
ctrlaltdel: 当按下ctrl+alt+del的时候会执行后面的进程,重启
shutdown:关机的时候执行后面的进程
restart,respawn: 这两个是一样的,如果进程意外终止会执行后面的/sbin/init重启
once: 后面的进程只执行一次,意外终止不会重启
wait: 要等到进程执行完毕才能执行下一个
  1. 创建 /etc/init.d/rcS
bash 复制代码
farsight@ubuntu:~/S5pv210/myrootfs/etc$ mkdir init.d
farsight@ubuntu:~/S5pv210/myrootfs/etc$ cd init.d/
farsight@ubuntu:~/S5pv210/myrootfs/etc/init.d$ touch rcS
farsight@ubuntu:~/S5pv210/myrootfs/etc/init.d$ chmod a+x rcS
//添加如下内容:
#!/bin/sh //用什么shell来解析如下脚本命令
echo "----------start myrootfs---------------"
/bin/mount -a //根据/etc/fstab的描述来挂载相关的内存文件系统
//也可以按照如下写法:(不需要/bin/mount -a, 也不需要/etc/fstab文件)
/*
mount -t proc myproc /proc
mount -t sysfs mysys /sys
mount -t tmpfs mydev /dev
*/
/sbin/mdev -s //让编译到内核的驱动程序创建出设备节点
echo /sbin/mdev > /proc/sys/kernel/hotplug //insmod的时候能创建出设备节点
echo "----------end myrootfs"
  1. 创建/etc/fstab //参考ubuntu中的 /etc/fstab
bash 复制代码
farsight@ubuntu:~/S5pv210/myrootfs/etc$ touch fstab
//增加如下内容:
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
myproc            /proc           proc    defaults          0       0
mysys             /sys            sysfs   defaults          0       0
mydev             /dev            tmpfs   defaults          0       0
  1. myrootfs/etc 创建 profile 文件
c 复制代码
//增加如下内容:
#!/bin/sh
export HOSTNAME=farsight
export USER=root
export HOME=root
export PS1="[$USER@$HOSTNAME \w]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH  LD_LIBRARY_PATH
  1. 开启自启动
bash 复制代码
mkdir -p ~/S5pv210/myrootfs/root

可继续扩展:根据项目需求补充 /etc/mdev.confSSH 服务配置网络脚本 等。


8.6 制作设备节点(若未在 rcS 中创建)

bash 复制代码
cd ~/S5pv210/myrootfs/dev
sudo mknod console c 5 1
sudo mknod null c 1 3
sudo mknod ttySAC0 c 204 64   # S5PV210 UART 设备号
sudo chmod 600 console
sudo chmod 666 null
sudo chmod 660 ttySAC0

8.7 验证根文件系统

bash 复制代码
cd ~/S5pv210/myrootfs
find . | cpio -o --format=newc | wc -c   # 粗略估算大小
tree -L 2                                # 结构检查

九、Linux环境构建(使用自己的根文件系统)

  1. 把制作好的根文件系统拷贝到/opt目录下
bash 复制代码
farsight@ubuntu:~/S5pv210$ cp -raf myrootfs/ /opt/
  1. 配置ubuntu的NFS服务
bash 复制代码
farsight@ubuntu:~/S5pv210$ sudo vi /etc/exports
//------------------------------
/opt/myrootfs           *(subtree_check,rw,no_root_squash,async)
//------------------------------
farsight@ubuntu:~/S5pv210$ sudo exportfs -a
farsight@ubuntu:~/S5pv210$ sudo /etc/init.d/nfs-kernel-server restart
  1. 配置开发板
bash 复制代码
set bootargs root=/dev/nfs nfsroot=192.168.30.62:/opt/myrootfs ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200

网络提示:确保主机与开发板在同一网段,并关闭防火墙或放行 NFS 端口。

十、制作可烧录的根文件系统镜像(NAND Flash 驱动移植与内核配置)

10.1 nandflash驱动移植

复制代码
  1> 拷贝s3c_nand.c到内核linux-3.0.8/drivers/mtd/nand目录下
     拷贝regs-nand.h到linux-3.0.8/arch/arm/mach-s5pv210/include/mach目录下
     
  2> 修改linux-3.0.8/drivers/mtd/nand目录下的Kconfig和Makefile
     //Kconfig增加内容如下:
bash 复制代码
config MTD_NAND_S3C
tristate "NAND Flash support for Samsung S5PV210"
depends on ARCH_S5PV210
help
  This enables the NAND flash controller on the S5PV210 SoCs
  No board specific support is done by this driver, each board
  must advertise a platform_device for the driver to attach.

config MTD_NAND_S3C_DEBUG
bool "Samsung S5PV210 NAND driver debug"
depends on MTD_NAND_S3C
help
  Enable debugging of the S5PV210 NAND driver

config MTD_NAND_S3C_HWECC
bool "Samsung S5PV210 NAND Hardware ECC"
depends on MTD_NAND_S3C
help
  Enable the use of the controller's internal ECC generator when
  using NAND. Early versions of the chips have had problems with
  incorrect ECC generation, and if using these, the default of
  software ECC is preferable.

//Makefile增加内容如下:

bash 复制代码
obj-$(CONFIG_MTD_NAND_S5PV210)    += s3c_nand.o
复制代码
  3> 增加platform_device

  //修改 arch/arm/mach-s5pv210/mach-smdkv210.c 文件
  	1) 增加 nandflash 的平台信息,头文件,注册
c 复制代码
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <plat/nand.h>
static struct mtd_partition s5pv210_nand_part[] = {
    [0] ={
        .name = "myuboot",
        .offset = 0x0,
        .size = SZ_1M,  
    },
    [1] ={
        .name = "kernel",
        .offset = MTDPART_OFS_APPEND,
        .size = SZ_1M * 4,  
    },
    [2] ={
        .name = "rootfs",
        .offset = MTDPART_OFS_APPEND,
        .size = SZ_1M * 16,  
    },
    [3] ={
        .name = "userdata",
        .offset = MTDPART_OFS_APPEND,
        .size = SZ_1M * 16,  
    },
    [4] ={
        .name = "usr spec",
        .offset = MTDPART_OFS_APPEND,
        .size = MTDPART_SIZ_FULL,  
    },
};

struct s3c_nand_mtd_info s5pv210_nand_mtd_part_info = {
    .chip_nr = 1,
    .mtd_part_nr = ARRAY_SIZE(s5pv210_nand_part),
    .partition = s5pv210_nand_part,
};

static struct resource s5pv210_nand_resource[] = {
    [0] = {
        .start  = 0xB0E00000,
        .end = 0xB0E00000 + SZ_1M,
        .flags = IORESOURCE_MEM,
    }
};

struct platform_device s5pv210_device_nand = {
    .name                  = "s5pv210-nand",
    .id                    = -1,
    .num_resources         = ARRAY_SIZE(s5pv210_nand_resource),
    .resource              = s5pv210_nand_resource,//nand控制寄存器的地址资源
    .dev = {
        .platform_data     = &s5pv210_nand_mtd_part_info,// 特殊的平台数据,分区表
    }
};

static struct platform_device *smdkv210_devices[] __initdata = {
    ...
        &smdkv210_dm9000,
    &s5pv210_device_nand,
    ...
};
复制代码
	2) 在 arch/arm/plat-samsung/include/plat/nand.h` 增加结构体类型的定义
c 复制代码
struct s3c_nand_mtd_info {
   uint chip_nr;
   uint mtd_part_nr;
   struct mtd_partition *partition;
};
复制代码
	3) 修改 `arch/arm/mach-s5pv210/clock.c` 文件
c 复制代码
static struct clk init_clocks_off[] = {
{
    ...
    { 
         .name  = "nandxl",
         .id  = -1,
         .parent  = &clk_hclk_psys.clk,
         .enable  = s5pv210_clk_ip1_ctrl,
         .ctrlbit = (1 << 24),
    }, 
}; 
复制代码
	4) 修改include/linux/mtd/partitions.h

 		添加如下内容:
c 复制代码
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
复制代码
4> make menuconfig 配置内核并且编译
bash 复制代码
 Device Drivers  --->
    <*> Memory Technology Device (MTD) support  --->
        <*> Direct char device access to MTD devices 
        <*> Caching block device access to MTD devices 
        <*> NAND Device Support  ---> 
           <*> NAND Flash support for Samsung S5PV210
               [*] Samsung S5PV210 NAND Hardware ECC
复制代码
5> 重新编译并拷贝内核
bash 复制代码
make zImage -j2
cp -raf arch/arm/boot/zImage /tftpboot/
复制代码
6> 重启开发板,查看信息
bash 复制代码
NAND device: Manufacturer ID: 0x01, Chip ID: 0xd3 (AMD S34ML08G1)
Creating 5 MTD partitions on "s5pv210-nand":
0x000000000000-0x000000100000 : "myuboot"
0x000000100000-0x000000500000 : "kernel"
0x000000500000-0x000001500000 : "rootfs"
0x000001500000-0x000002500000 : "userdata"
0x000002500000-0x000020000000 : "usr spec"

[root@farsight /]# cat /proc/partitions
major minor  #blocks  name

31        0       1024 mtdblock0
31        1       4096 mtdblock1
31        2      16384 mtdblock2
31        3      16384 mtdblock3
31        4     486400 mtdblock4

[root@farsight /]# ls /dev/mtd* -l
brw-rw----    1 0        0          31,   0 Jan  1 00:00 /dev/mtdblock0
brw-rw----    1 0        0          31,   1 Jan  1 00:00 /dev/mtdblock1
brw-rw----    1 0        0          31,   2 Jan  1 00:00 /dev/mtdblock2
brw-rw----    1 0        0          31,   3 Jan  1 00:00 /dev/mtdblock3
brw-rw----    1 0        0          31,   4 Jan  1 00:00 /dev/mtdblock4

10.2 制作并烧录根文件系统镜像

bash 复制代码
Linux系统中nandflash的根文件系统镜像:
	  cramfs ----  只读的并且压缩的格式
	  jffs2   ----  可读可写压缩的格式
	  yaffs  ----  可读可写不压缩的格式
复制代码
1> 确保 Linux 内核识别 cramfs 和 jffs2 镜像
bash 复制代码
File systems  ---> 
   [*] Miscellaneous filesystems  --->
       <*> Journalling Flash File System v2 (JFFS2) support 
       <*> Compressed ROM file system support (cramfs) 

//重新编译内核并拷贝

bash 复制代码
make zImage -j2
cp -raf arch/arm/boot/zImage /tftpboot/
复制代码
2> 制作cramfs根文件系统镜像
	   a. 制作
bash 复制代码
farsight@ubuntu:~/S5pv210$ mkfs.cramfs myrootfs/ myrootfs.cramfs
复制代码
       b. 烧录		  
	   		烧写cramfs文件系统镜像
c 复制代码
 FS210 # tftp 0x40008000 myrootfs.cramfs
 FS210 # nand erase 0x500000 0x1000000
 FS210 # nand write 0x40008000 0x500000 0x1000000
复制代码
   c. 设置开发板
	   设置uboot启动参数
bash 复制代码
set bootargs root=/dev/mtdblock2 rootfstype=cramfs ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200
复制代码
 3> 制作jffs2根文件系统镜像
      a. 制作(需要先离线安装工具)
bash 复制代码
farsight@ubuntu:~/S5pv210/mtd$ sudo dpkg -i *
farsight@ubuntu:/opt$ mkfs.jffs2 -r myrootfs -o myrootfs.jffs2 -e 0x20000 --pad=0x1000000 -n
// -r:源
// -o:目标
// -e:块大小
// --pad=  指定做出来的镜像大小
// -n:不要打印不必要的信息
复制代码
	  b. 烧录
c 复制代码
FS210 # tftp 0x40008000 myrootfs.jffs2
FS210 # nand erase 0x500000 0x1000000
FS210 # nand write 0x40008000 0x500000 0x1000000
复制代码
	c. 设置u-boot启动参数
bash 复制代码
set bootargs root=/dev/mtdblock2 rootfstype=jffs2 ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200

或者

bash 复制代码
set bootargs root=31:2 rootfstype=jffs2 ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200

或者

bash 复制代码
set bootargs root=1f02 rootfstype=jffs2 ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200

root=31:2root=1f02/dev/mtdblock2 的主次设备号写法,适合内核早期未自动创建设备节点时。

十一、混合烧录 & 验证 NAND 分区

11.1 混合烧录

1> 修改制作好的根文件系统,在 myrootfs/etc/init.d/rcS 增加如下命令,并重新制作 cramfs

bash 复制代码
//----------------------------------
/bin/mount -t jffs2 /dev/mtdblock3 /home
//----------------------------------
farsight@ubuntu:/opt$ mkfs.cramfs myrootfs/ myrootfs.cramfs
farsight@ubuntu:/tftpboot$ cp -raf /opt/myrootfs.cramfs ./

2> 在/opt目录下创建userdata目录(里面任意放一个文件), 制作jffs2根文件系统镜像

bash 复制代码
farsight@ubuntu:/opt$ mkfs.jffs2 -r userdata -o userdata.jffs2 -e 0x20000 -n

3> 烧录 cramfsjffs2 根文件系统镜像

c 复制代码
FS210 # tftp 0x40008000 myrootfs.cramfs
FS210 # nand erase 0x500000 0x1000000
FS210 # nand write 0x40008000 0x500000 0x1000000

FS210 # tftp 0x40008000 userdata.jffs2
FS210 # nand erase 0x1500000 0x1000000
FS210 # nand write 0x40008000 0x1500000 0x1000000

4> 设置启动参数

bash 复制代码
set bootargs root=/dev/mtdblock2 rootfstype=cramfs ip=192.168.30.63 init=/linuxrc console=ttySAC0,115200

11.2 验证 NAND 分区

  • Linux内核烧录
  • 1> 下载内核并烧录
c 复制代码
FS210 # tftp 0x40008000 zImage
FS210 # nand erase 0x100000 0x400000
FS210 # nand write 0x40008000 0x100000 0x400000
  • 2> 设置开发板
bash 复制代码
set bootcmd nand read 0x40008000 0x100000 0x400000\; bootm 0x40008000
set bootargs root=/dev/mtdblock2 rootfstype=cramfs init=/linuxrc console=ttySAC0,115200

11.3 启动与验证

  • 查看分区信息:
bash 复制代码
cat /proc/mtd
cat /proc/partitions
ls -l /dev/mtd*
  • 挂载状态:
bash 复制代码
mount
df -h

一些配置过程中会遇见的常见问题:

现象 排查步骤
启动卡在 Uncompressing Linux... 检查 zImage 是否适配板级配置 / U-Boot 内存地址是否正确
Kernel panic - not syncing: No init found 确认根文件系统存在 /init/sbin/initinit=/linuxrc 参数有效
sh: can't access tty; job control turned off 确认 /dev/console 设备节点存在且权限正确
mount: mounting /dev on dev failed 检查 tmpfs 是否启用、rcS 脚本是否执行成功
mtdblockX 无法写入 分区是否只读、驱动是否开启硬件 ECC、镜像大小是否超出分区
mkfs.jffs2 报错 确认 mtd-utils 版本适配 NAND 参数,-e 块大小应与 NAND 擦除块一致

本文从概念层面重新理解 MCU、嵌入式系统、嵌入式 Linux 的关系与差异,是选择合适软硬件方案的前提。从第八节开始进入实务操作:根文件系统制作、NAND 驱动移植、文件系统烧录等步骤 需要严谨执行,每一步都蕴含对 Linux 启动流程和硬件资源管理的深入理解。

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

相关推荐
还不秃顶的计科生2 小时前
查看linux服务器中某文件夹占用空间大小
服务器·python
EVERSPIN2 小时前
单片机CH554电容触摸屏控制器方案
单片机·嵌入式硬件·单片机ch554
“αβ”2 小时前
UDP与TCP的区别
linux·运维·服务器·网络·网络协议·tcp/ip·udp
天上飞的粉红小猪2 小时前
应用层自定义协议与序列化
运维·服务器·网络
容测电子2 小时前
ISO 11452-4:大电流注入BCI,从原理到校准
经验分享·嵌入式硬件·汽车·电磁兼容·emc测试·emc测试设备
兆龙电子单片机设计2 小时前
【STM32项目开源】STM32单片机智能宠物喂养系统
stm32·单片机·开源·毕业设计·电子信息
Y1rong2 小时前
STM32之串口(三)
stm32·单片机·嵌入式硬件
Snower_20222 小时前
CentOS 7 搭建 SVN 服务器(精简版教程)
linux·运维·服务器·svn·centos
wb043072012 小时前
一次jvm配置问题导致的数据库连接异常
服务器·jvm·数据库·后端