跳转至

嵌入式软件平台/芯片确认与驱动来源追踪研究

1. uclass_first_device_err 函数归属

框架: U-Boot Driver Model (DM) 驱动程序模型

头文件位置: include/dm/uclass.h

实现文件: drivers/core/uclass.c

函数原型:

/**
 * uclass_first_device_err() - Get the first device in a uclass
 *
 * The device returned is probed if necessary, and ready for use if no error is
 * returned
 *
 * @id: Uclass ID to look up
 * @devp: Returns pointer to the first device in that uclass, or NULL if none
 * Return: 0 if found, -ENODEV if not found, other -ve on error
 */
int uclass_first_device_err(enum uclass_id id, struct udevice **devp);

功能说明: - 获取指定 uclass 中的第一个设备 - 自动探测设备(如果需要) - 返回错误码:0 表示成功,-ENODEV 表示未找到设备,其他负值表示错误 - 与 uclass_first_device() 的区别:后者跳过探测失败的设备,而 _err 版本会返回探测错误

相关函数: - uclass_first_device() - 获取第一个设备(跳过探测失败的) - uclass_next_device_err() - 获取下一个设备(带错误处理) - uclass_first_device_check() - 获取第一个设备(检查模式) - uclass_get() - 获取 uclass 实例


2. 嵌入式项目中确认目标平台和芯片的方法

2.1 编译时确定(Kconfig 系统)

U-Boot 使用 Kconfig 系统进行架构和板级选择:

架构选择文件: arch/Kconfig

choice
    prompt "Architecture select"
    default SANDBOX

config ARC
    bool "ARC architecture"
    select DM
    select CLK
    select SUPPORT_OF_CONTROL
    ...

config ARM
    bool "ARM architecture"
    select DM
    select SUPPORT_OF_CONTROL
    ...

config ARM64
    bool "ARM 64-bit architecture"
    ...

板级配置: configs/<board>_defconfig

每个支持的板子都有对应的 defconfig 文件,例如: - configs/TQM823L_defconfig - configs/rk3399_defconfig

编译命令:

make <board>_defconfig
make

2.2 运行时确定

方法 1: 通过设备树(Device Tree)

// 读取设备树中的 compatible 字符串
ofnode_get_compatible_list(dev_ofnode(dev), compat, ARRAY_SIZE(compat));

方法 2: 通过 U-Boot 命令

1
2
3
4
5
# 在 U-Boot 命令行中
=> bdinfo    # 显示板级信息
=> cpu info   # 显示 CPU 信息
=> dm tree    # 显示驱动模型设备树
=> dm class   # 按 uclass 显示设备

方法 3: 通过代码查询

1
2
3
4
5
6
7
// 获取 CPU 信息
struct udevice *cpu;
uclass_first_device_err(UCLASS_CPU, &cpu);

// 获取板级信息
struct udevice *board;
uclass_first_device_err(UCLASS_BOARD, &board);

2.3 维护者查询工具

使用 scripts/get_maintainer.pl 查询特定板子/子系统的维护者:

1
2
3
4
5
# 查询文件的维护者
perl scripts/get_maintainer.pl -f drivers/mtd/nand/spi/core.c

# 查询补丁的维护者
perl scripts/get_maintainer.pl <patch_file>

3. SPI/QSPI NAND Flash 驱动代码来源追踪

3.1 驱动目录结构

drivers/mtd/nand/spi/
├── core.c              # 核心驱动框架
├── otp.c               # OTP (One-Time Programmable) 支持
├── alliancememory.c    # Alliance Memory 芯片支持
├── ato.c               # ATO 芯片支持
├── esmt.c              # ESMC 芯片支持
├── fmsh.c              # 飞索半导体支持
├── foresee.c           # Foresee 芯片支持
├── gigadevice.c        # 兆易创新 (GigaDevice) 支持
├── macronix.c          #  Macronix 支持
├── micron.c            # 美光 (Micron) 支持
├── paragon.c           # Paragon 支持
├── skyhigh.c           # SkyHigh 支持
├── toshiba.c           # 东芝支持
├── winbond.c           # 华邦支持
└── xtx.c               # 芯天下支持

3.2 核心驱动文件分析

drivers/mtd/nand/spi/core.c

关键特性: - 同时支持 Linux 内核和 U-Boot(通过 #ifndef __UBOOT__ 条件编译) - 使用 SPI MEM 操作框架 - 支持多种 SPI 传输模式(1S-1S-1S, 1S-2S-2S, 1S-4S-4S 等)

U-Boot 特定包含:

#else
#include <errno.h>
#include <watchdog.h>
#include <spi.h>
#include <spi-mem.h>
#include <ubi_uboot.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/mtd/spinand.h>
#include <linux/printk.h>
#include <linux/delay.h>
#endif

3.3 厂商标识定义

各厂商 SPI NAND 的制造商 ID 定义:

// GigaDevice (兆易创新)
#define SPINAND_MFR_GIGADEVICE  0xC8

// Micron (美光)
#define SPINAND_MFR_MICRON      0x2c

// Macronix
#define SPINAND_MFR_MACRONIX    0xC2

// Winbond (华邦)
#define SPINAND_MFR_WINBOND     0xEF

// Toshiba (东芝)
#define SPINAND_MFR_TOSHIBA     0x98

3.4 驱动维护信息

子系统维护者 (来自 MAINTAINERS 文件):

1
2
3
4
5
6
SPI NAND
M:  Dario Binacchi <dario.binacchi@amarulasolutions.com>
M:  Michael Trimarchi <michael@amarulasolutions.com>
R:  Frieder Schrempf <frieder.schrempf@kontron.de>
S:  Maintained
T:  git https://source.denx.de/u-boot/custodians/u-boot-nand-flash.git

相关子系统: - SPI: drivers/spi/ (Orphaned, custodian: u-boot-spi) - SPI-NOR: drivers/mtd/spi/ (Maintained by Vignesh R) - RAW NAND: drivers/mtd/nand/raw/ (Maintained by Dario Binacchi)

3.5 代码来源追踪方法

方法 1: Git 历史查询

1
2
3
4
5
6
7
8
# 查看文件的提交历史
git log --oneline drivers/mtd/nand/spi/core.c

# 查看特定行的作者
git blame drivers/mtd/nand/spi/core.c

# 查找引入特定函数的提交
git log -S "uclass_first_device_err" --oneline

方法 2: 查看 Kconfig 配置

1
2
3
4
5
# 搜索 SPI NAND 相关配置
grep -r "MTD_SPI_NAND" drivers/mtd/nand/spi/Kconfig

# 查看哪些板子启用了 SPI NAND
grep -r "MTD_SPI_NAND" configs/

方法 3: 查看设备树绑定

1
2
3
4
5
6
7
8
# 设备树中 SPI NAND 节点示例
&spi0 {
    flash@0 {
        compatible = "gigadevice,gd5f1gq4uf90", "spi-nand";
        reg = <0>;
        spi-max-frequency = <104000000>;
    };
};

3.6 Makefile 构建配置

drivers/mtd/nand/spi/Makefile:

1
2
3
4
spinand-objs := core.o otp.o
spinand-objs += alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o
spinand-objs += micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o


4. 实用命令汇总

4.1 U-Boot 编译配置

# 列出所有支持的板子
make | grep defconfig

# 配置特定板子
make rk3399_defconfig

# 查看当前配置
grep CONFIG_ .config | head -50

# 编译
make -j$(nproc)

4.2 驱动模型调试

1
2
3
4
5
6
# 在 U-Boot 命令行
=> dm tree           # 显示设备树
=> dm class spi      # 显示 SPI 设备
=> dm class mtd      # 显示 MTD 设备
=> dm info           # 显示设备详细信息
=> dm uclass         # 列出所有 uclass

4.3 代码搜索

1
2
3
4
5
6
7
8
# 搜索函数定义
grep -rn "uclass_first_device_err" drivers/

# 搜索特定芯片支持
grep -rn "SPINAND_MFR_" drivers/mtd/nand/spi/

# 搜索设备树兼容字符串
grep -rn "compatible.*spi-nand" arch/*/dts/

5. 参考资源


研究完成时间:2026-03-12