当前位置: 首页 > news >正文

嵌入式Linux--全志V3s--NOR Flash分区与文件系统实战(一)

1. 全志V3s与NOR Flash开发板简介

第一次拿到全志V3s开发板时,我注意到板子上那颗不起眼的XT25F128B NOR Flash芯片。这种16MB容量的存储介质在嵌入式领域非常典型——价格低廉但性能有限,就像给跑车装了个小油箱。与常见的NAND Flash不同,NOR Flash允许直接执行代码(XIP),但写入速度较慢且容量较小。这种特性决定了我们必须精打细算地规划存储空间。

荔枝派Zero开发板的硬件布局很紧凑,SPI接口的NOR Flash直接连接在V3s的SPI0控制器上。实测发现,这颗XT25F128B的擦除块大小是64KB,这意味着我们所有的分区设计都必须以64KB为最小单位对齐。就像装修时要考虑瓷砖尺寸一样,不当的分区规划会导致大量存储空间浪费。

2. 嵌入式Linux四大件与存储妥协

2.1 系统必备组件

在NOR Flash上部署Linux系统就像玩俄罗斯方块,需要巧妙安排几个关键组件:

  • U-Boot:系统引导程序,我通常预留1MB空间
  • 设备树(dtb):硬件描述文件,64KB足够
  • Linux内核:经过裁剪后4MB空间绰绰有余
  • 根文件系统:剩下的约10.9MB空间全部分配给它

2.2 NOR Flash的特殊考量

由于NOR Flash的特性,我们必须做出一些妥协:

  1. 文件系统必须选择JFFS2这种专为Flash设计的类型
  2. 内核需要特别配置MTD和SPI-NOR驱动支持
  3. U-Boot环境变量必须放在前1MB空间内
  4. 所有分区起始地址必须按擦除块大小对齐

我曾尝试使用ext4文件系统,结果系统启动时直接卡死。后来发现是因为ext4的日志特性会频繁擦写Flash,导致寿命急剧下降。

3. U-Boot编译与配置实战

3.1 获取特殊版本U-Boot

全志芯片的SPI驱动尚未合并到主线U-Boot,需要克隆实验分支:

git clone -b v3s-spi-experimental https://github.com/Lichee-Pi/u-boot.git cd u-boot

3.2 Flash型号配置技巧

执行menuconfig时有个坑要注意:

make ARCH=arm menuconfig

进入Device Drivers > SPI Flash Support后,虽然列表里没有芯天下的选项,但实测选择Macronix的驱动可以兼容XT25F128B。如果Flash容量大于16MB,记得勾选CONFIG_SPI_FLASH_BAR选项。

3.3 环境变量关键配置

include/configs/sun8i.h中添加启动参数时,一定要在包含sunxi-common.h之前添加:

#define CONFIG_BOOTCOMMAND "sf probe 0; " \ "sf read 0x41800000 0x100000 0x10000; " \ "sf read 0x41000000 0x110000 0x400000; " \ "bootz 0x41000000 - 0x41800000" #define CONFIG_BOOTARGS "console=ttyS0,115200 earlyprintk panic=5 rootwait " \ "mtdparts=spi32766.0:1M(uboot)ro,64k(dtb)ro,4M(kernel)ro,-(rootfs) root=31:03 rw rootfstype=jffs2"

这里有几个关键点:

  1. root=31:03表示使用mtdblock3作为根文件系统
  2. rootfstype=jffs2指定文件系统类型
  3. 内存地址0x41000000用于加载内核,0x41800000用于设备树

4. Linux内核定制化编译

4.1 获取适配内核源码

使用Lichee Pi维护的内核分支更稳定:

git clone https://github.com/Lichee-Pi/linux.git cd linux git checkout zero-4.13.y

4.2 内核关键配置项

必须确保以下选项启用:

make ARCH=arm menuconfig

路径:

  • Device Drivers > Memory Technology Device (MTD) support > Command line partition table parsing
  • Device Drivers > Memory Technology Device (MTD) support > SPI-NOR device support
  • File systems > Miscellaneous filesystems > Journalling Flash File System v2 (JFFS2) support

4.3 设备树修改要点

arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts中添加SPI节点:

&spi0 { status = "okay"; xt25f128b: xt25f128b@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <50000000>; #address-cells = <1>; #size-cells = <1>; }; };

注意Flash型号必须在内核支持的m25p_ids[]列表中,否则无法识别。如果型号不在列表中,可以尝试使用通用的"spi-nor"兼容性标签。

5. 文件系统与镜像打包

5.1 JFFS2镜像生成

首先安装制作工具:

sudo apt-get install mtd-utils

假设已有rootfs目录,计算JFFS2分区大小:

16MB(总空间) - 1MB(uboot) - 64KB(dtb) - 4MB(kernel) = 0xAF0000(10.9MB)

生成镜像命令:

mkfs.jffs2 -s 0x100 -e 0x10000 -p 0xAF0000 -d rootfs/ -o jffs2.img

参数说明:

  • -s 0x100:页大小256字节
  • -e 0x10000:擦除块大小64KB
  • -p 0xAF0000:分区总空间

5.2 完整镜像打包脚本

创建打包脚本package.sh

#!/bin/sh dd if=/dev/zero of=flashimg.bin bs=1M count=16 dd if=u-boot-sunxi-with-spl.bin of=flashimg.bin bs=1K conv=notrunc dd if=sun8i-v3s-licheepi-zero.dtb of=flashimg.bin bs=1K seek=1024 conv=notrunc dd if=zImage of=flashimg.bin bs=1K seek=1088 conv=notrunc dd if=jffs2.img of=flashimg.bin bs=1K seek=5184 conv=notrunc

执行后会生成16MB的flashimg.bin文件,包含所有系统组件。这种打包方式就像制作多层蛋糕,每层食材必须精确放置在指定位置。

6. 烧录与启动技巧

6.1 进入FEL模式的方法

全志芯片的FEL模式有三种进入方式:

  1. 不插SD卡且Flash为空
  2. 使用特殊SD卡启动镜像
  3. 上电时将SPI_MISO引脚拉低

最可靠的方法是先清空Flash,然后通过USB连接电脑:

sudo sunxi-fel version

正常连接会显示类似AWUSBFEX soc=00001681(V3s)的信息。

6.2 镜像烧录命令

全盘烧录最简单:

sudo sunxi-fel -p spiflash-write 0 flashimg.bin

如果想单独更新某个组件,比如只更新内核:

sudo sunxi-fel -p spiflash-write 0x110000 zImage

烧录完成后复位开发板,通过串口可以看到启动日志。如果遇到问题,建议先检查:

  1. U-Boot是否能正确识别Flash
  2. 内核启动参数中的root参数是否正确
  3. JFFS2镜像是否完整无误

在实际项目中,我发现NOR Flash的写入速度较慢,频繁烧录会降低开发效率。因此建议先在SD卡上调试系统,稳定后再移植到NOR Flash。

http://www.jsqmd.com/news/652549/

相关文章:

  • 计算机毕业设计:Python海洋与淡水渔业资源监控大屏 Flask框架 数据分析 可视化 数据大屏 大数据 机器学习 深度学习(建议收藏)✅
  • 如何利用TypeScript提升clean-code-javascript项目质量:静态类型检查的7大优势
  • 终极指南:PMD与元编程集成如何实现代码生成质量管控
  • Python 爬虫实战:批量抓取免费代理IP地址,提升网络爬虫效率与匿名性
  • 避坑指南:在安卓Termux里用QEMU装Win11最容易踩的5个雷(附解决方案)
  • 镜像视界·普陀研究院:厘米级无感定位,开启全域无设备空间智能革命
  • wxBot数据库集成终极指南:实现消息持久化与历史记录管理
  • Navicat Premium 16最新版SQL文件导入实战(附UTF-8编码最佳实践)
  • 您的AI助手为何总是“看不懂“网页?一个前缀让大语言模型真正理解网络世界
  • 终极指南:Yii2 FecShop社区生态与未来发展——开源电商系统的演进之路
  • ART库装饰功能详解:218种装饰让你的文本脱颖而出
  • Gumbo-Parser编译优化终极指南:如何平衡性能与代码体积
  • 别只用来生成代码!挖掘STM32CubeMX隐藏工具链:PackCreator与生态整合实战
  • CSS如何给按钮添加按下缩小的动画_利用-active配合transform
  • 如何使用Supabase构建实时物流追踪系统:从货物状态监控到位置追踪的完整指南
  • 终极指南:Fay数字人语音合成声码器性能对比与优化方案
  • 构建智能微信助手:探索Python自动化机器人的创新实践
  • Faster-Whisper-GUI:高效专业的音频视频转字幕一体化解决方案
  • 电池数据文件,元数据区域用于记录电池测试的核心配置信息
  • 别再死记硬背‘结构洞’定义了!用Python+NetworkX画张图,3分钟让你秒懂
  • 鸿蒙应用签名进阶:用OpenSSL命令行管理你的.p12证书库(含多环境配置)
  • LLM服务“看似正常却持续劣化”的5种静默故障(附Prometheus+Langfuse联合检测脚本)
  • virt基础-mdev_parent_ops函数集源码解析-i915
  • 从算法工程师视角拆解:CSDN博客质量分V5.0的迭代逻辑与平滑函数优化
  • GitHub Pages 并发部署与工作流优化终极指南
  • CubeFS元数据备份工具:实现自动化备份的终极指南
  • Gogs数据迁移进阶:如何只迁移数据库或单个仓库?(MySQL/PostgreSQL切换实战)
  • 终极指南:如何用Tweepy和Jupyter Notebook实现交互式Twitter数据分析
  • 革命性窗口管理:智能置顶工具的完全实战指南
  • 终极指南:使用gumbo-parser将HTML转换为JSON的完整教程