openwrt spi flash 分区适配过程
openwrt spi flash 分区适配过程
这里基于 openwrt mt7620a 平台来跟踪,主要是想理清 dts 里的分区描述是如何一步步转化成内核分区行为。
先来看看 dts 中关于分区的描述:
palmbus@10000000 {
spi@b00 {
status = "okay";
m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "w25q128";
reg = <0 0>;
linux,modalias = "m25p80", "w25q128";
spi-max-frequency = <10000000>;
partition@0 {
label = "u-boot";
reg = <0x0 0x30000>;
read-only;
};
partition@30000 {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};
factory: partition@40000 {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
};
partition@50000 {
label = "firmware";
reg = <0x50000 0xfb0000>;
};
};
};
dts 描述的是一个树状结构。spi 控制器挂在 platform 总线上,spi flash (w25q128) 挂在 spi 总线上。 探测到 spi flash 的流程如下:
- plat_of_setup() 遍历 palmbus 上的设备,并为每一个动态创建 platform_device,添加到系统总线上 device_add()。对于 spi 这里会创建一个名为 "ralink,rt2880-spi" 的 platfrom_device 并添加到系统中。
- drivers/spi/spi-rt2880.c 中会注册 spi 的 platform_driver,与上一步的 platfrom_device match 上了之后,触发调用 rt2880_spi_probe() 。
- spi_register_master() 向系统注册 spi 主控制器,并最后调用 of_register_spi_devices(master) 看看 dts 中在 spi 总线上有哪些设备。
- 对 dts 中描述的每一个 spi 总线下的设备,为其创建相应的 spi_device,同时根据 dts 中描述的 reg, spi-cpha, spi-cpol, spi-cs-high, spi-3wire, spi-max-frequency 等属性来配置该 spi 设备。对于这里,创建了一个名为 “m25p80” 的 spi_device。
- drivers/mtd/device/m25p80.c 中有名为 “m25p80" 的 spi_driver,于是 match 上了。触发执行 m25p_probe()。
- m25p_probe() 中读到了这颗 spi flash 的 id 后,确认了一些基本信息(如页大小、块大小), 最后调用 mtd_device_parse_register() 开始真正的分区。
分区解析器
part_parser 用来按照某种规则将分区信息解析出来。这些规则可以有很多,内核里调用 register_mtd_parser() 即可注册一个新的解析器。
drivers/mtd/mtdpart.c 中维护了一个链表 part_parsers,解析器按注册顺序添加到这个链表里。
parse_mtd_partitions() 中,如果未指定解析器的话,则默认只允许用 cmdlinepart, ofpart 两种解析器。对于我们这里,实际上起作用的是 ofpart。
static struct mtd_part_parser ofpart_parser = {
.owner = THIS_MODULE,
.parse_fn = parse_ofpart_partitions,
.name = "ofpart",
};
parse_ofpart_partitions() 遍历 dts 中 spi flash 设备下的分区描述信息,取出其中的 reg, label, name, read-only, lock 等信息以填充一个 struct mtd_partition 结构体。上面 dts 里描述了 4 个分区, 就有一个大小为 4 的 struct mtd_partition 数组,最后由 add_mtd_partitions() 添加为各 mtd 分区。
分区的情况可以待系统启动后在 /proc/mtd 文件中查看到。
# cat /proc/mtd
dev: size erasesize name
mtd0: 00030000 00010000 "u-boot"
mtd1: 00010000 00010000 "u-boot-env"
mtd2: 00010000 00010000 "factory"
mtd3: 00fb0000 00010000 "firmware"
mtd4: 00ea9283 00010000 "rootfs"
mtd5: 00b30000 00010000 "rootfs_data"
根文件系统的解析
上面 /proc/mtd 的内容中相比 dts 中的描述多了两个分区 rootfs, rootfs_data。这两个分区是何时添加的呢?
看看添加 mtd 分区的函数:
int add_mtd_partitions(struct mtd_info *master,
const struct mtd_partition *parts,
int nbparts)
{
struct mtd_part *slave;
uint64_t cur_offset = 0;
int i;
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i < nbparts; i++) {
slave = allocate_partition(master, parts + i, i, cur_offset);
if (IS_ERR(slave))
return PTR_ERR(slave);
mutex_lock(&mtd_partitions_mutex);
list_add(&slave->list, &mtd_partitions);
mutex_unlock(&mtd_partitions_mutex);
add_mtd_device(&slave->mtd);
mtd_partition_split(master, slave);
cur_offset = slave->offset + slave->mtd.size;
}
return 0;
}
最后调用了 mtd_partition_split()。
static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part)
{
static int rootfs_found = 0;
if (rootfs_found)
return;
if (!strcmp(part->mtd.name, "rootfs")) {
rootfs_found = 1;
if (config_enabled(CONFIG_MTD_ROOTFS_SPLIT))
split_rootfs_data(master, part);
}
if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
config_enabled(CONFIG_MTD_SPLIT_FIRMWARE))
split_firmware(master, part);
arch_split_mtd_part(master, part->mtd.name, part->offset,
part->mtd.size);
}
如果:
- rootfs 还没有被找到
- 当前分区名是 "firmware"
- 内核配置时开启了 CONFIG_MTD_SPLIT_FIRMWARE
则调用 split_firmware() 来解析。在该函数中做了以下几件事:
- 找 type 为 MTD_PARSER_TYPE_FIRMWARE 的分区解析器来分析。
- "uimage-fw" 解析器读出 firmware 分区的头部,成功找到一个 uImage。
- 跃过 uImage,紧接着成功找到 squashfs 的头信息,于是找到了格式为 squashfs 的 rootfs。
- 解析器在找到一个分区后,会调用 __mtd_add_partition() 将此分区添加到系统中。
- __mtd_add_partition() 最后又调用 mtd_partition_split(),因为此时 rootfs 已经找到,所以会调用 split_rootfs_data() 找 rootfs_data 分区。
- rootfs 为 squashfs 分区,该格式的文件系统只读,且头信息里有标记分区大小。所以很容易就可以找到 rootfs_data 的起始位置。
openwrt spi flash 分区适配过程的更多相关文章
- (三)修改内核大小,适配目标板Nand flash分区配置
一. 修改内核大小 1. 在你的配置文件下uboot/include/config/xxx.h 里面有一个宏定义 #define MTDPARTS_DEFAULT "mtdparts=jz2 ...
- nand flash,nor flash,spi flash,片上RAM,片外RAM
Flash有掉电数据保存的特点,RAM掉电则数据丢失,但是RAM的速度更高,擦写次数理论上没有限制,而Flash则不行. Nand Flash相比其余的几种flash优势在于可擦写次数多,擦写速度快, ...
- OpenRisc-32-ORPSoC烧写外部spi flash
引言 经过前面的分析和介绍,我们对ORPSoC的启动过程(http://blog.csdn.net/rill_zhen/article/details/8855743)和 ORpSoC的debug子系 ...
- RTT下spi flash+elm fat文件系统移植小记
背景: MCU:STM32F207 SPI flash: Winbond W25Q16BV OS: RTT V1.1.1 bsp: STM32F20x 1 将spi_core.c,spi_dev.c及 ...
- RTThread DFS文件系统使用: 基于使用SFUD驱动的SPI FLASH之上的ELM FATFS文件系统
参考博文: 博文很长,但是实际要操作的步骤没几下. http://m.elecfans.com/article/730878.html 为了防止几年后文章链接找不到,我把文章复制过来了 /***** ...
- 16经典的SPI Flash的扇区擦除flash_se功能
一设计功能 对SPI_flash进行扇区擦除,分为写指令和扇区擦除两个时序部分. 二设计知识点 我简单理解flash,第一它是掉电不丢失数据的存储器,第二它每次写入新数据前首先得擦除数据,分为扇区擦除 ...
- 【原创】All in One i.MXRT1050/RT1020 SPI Flash Algorithm for J-Flash
2020年,这个给大家一种很漫长的恍惚感的一年,终于是过去了.这一年我们很多新的人生第一次就这么被发生了,第一次居家办公这么长时间(很多人肥膘都长了不少,我却瘦了2斤,不知是工作太积极了还是被家里小怪 ...
- 双系统Ubuntu分区扩容过程记录
本人电脑上安装了Win10 + Ubuntu 12.04双系统.前段时间因为在Ubuntu上做项目要安装一个比较大的软件,导致Ubuntu根分区的空间不够了.于是,从硬盘又分出来一部分空间,分给Ubu ...
- Nand Flash,Nor Flash,CFI Flash,SPI Flash 之间的关系
前言: 在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解.下面细说一下标题中的中Flash中的关系 一,Flash的内存存储结构 flash按照内部存 ...
随机推荐
- centos中简易安装docker
centos中简易安装docker准备环境要求:请确保自己的centos的内核版本大于3.10,使用如下linux命令: uname -r1显示如下类似信息: 3.10.0-862.3.3.el7.x ...
- 表单编码 appliation/x-www-form-urlencoded 与 multipart/form-data 的区别
当表单使用POST方法时,表单数据提交到服务器端之前有两种编码类型可供选择.默认编码类型为 application/x-www-form-urlencoded,此时所有非字母数字类型的字符都需要转换为 ...
- jdk1.7升级到1.8遇到的问题
1.修改project structure 里面的Project , Modules , SDKs jdk的版本 2.修改Java Compiler 里面java的jdk版本 3.tomcat 里面j ...
- poj 1637 混合图欧拉回路 学习笔记
题目大意 求混合图是否存在欧拉回路 做法 有向边我们只有增加入度出度 对于无向边,我们给它设定一个初始方向 如果不能满足|入度-出度|为偶数,无解 然后在网络流图中, 设设定方向的反向连一条边,表示反 ...
- Team Contests - Warmup(2016年多校热身赛,2016年黑龙江省赛)
Team Contests - Warmup A 题意:... 思路:不会 代码:... 随机 B 题意:给n个点,问是否有一个圆上有最少n/3个点 思路:随机大法好. 代码:... 递推 C 题意: ...
- 【MFC】 点击不同的按钮后在界面同一位置显示不同的对话框内容(转)
原文转自 http://bbs.csdn.net/topics/391039432 如图类似Tab控件的功能 但Tab控件按钮是固定的上下左右 不方便 所以想自己重新做个这种 我M ...
- MAMP 10.10下启动报错解决方案
cd /Applications/MAMP/Library/binmv envvars _envvars
- 咦?Oracle归档文件存哪了?
实验环境:RHEL 5.4 + Oracle 11.2.0.3 现象:日志切换后没找到归档日志目录. 1.查看归档日志路径 2.日志切换后并未找到归档目录 3.创建归档目录后再次观察 引申知识 1.查 ...
- Centos7源码安装MySQL5.7
a.连接数据库报111 从一台linux远程连接另一台linux上的MySQL,出现ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx. ...
- Linux内核源码分析--内核启动之zImage自解压过程
参考: http://blog.chinaunix.net/uid-20543672-id-3018233.html Linux内核编译流程分析 linux2.6内核启动分析--李枝果(不看是你的损失 ...