当前位置:首页>Linux>Linux I2C 设备寄存器读写流程:SGM41528_9 充电IC驱动实例拆解

Linux I2C 设备寄存器读写流程:SGM41528_9 充电IC驱动实例拆解

  • 2026-08-18 23:11:24
Linux I2C 设备寄存器读写流程:SGM41528_9 充电IC驱动实例拆解

Linux I2C 设备寄存器读写流程:SGM41528_9 实例

一、本文目标

本文以 SGM41528_9 充电芯片驱动为例,完整说明一个 Linux I2C 寄存器型设备的常见读写分层:

业务接口
    -> 寄存器字段接口
    -> 读改写接口
    -> 带锁寄存器接口
    -> SMBus 单字节接口
    -> I2C 控制器
    -> 芯片硬件寄存器

读完本文后,应能够回答以下问题:

1. i2c_smbus_read_byte_data() 和 i2c_smbus_write_byte_data() 分别做什么。 2. 为什么底层函数使用 s32 返回值,而输出数据使用 u8

 3. 为什么普通寄存器访问需要互斥锁。 

4. 为什么修改一个字段不能直接覆盖整个寄存器。 

5. regmaskshift 如何描述一个寄存器字段。 6. field_read() 和 field_write() 如何隐藏寄存器位运算细节。 

7. PG_STAT 如何变成 Linux 的 POWER_SUPPLY_PROP_ONLINE。 

8. 上层如何通过 Power Supply 接口修改 EN_CHG。 

9. I2C 错误如何逐层返回给调用者。 

10. 当前实现有哪些值得保留和需要改进的地方。

本文所有“当前代码行为”均以真实源码为准。芯片内部 Power Good 阈值、充电状态编码等硬件细节,如果源码不能证明,则明确标记为“需查数据手册”。

二、先理解三种数据

2.1 寄存器地址

寄存器地址用于指定要访问芯片内部的哪个寄存器,例如:

0x06:包含 EN_CHG 等控制字段
0x0B:包含 CHRG_STAT 等状态字段
0x0C:包含 PG_STAT 等输入状态字段

字段表确认 EN_CHG 位于 0x06CHRG_STAT 位于 0x0BPG_STAT 位于 0x0C

2.2 完整寄存器值

SGM 驱动使用单字节寄存器访问,因此一次底层读取获得一个 u8,即完整的 8 位寄存器值:

bit 7  bit 6  bit 5  bit 4  bit 3  bit 2  bit 1  bit 0

一个寄存器可能同时承载多个字段,所以读取出来的一个字节不一定只表示一种功能。

2.3 逻辑字段值

逻辑字段值是从完整寄存器中提取出的某一组位。例如 EN_CHG 只有一位,逻辑值是 0/1CHRG_STAT 占三位,逻辑值范围理论上是 0~7

驱动通过 mask 选择字段,通过 shift 把字段移动到 bit 0,形成上层容易使用的普通整数。

三、整体分层架构

图中业务入口由 Power Supply 描述符注册,读取回调为 sgm41528_9_get_property(),写入回调为 sgm41528_9_set_property()

字段层位于 field_read() 和 field_write(),带锁的完整寄存器读取由 read_reg() 完成,字段写入则通过 update_bits() 完成读改写。

最底层通过 Linux SMBus Byte Data API 与 I2C 设备通信。

四、I2C 设备对象和访问上下文

4.1 驱动私有结构体

SGM 驱动把 i2c_client、设备对象、Power Supply 对象和 I2C 互斥锁放在同一个私有结构体中:

struct sgm41528_9_device {
struct i2c_client *client;
struct device *dev;
struct power_supply *charger;
struct mutex lock;
struct mutex i2c_rw_lock;
/* 其他成员省略 */
};

其中:

成员
本文关注的作用
client
指向当前 I2C 从设备,底层 SMBus API 通过它找到适配器和设备地址
dev
用于设备日志、资源管理和设备模型
charger
已注册的 Power Supply 对象
i2c_rw_lock
串行化当前驱动内的寄存器读写和读改写操作

4.2 probe() 建立关联

I2C 核心调用驱动的 probe() 时传入 struct i2c_client *client。驱动把它保存到 sgm->client,并初始化 I2C 互斥锁:

sgm->client = client;
sgm->dev = dev;

mutex_init(&sgm->lock);
mutex_init(&sgm->i2c_rw_lock);

i2c_set_clientdata(client, sgm);

之后任何拿到 sgm 的函数,都可以通过 sgm->client 访问同一颗芯片,而不需要重复传递 I2C 总线号和从设备地址。

五、最底层单字节读取

5.1 完整源码

staticint __sgm41528_9_read_byte(struct sgm41528_9_device *sgm,
u8 reg, u8 *data)
{
s32 ret;

ret = i2c_smbus_read_byte_data(sgm->client, reg);
if (ret < 0) {
pr_err("i2c read fail: can't read from reg 0x%02X\n", reg);
return ret;
}

*data = (u8)ret;
return0;
}

5.2 参数含义

sgm  :当前芯片实例
reg  :需要读取的 8 位寄存器地址
data :输出参数,保存读取到的一个字节

函数返回值和输出值分开设计:

返回 0    :读取成功,数据写入 *data
返回负数 :读取失败,返回 Linux I2C 错误码

5.3 为什么 ret 使用 s32

i2c_smbus_read_byte_data() 成功时返回 0~255,失败时返回负错误码,因此不能直接用 u8 保存返回值。代码先用有符号 s32 接收,确认 ret >= 0 后再转换为 u8

读取失败时,*data 不会被更新。调用者必须先判断返回值,再使用输出数据。

5.4 SMBus Byte Data Read 总线过程

从协议角度看,i2c_smbus_read_byte_data(client, reg) 表示“以 reg 为命令码读取一个数据字节”。典型时序为:

S
-> Slave Address + Write
-> ACK
-> Command/Register Address
-> ACK
-> Repeated START
-> Slave Address + Read
-> ACK
-> Data Byte
-> NACK
-> P

符号含义:

S    :START
P    :STOP
ACK  :接收方应答
NACK :主机读取最后一个字节后结束传输

Linux I2C 核心和具体 I2C Adapter 驱动负责把 SMBus 请求转换成控制器传输;SGM 驱动只提供 client 和寄存器地址。

六、最底层单字节写入

6.1 完整源码

staticint __sgm41528_9_write_byte(struct sgm41528_9_device *sgm,
int reg, u8 val)
{
s32 ret;

ret = i2c_smbus_write_byte_data(sgm->client, reg, val);
if (ret < 0) {
pr_err("i2c write fail: can't write 0x%02X "
"to reg 0x%02X: %d\n", val, reg, ret);
return ret;
}

return0;
}

6.2 参数和返回值

sgm :当前芯片实例
reg :目标寄存器地址
val :需要写入的完整 8 位值

成功时返回 0,失败时返回底层负错误码。与读取不同,写操作没有额外输出参数。

6.3 SMBus Byte Data Write 总线过程

典型写入时序为:

S
-> Slave Address + Write
-> ACK
-> Command/Register Address
-> ACK
-> Data Byte
-> ACK
-> P

这个接口写入的是一个完整字节。如果目标寄存器包含多个字段,而业务只想修改其中一位,则不应该直接调用该接口覆盖整个寄存器,应使用后面的 update_bits() 或 field_write()

七、为什么底层函数名前有双下划线

__sgm41528_9_read_byte() 和 __sgm41528_9_write_byte() 中的双下划线不是 C 语言语法要求,而是本驱动采用的命名约定。

在当前实现中,这两个底层函数自身不获取 i2c_rw_lock。上层 read_reg() 和 update_bits() 会在调用它们之前加锁,因此双下划线可以理解为:

内部底层版本;调用者负责满足加锁或无并发前提

这只是代码约定,编译器不会自动阻止其他函数直接调用双下划线版本。

八、带锁的普通寄存器读取

8.1 完整源码

staticint sgm41528_9_read_reg(struct sgm41528_9_device *sgm,
      u8 reg, u8 *data)
{
int ret;

mutex_lock(&sgm->i2c_rw_lock);
ret = __sgm41528_9_read_byte(sgm, reg, data);
mutex_unlock(&sgm->i2c_rw_lock);

return ret;
}

8.2 互斥锁保护什么

i2c_rw_lock 让当前驱动中的访问者按顺序执行 I2C 寄存器操作,避免同一设备的不同线程同时进入底层传输。

这里使用 mutex,意味着调用路径必须处于允许睡眠的上下文。I2C 传输本身通常也可能睡眠,因此普通工作线程、probe()、sysfs 和 Power Supply 回调可以使用,硬中断上下文不能直接使用。

8.3 这把锁的边界

该锁只能约束遵守它的当前驱动代码。如果某个路径直接调用 __sgm41528_9_write_byte(),就会绕过这把锁。它也不能自动协调其他驱动或用户空间通过其他接口访问同一硬件。

九、修改寄存器部分位:Read-Modify-Write

9.1 为什么不能总是直接写整个寄存器

假设一个寄存器布局如下:

bit 7       bit 6       bit 5:4      bit 3       bit 2:0
EN_OTG      AUTO_DET    TREG         EN_CHG      OTHER

如果只想修改 EN_CHG,直接写一个固定字节可能同时覆盖 EN_OTGAUTO_DETTREG 和 OTHER。正确方式是:

读取旧寄存器值
-> 清除 EN_CHG 对应位
-> 合并新的 EN_CHG 值
-> 写回完整寄存器

9.2 完整源码

staticint sgm41528_9_update_bits(struct sgm41528_9_device *sgm,
 u8 reg, u8 mask, u8 val)
{
int ret;
u8 tmp;

mutex_lock(&sgm->i2c_rw_lock);

ret = __sgm41528_9_read_byte(sgm, reg, &tmp);
if (ret) {
pr_err("Failed: reg=%02X, ret=%d\n", reg, ret);
goto out;
}

tmp &= ~mask;
tmp |= val & mask;

ret = __sgm41528_9_write_byte(sgm, reg, tmp);
if (ret)
pr_err("Failed: reg=%02X, ret=%d\n", reg, ret);

out:
mutex_unlock(&sgm->i2c_rw_lock);
return ret;
}

9.3 核心公式

两行位运算:

tmp &= ~mask;
tmp |= val & mask;

等价于:

new_value = (old_value & ~mask) | (val & mask);

含义分别是:

old_value & ~mask :清除目标字段,保留其他位
val & mask        :只保留新值中属于目标字段的位
按位或             :把新字段合并到旧寄存器

9.4 位运算示例

假设:

old  = 0xAC = 10101100
mask = 0x0C = 00001100
val  = 0x04 = 00000100

清除目标字段:

~mask         = 11110011

10101100
11110011
-----------
10100000

合并新值:

val & mask    = 00000100

10100000
00000100
-----------
10100100 = 0xA4

最终只有 bit 3:2 被修改,其他位保持不变。

9.5 为什么锁必须覆盖读取和写回全过程

错误的锁范围可能产生丢失更新:

线程 A 读取 0x10
线程 B 修改并写回 0x20
线程 A 仍根据旧值 0x10 计算并写回
线程 B 的修改被覆盖

当前实现从读取前一直持锁到写回后,使“读、改、写”成为当前驱动内部不可交叉的事务。

9.6 为什么读取失败要跳到 out

读取失败后 tmp 无效,不能继续计算和写回。使用 goto out 可以统一释放互斥锁。如果直接在错误分支 return ret,会遗漏 mutex_unlock(),导致后续访问阻塞。

十、寄存器字段抽象

10.1 字段描述结构

struct sgm41528_9_fields {
u8 reg;
u8 shift;
u8 mask;
};

成员含义:

成员
含义
示例
reg
字段位于哪个寄存器
EN_CHG
 位于 0x06
shift
字段最低有效位距离 bit 0 的位移
EN_CHG
 位于 bit 3,所以 shift=3
mask
字段在寄存器中占用哪些位
bit 3 对应 0x08

10.2 枚举和字段表

驱动先用枚举为字段命名:

enum SGM41528_9_BIT_OPTION {
/* ... */
F_BIT_EN_CHG,
/* ... */
F_BIT_CHRG_STAT,
F_BIT_PG_STAT,
/* ... */
F_BIT_MAX,
};

再通过指定初始化器建立映射:

staticconststruct sgm41528_9_fields
sgm41528_9_regs[F_BIT_MAX] = {
[F_BIT_ICHG]      = {0x010, GENMASK(50)},
[F_BIT_WD]        = {0x054, GENMASK(54)},
[F_BIT_EN_CHG]    = {0x063, GENMASK(33)},
[F_BIT_CHRG_STAT] = {0x0B0, GENMASK(20)},
[F_BIT_PG_STAT]   = {0x0C7, GENMASK(77)},
};

10.3 GENMASK()

GENMASK(high, low) 生成从 bit high 到 bit low 连续为 1 的掩码:

GENMASK(33) = 00001000 = 0x08
GENMASK(54) = 00110000 = 0x30
GENMASK(50) = 00111111 = 0x3F
GENMASK(77) = 10000000 = 0x80

10.4 shift 的本质

shift 是字段最低有效位的 bit 编号,也就是 mask 中最右侧那个 1 所在的位置。

字段位置
mask
shift
bit 0
0000 0001
0
bit 3
0000 1000
3
bit 3:2
0000 1100
2
bit 5:4
0011 0000
4
bit 7:6
1100 0000
6

shift 负责在两种表示之间转换:

寄存器对齐值 --右移 shift--> 右对齐逻辑值
右对齐逻辑值 --左移 shift--> 寄存器对齐值

11、字段读取 field_read()

11.1 完整源码

staticint sgm41528_9_field_read(struct sgm41528_9_device *sgm,
enum SGM41528_9_BIT_OPTION field_id)
{
int ret;
u8 val;

ret = sgm41528_9_read_reg(
sgm,
sgm41528_9_regs[field_id].reg,
&val);
if (ret < 0)
return ret;

val &= sgm41528_9_regs[field_id].mask;
val >>= sgm41528_9_regs[field_id].shift;

return val;
}

11.2 读取公式

field_value = (register_value & mask) >> shift;

流程为:

field_id
-> 查表得到 reg/mask/shift
-> 读取完整寄存器
-> mask 清除无关位
-> 右移 shift
-> 返回逻辑字段值

11.3 为什么返回类型是 int

字段本身只有 u8,但函数需要同时返回字段值和负错误码:

>= 0:字段值
<  0:I2C 读取错误

所以上层必须先执行:

ret = sgm41528_9_field_read(...);
if (ret < 0)
return ret;

再把 ret 当作字段值。

12、字段写入 field_write()

12.1 完整源码

staticint sgm41528_9_field_write(struct sgm41528_9_device *sgm,
enum SGM41528_9_BIT_OPTION field_id,
      u8 val)
{
return sgm41528_9_update_bits(
sgm,
sgm41528_9_regs[field_id].reg,
sgm41528_9_regs[field_id].mask,
val << sgm41528_9_regs[field_id].shift);
}

12.2 写入公式

aligned_value = logical_value << shift;
new_register = (old_register & ~mask) |
      (aligned_value & mask);

上层传入的是右对齐逻辑值。例如 EN_CHG 位于 bit 3,上层传 1field_write() 自动计算:

1 << 3 = 0x08

然后 update_bits() 把 0x08 写入 bit 3,不影响其他位。

13、完整读取实例:PG_STAT 到 ONLINE

13.1 PG_STAT 字段定义

[F_BIT_PG_STAT] = {0x0C7, GENMASK(77)};

对应:

reg   = 0x0C
shift = 7
mask  = 0x80

13.2 业务调用

Power Supply getter 读取:

online = sgm41528_9_field_read(sgm, F_BIT_PG_STAT);
if (online < 0) {
dev_err(sgm->dev,
"%s: read PG_STAT failed, ret=%d\n",
__func__, online);
return online;
}

POWER_SUPPLY_PROP_ONLINE 分支把非零值规范化成 1:

case POWER_SUPPLY_PROP_ONLINE:
val->intval = !!online;
break;

13.3 完整调用链

上层充电管理器通过名称取得真实充电器 Power Supply,并读取 POWER_SUPPLY_PROP_ONLINE

13.4 位提取示例

假设芯片 REG0C 返回:

REG0C = 0xB0 = 10110000
mask  = 0x80 = 10000000
shift = 7

计算:

(10110000 & 10000000) >> 7
10000000 >> 7
1

因此 Linux ONLINE 返回 1。

13.5 PG_STAT 如何知道输入在线

源码确认的是:驱动读取 REG0C.bit7 并把它作为 online。驱动本身没有根据电压做软件计算。

硬件机制推断:SGM41528_9 内部监测 VBUS 输入,在满足芯片 Power Good 条件时置位 PG_STAT,条件失效时清零。具体输入阈值、去抖时间和异常条件必须查 SGM41528_9 数据手册,当前仓库没有提供这些定义。

14、为什么 ONLINE 不等于“正在充电”

PG_STAT 描述输入侧是否存在有效电源,CHRG_STAT 描述充电状态机当前阶段,两者语义不同。

ONLINE    :外部输入电源是否有效
CHRG_STAT :芯片当前是否未充电、涓流、预充、快充或终止

即使 ONLINE=1,也可能由于软件关闭 EN_CHG、电池已满或保护条件而没有实际充电。

当前 STATUS 逻辑先判断 online,再解释 chg_stat

case POWER_SUPPLY_PROP_STATUS:
if (!online)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
elseif (chg_stat == 0)
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
elseif (chg_stat == 1 || chg_stat == 2)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
elseif (chg_stat == 3)
val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break;

这说明“输入在线”和“充电阶段”必须分别读取,然后组合成上层状态。

15、完整写入实例:控制 EN_CHG

15.1 EN_CHG 字段定义

[F_BIT_EN_CHG] = {0x063, GENMASK(33)};

对应:

reg   = 0x06
shift = 3
mask  = 0x08

15.2 Power Supply 写入口

staticint sgm41528_9_set_property(
struct power_supply *psy,
enum power_supply_property prop,
constunion power_supply_propval *val)
{
struct sgm41528_9_device *sgm =
power_supply_get_drvdata(psy);
int ret = -EINVAL;

switch (prop) {
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
ret = sgm41528_9_chg_enable_set(
sgm, !!val->intval);
break;
default:
return -EINVAL;
}

return ret;
}

15.3 转换为字段写入

ret = sgm41528_9_field_write(
sgm,
F_BIT_EN_CHG,
enable ? 1 : 0);

15.4 完整调用链

上层 tp_chg_manager 通过 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 请求开启或关闭真实充电器。

15.5 位更新计算

假设寄存器 0x06 原值是:

old = 0x34 = 00110100

开启充电:

logical value = 1
aligned       = 1 << 3 = 0x08
mask          = 0x08

new = (0x34 & ~0x08) | (0x08 & 0x08)
    = 0x3C

关闭充电:

logical value = 0
aligned       = 0 << 3 = 0x00

new = (0x3C & ~0x08) | (0x00 & 0x08)
    = 0x34

整个过程只改变 bit 3。

16、sysfs 寄存器调试路径

当前驱动提供寄存器调试属性,可以从设备对应的 I2C sysfs 目录读取或写入寄存器。

读取路径使用带锁的 sgm41528_9_read_reg()

sgm41528_9_read_reg(sgm, reg, &val);

写入路径当前直接调用底层未加锁函数:

__sgm41528_9_write_byte(sgm, (int)reg, val);

设备路径通常可通过以下命令查找:

find /sys -name sgm41529_all_regs 2>/dev/null
find /sys -name sgm41529_rw_reg 2>/dev/null

I2C 设备目录通常类似:

/sys/bus/i2c/devices/1-006b/

具体总线号和地址以设备实际枚举结果为准。

17、推荐的通用 I2C 寄存器访问模板

下面把 SGM 的思路提炼成更完整的通用模板。示例代码用于讲解设计,不代表已经修改当前驱动。

17.1 底层未加锁接口

staticint __chip_read_byte(struct chip_device *chip,
   u8 reg, u8 *data)
{
s32 ret;

ret = i2c_smbus_read_byte_data(chip->client, reg);
if (ret < 0)
return ret;

*data = (u8)ret;
return0;
}

staticint __chip_write_byte(struct chip_device *chip,
    u8 reg, u8 val)
{
return i2c_smbus_write_byte_data(chip->client, reg, val);
}

17.2 带锁完整寄存器接口

staticint chip_read_reg(struct chip_device *chip,
u8 reg, u8 *data)
{
int ret;

mutex_lock(&chip->io_lock);
ret = __chip_read_byte(chip, reg, data);
mutex_unlock(&chip->io_lock);

return ret;
}

staticint chip_write_reg(struct chip_device *chip,
 u8 reg, u8 val)
{
int ret;

mutex_lock(&chip->io_lock);
ret = __chip_write_byte(chip, reg, val);
mutex_unlock(&chip->io_lock);

return ret;
}

17.3 带锁位更新接口

staticint chip_update_bits(struct chip_device *chip,
   u8 reg, u8 mask, u8 val)
{
int ret;
u8 old, new;

mutex_lock(&chip->io_lock);

ret = __chip_read_byte(chip, reg, &old);
if (ret < 0)
goto out;

new = (old & ~mask) | (val & mask);
if (new == old) {
ret = 0;
goto out;
}

ret = __chip_write_byte(chip, reg, new);

out:
mutex_unlock(&chip->io_lock);
return ret;
}

这里增加 new == old 判断,可以在字段值没有变化时跳过 I2C 写入。是否需要该优化取决于芯片行为和项目要求。

17.4 字段描述和字段接口

struct chip_field {
u8 reg;
u8 shift;
u8 mask;
};

staticint chip_field_read(struct chip_device *chip,
unsignedint field_id)
{
conststruct chip_field *field;
int ret;
u8 value;

if (field_id >= FIELD_MAX)
return -EINVAL;

field = &chip_fields[field_id];

ret = chip_read_reg(chip, field->reg, &value);
if (ret < 0)
return ret;

return (value & field->mask) >> field->shift;
}

staticint chip_field_write(struct chip_device *chip,
unsignedint field_id,
   u8 value)
{
conststruct chip_field *field;
u8 max;

if (field_id >= FIELD_MAX)
return -EINVAL;

field = &chip_fields[field_id];
max = field->mask >> field->shift;
if (value > max)
return -EINVAL;

return chip_update_bits(
chip,
field->reg,
field->mask,
value << field->shift);
}

18、什么时候使用哪个接口

需求
推荐接口
原因
读取完整 8 位寄存器
read_reg()
有统一锁和错误处理
写入完整 8 位寄存器
write_reg()
避免调用者绕过锁
修改寄存器部分位
update_bits()
保留非目标字段
读取业务字段
field_read()
自动处理 reg/mask/shift
写入业务字段
field_write()
自动左移并安全更新目标位
已持有 I/O 锁的内部事务
__read_byte()
 / __write_byte()
避免重复加锁

一般业务代码应优先使用字段接口;寄存器调试和芯片初始化可以使用完整寄存器接口;双下划线底层接口应限制在驱动内部受控路径。

19、总结

SGM41528_9 的寄存器读写路径体现了 Linux I2C 寄存器型驱动的典型分层:

最底层:i2c_smbus_read_byte_data / write_byte_data
    -> 完成单字节总线访问

寄存器层:read_reg / update_bits
    -> 提供互斥保护和读改写

字段层:field_read / field_write
    -> 使用 reg、mask、shift 操作具体功能字段

业务层:get_property / set_property
    -> 把硬件字段转换成 ONLINE、STATUS、EN_CHG 等系统语义

上层管理:tp_chg_manager
    -> 周期读取状态并控制充电策略

最重要的设计原则是:

1. 底层总线返回值和寄存器数据必须分开处理。

 2. 运行期 I2C 访问需要统一的并发保护策略。 

3. 读改写必须在同一锁范围内完成。 

4. 修改单个字段时必须保留寄存器其他位。

 5. 用字段表集中管理寄存器地址、掩码和位移。 

6. 上层优先使用字段接口,而不是重复硬编码寄存器魔数。 

7. 所有 I2C 错误必须逐层返回,不能只打印日志后假装成功。 

8. 芯片状态编码和特殊位语义必须以数据手册为最终依据。

【往期推荐】

USB 四种传输模式详解:为什么键盘、U盘和摄像头走的不是一条路

驱动篇|休眠功耗相关原理解析:从电源域到唤醒源

AI如此智能的时代,搞技术还有出路吗?

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 22:53:07 HTTP/2.0 GET : https://f.mffb.com.cn/a/507260.html
  2. 运行时间 : 0.243355s [ 吞吐率:4.11req/s ] 内存消耗:4,870.23kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=9618518ce26e009a48488c821da41a81
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000939s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001516s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.003055s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000637s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001180s ]
  6. SELECT * FROM `set` [ RunTime:0.000520s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001304s ]
  8. SELECT * FROM `article` WHERE `id` = 507260 LIMIT 1 [ RunTime:0.013134s ]
  9. UPDATE `article` SET `lasttime` = 1787323987 WHERE `id` = 507260 [ RunTime:0.046315s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.004404s ]
  11. SELECT * FROM `article` WHERE `id` < 507260 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001118s ]
  12. SELECT * FROM `article` WHERE `id` > 507260 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000866s ]
  13. SELECT * FROM `article` WHERE `id` < 507260 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.010988s ]
  14. SELECT * FROM `article` WHERE `id` < 507260 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.003542s ]
  15. SELECT * FROM `article` WHERE `id` < 507260 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001920s ]
0.246784s