终端操作和输出:
清理项目
ada@raspberrypi:~/mt3502 $ make clean
make -C /lib/modules/6.6.51+rpt-rpi-v8/build M=/home/ada/mt3502 clean
make[1]: 进入目录“/usr/src/linux-headers-6.6.51+rpt-rpi-v8”
CLEAN /home/ada/mt3502/Module.symvers
make[1]: 离开目录“/usr/src/linux-headers-6.6.51+rpt-rpi-v8”
编译模块
ada@raspberrypi:~/mt3502 $ make
make -C /lib/modules/6.6.51+rpt-rpi-v8/build M=/home/ada/mt3502 modules
make[1]: 进入目录“/usr/src/linux-headers-6.6.51+rpt-rpi-v8”
CC [M] /home/ada/mt3502/mt350x.o
MODPOST /home/ada/mt3502/Module.symvers
CC [M] /home/ada/mt3502/mt350x.mod.o
LD [M] /home/ada/mt3502/mt350x.ko
make[1]: 离开目录“/usr/src/linux-headers-6.6.51+rpt-rpi-v8”
卸载模块(未加载)
ada@raspberrypi:~/mt3502 $ sudo rmmod mt350x
rmmod: ERROR: Module mt350x is not currently loaded
编译设备树源文件
ada@raspberrypi:~/mt3502 $ dtc -@ -I dts -O dtb -o mt350x.dtbo mt350x.dts
加载设备树覆盖层
ada@raspberrypi:~/mt3502 $ sudo dtoverlay -l | grep mt350x
ada@raspberrypi:~/mt3502 $ sudo dtoverlay mt350x.dtbo
ada@raspberrypi:~/mt3502 $ sudo dtoverlay -l | grep mt350x
0: mt350x
加载内核模块
ada@raspberrypi:~/mt3502 $ lsmod | grep mt350x
ada@raspberrypi:~/mt3502 $ sudo insmod mt350x.ko
ada@raspberrypi:~/mt3502 $ lsmod | grep mt350x
mt350x 16384 0
说明
make clean:清理项目中的编译生成文件。make:编译内核模块。sudo rmmod mt350x:尝试卸载模块(模块未加载时会报错)。dtc:编译设备树源文件为.dtbo文件。sudo dtoverlay:加载设备树覆盖层。sudo insmod mt350x.ko:加载内核模块。-
lsmod | grep mt350x:检查模块是否已加载。
更新su密码
ada@raspberrypi:/ $ sudo passwd root
新的密码:
重新输入新的密码:
passwd:已成功更新密码
ada@raspberrypi:/ $ su
密码:
寻找节点路径
root@raspberrypi:/# cd /sys/class/i2c-dev/
root@raspberrypi:/sys/class/i2c-dev# ls
i2c-1 i2c-2
root@raspberrypi:/sys/class/i2c-dev# cd i2c-1
root@raspberrypi:/sys/class/i2c-dev/i2c-1# ls
dev device name power subsystem uevent
root@raspberrypi:/sys/class/i2c-dev/i2c-1# cd device
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device# ls
1-0075 delete_device device i2c-dev name new_device of_node power subsystem uevent
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device# cd 1-0075
节点目录
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device/1-0075# ls
calibrate displacement driver modalias name of_node power subsystem sum_delta uevent
读取数据
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device/1-0075# cat displacement
delta_x: 0, delta_y: 0
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device/1-0075# cat sum_delta
sum_delta_x: 846, sum_delta_y: 0
执行校准命令
root@raspberrypi:/sys/class/i2c-dev/i2c-1/device/1-0075# echo 1 > calibrate
1
解决方案:
- 设备树内容示例:
设备树中需声明 I2C 设备地址和兼容性字符串,例如:/ { compatible = "raspberrypi,model"; fragment@0 { target = <&i2c1>; __overlay__ { #address-cells = <1>; #size-cells = <0>; mt350x: mt350x@50 { compatible = "your-company,mt350x"; reg = <0x50>; // I2C 设备地址 }; }; }; };- 关键点:
compatible必须与驱动代码中的of_match_table匹配。reg指定设备的 I2C 地址(如0x50)。
- 关键点:
2. 检查驱动代码
驱动代码(mt350x.c)需要包含以下关键逻辑:
-
绑定设备树的
compatible:static const struct of_device_id mt350x_of_match[] = { { .compatible = "your-company,mt350x" }, {}, }; MODULE_DEVICE_TABLE(of, mt350x_of_match); -
注册 I2C 驱动:
static struct i2c_driver mt350x_driver = { .driver = { .name = "mt350x", .of_match_table = mt350x_of_match, }, .probe = mt350x_probe, .remove = mt350x_remove, }; module_i2c_driver(mt350x_driver); -
在
probe()中创建设备节点:static int mt350x_probe(struct i2c_client *client, const struct i2c_device_id *id) { // 创建设备节点(例如 /dev/mt350x) dev = device_create(class, NULL, dev_num, NULL, "mt350x"); // 初始化 I2C 通信 ... return 0; }
操作流程总结
-
设备树编译:
编译增量设备树源文件
安装设备树编译工具
sudo apt-get install device-tree-compiler使用 dtc 进行编译
dtc -@ -I dts -O dtb -o mt350x.dtbo mt350x.dts分析步骤:
检查设备树配置
- 确认是否已添加设备树覆盖:
如果你有.dts或.dtbo文件(如mt350x.dtbo),需确保它已正确应用到系统中:# 查看已加载的设备树覆盖 sudo dtoverlay -l | grep mt350x- 如果未加载,手动加载:
sudo dtoverlay mt350x.dtbo
- 如果未加载,手动加载:
- 确认是否已添加设备树覆盖:
-
加载驱动模块:
sudo rmmod mt350x sudo insmod mt350x.ko分析步骤:
-
检查模块是否已加载:
运行以下命令,查看模块是否在已加载列表中:lsmod | grep mt350x- 如果看到输出结果,说明模块已加载。
-
卸载已存在的模块:
如果模块已加载,使用rmmod卸载它:sudo rmmod mt350x- 注意:模块名可能不包含
.ko后缀,直接使用mt350x。
- 注意:模块名可能不包含
-
重新加载模块:
卸载成功后,再次尝试加载:sudo insmod mt350x.ko
验证模块是否正常工作:
虽然模块已加载,但你可能需要确认它是否按预期工作。以下是验证步骤:
-
查看内核日志:
运行以下命令,检查模块加载时的输出(可能有初始化信息或错误):dmesg | grep mt350x- 如果看到类似
mt350x: module loaded successfully的日志,说明一切正常。
- 如果看到类似
-
检查设备节点或接口:
- 如果这是一个设备驱动(例如字符设备),检查
/dev/下是否生成了对应的设备文件:ls -l /dev/mt350x* # 替换为你的设备名 - 如果涉及网络或硬件接口,检查相关工具的输出(如
ifconfig、i2cdetect等)。
- 如果这是一个设备驱动(例如字符设备),检查
总结:
- 当前状态正常,模块已成功加载。
- 无需再次执行
insmod,除非你修改了模块代码需要重新加载。 - 如需调试,优先通过
dmesg查看内核日志。
-
-
验证设备节点和 I2C 地址:
ls /dev/mt350x* # 检查设备节点 sudo i2cdetect -y 1 # 检查 I2C 设备是否存在
常见问题
- 设备树未生效:确保
.dtbo文件已复制到/boot/overlays/并在/boot/config.txt中添加dtoverlay=mt350x。 - 驱动未绑定设备树:检查驱动代码中的
compatible字符串是否与设备树一致。 - 权限问题:如果设备节点已创建但无访问权限,使用
sudo chmod 666 /dev/mt350x。
调试步骤
1. 验证 I2C 设备是否被识别
-
检查 I2C 总线上的设备:
# 安装 i2c 工具 sudo apt install i2c-tools # 扫描 I2C 总线(假设设备挂在 i2c-1) sudo i2cdetect -y 1- 输出中应显示设备地址(如
0x50)为UU或具体值。
- 输出中应显示设备地址(如
-
查看 sysfs 中的设备:
ls /sys/bus/i2c/devices/ # 查找类似 "1-0050" 的条目
2. 检查内核日志
即使 dmesg | grep mt350x 无输出,也可能有其他错误:
dmesg | tail -n 30 # 查看最近 30 条日志,搜索 "error" 或 "i2c"
问题原因分析:
-
仅加载内核模块不足以创建设备节点:
- I2C 设备通常需要 设备树(Device Tree) 或 手动注册 来声明设备地址和配置。
- 如果模块未绑定到具体的 I2C 设备节点,驱动可能无法触发
probe()函数,导致设备节点未生成。
-
可能缺失的环节:
- 设备树中未定义该 I2C 设备的节点。
- 内核模块未正确关联到设备树的
compatible字符串。 - 驱动代码中未注册字符设备或未调用创建设备节点的接口(如
device_create)。
你可以通过以下命令让内核日志(包括你的驱动输出)持续实时显示:
1. 使用 dmesg 的 follow 模式
sudo dmesg -w
- 效果:实时显示新增的内核日志(按
Ctrl+C退出)。 - 过滤特定关键字(如
mt350x):sudo dmesg -w | grep mt350x- 如果
grep导致输出延迟,添加--line-buffered参数:sudo dmesg -w | grep --line-buffered mt350x
- 如果
2. 使用 tail 跟踪日志文件
Debian 系统的内核日志通常保存在 /var/log/kern.log 或 /var/log/syslog:
sudo tail -f /var/log/kern.log | grep mt350x
或
sudo tail -f /var/log/syslog | grep mt350x
3. 使用 journalctl(systemd 系统)
sudo journalctl -f -k | grep mt350x
- 参数解释:
-f:实时跟踪新日志。-k:仅显示内核日志。
4. 在驱动代码中增加调试日志(可选)
如果日志输出频率不够,可以修改驱动代码(mt350x.c)中的 printk 语句:
// 示例:在 mt350x_read_displacement 函数中添加更多信息
printk(KERN_INFO "mt350x: displacement=%d, direction=%d, steps=%d\n",
displacement, motion_direction, motion_steps_detected);
重新编译并加载模块后,日志会更详细。
5. 调整日志级别(可选)
如果日志被屏蔽(如 printk 级别低于当前控制台日志级别),可以临时调整:
# 允许所有级别的日志显示
sudo dmesg -n debug
操作示例:
# 终端1:持续跟踪内核日志并过滤 mt350x
sudo dmesg -w | grep --line-buffered mt350x
# 终端2:触发传感器动作(例如移动设备)
# 观察终端1的输出是否变化
常见问题:
- 无实时输出:确保传感器正在被物理操作(例如移动),或检查驱动代码中
printk的触发条件。 - 日志过多:调整驱动代码中的打印频率(例如减少
msleep(512)的间隔)。 - 权限问题:使用
sudo执行命令。
如果问题依旧,建议检查驱动代码中的数据处理逻辑(例如 motion_direction 和 motion_steps_detected 是否被正确更新)。
20250325更新:
1、发现居然可以一条命令执行,比较省事,感觉发现新大陆,
2、可以持久化设备树覆盖
编译命令
make clean && make && sudo rmmod mt350x.ko && sudo insmod mt350x.ko
检查并加载设备树覆盖
用一条命令来完成检查设备树覆盖是否加载,如果没有加载则自动加载它:
dtc -@ -I dts -O dtb -o mt350x.dtbo mt350x.dts && sudo dtoverlay -l | grep -q mt350x || sudo dtoverlay mt350x.dtbo
命令解释:
• sudo dtoverlay -l:列出当前已加载的所有设备树覆盖。
• | grep -q mt350x:在输出中查找mt350x。-q参数表示安静模式,不输出任何内容,只返回状态码(0表示找到,1表示未找到)。
• ||:逻辑“或”操作符。如果前面的命令返回非零状态码(即mt350x未加载),则执行后面的命令。
• sudo dtoverlay mt350x.dtbo:加载mt350x.dtbo设备树覆盖文件。
使用场景:
• 如果mt350x已经加载,grep会返回 0,命令链停止,不会尝试重新加载。
• 如果mt350x未加载,grep会返回 1,触发加载命令。
在用户空间手动创建目录并设置权限
sudo mkdir -p /data/calibration
sudo chmod 777 /data/calibration
查看校准数据
root@raspberrypi:/sys/bus/i2c/devices/1-0075# ls
calibrate driver modalias name of_node power read_calibrate read_displacement read_sum_delta subsystem uevent
root@raspberrypi:/sys/bus/i2c/devices/1-0075# cat read_calibrate
calibrate_data: 73
root@raspberrypi:/sys/bus/i2c/devices/1-0075# cat read_sum_delta
sum_delta_x: 333, sum_delta_y: 0
root@raspberrypi:/sys/bus/i2c/devices/1-0075# echo 1 > calibrate
root@raspberrypi:/sys/bus/i2c/devices/1-0075# cat read_calibrate
calibrate_data: 59
root@raspberrypi:/sys/bus/i2c/devices/1-0075#
校准后查看校准数据
root@raspberrypi:/home/ada# cd /
root@raspberrypi:/# ls
bin boot data dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var
root@raspberrypi:/# cd data
root@raspberrypi:/data# ls
calibration
root@raspberrypi:/data# cd calibration
root@raspberrypi:/data/calibration# ls
mt350x_calibration_data.dat
root@raspberrypi:/data/calibration# cat mt350x_calibration_data.dat
59
root@raspberrypi:/data/calibration#
持久化设备树覆盖
如果你希望设备树覆盖在系统重启后仍然生效,可以将其添加到/boot/config.txt文件中。
1.将编译后的.dtbo文件复制到正确的目录
sudo cp mt350x.dtbo /boot/overlays/
2.加载增量设备树
编辑/boot/config.txt文件:
sudo nano /boot/config.txt
或者,如果你的系统使用的是/boot/firmware/config.txt,则编辑该文件:
sudo nano /boot/firmware/config.txt
在文件末尾添加以下内容:
dtoverlay=mt350x
保存并退出。
3.重启树莓派
sudo reboot
确认设备树覆盖是否持久化
4.重启后,运行以下命令来确认设备树覆盖是否仍然加载:
sudo dtoverlay -l | grep mt350x
如果输出中包含mt350x,则说明设备树覆盖已经正确持久化。

2万+

被折叠的 条评论
为什么被折叠?



