来源:转载自https://community.milkv.io/t/i2c-milk-v-duo-bh1750/627,原作者 LangZhao
前言
本章介绍在milkv-duo开发板上添加光感bh1750,并实现应用层测试。
一、电路图查看
1.1 duo开发板i2c引脚
GitHub - milkv-duo/duo-files 2
这些都是可以作为i2c使用的引脚
注意:电路图中的gpio0、1对应的是芯片上的gpio28、29,到dtsi中查看也是28、29。
电路图中检索gpio0、1即可找到对应的电路
如图,小板的gpio0、1的默认功能是IIC_SCL、IIC_SDA
而最左边框出来的是这个引脚可以复用的功能,具体需要到dtsi中打开对应的节点。
1.2 光感bh1750引脚
我买的是合宙的bh1750,已经下架了,可以找市面上已有的。
从左到右分别是addr | sda | scl | gnd | vcc
光感和duo板连接线路
bh1750 | duo
vcc | 3.3v(out)
gnd | gnd
scl | gpio0(gpio28)
sda | gpio1(gpio29)
addr | gnd
二、dtsi添加
dts基础:Linux DTS(Device Tree Source)-CSDN博客
dts文件路径:build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts
将如下内容添加到dts中
&i2c0 {
status = "okay";
clock-frequency = <100000>;
bh1750:bh1750@23 {
compatible = "rohm,bh1750";
reg = <0x23>;
status = "okay";
};
};
其中23为bh1750的addr接地的i2c地址,具体可以看驱动以及传感器的文档。
Dtsi中增加后,编译img并刷机,查看devicetree下是否增加
cd /sys/firmware/devicetree/base/i2c@04000000/bh1750@23
cat name
image865×54 31.1 KB
duo-buildroot-sdk\build\boards\default\dts\cv180x\cv180x_base.dtsi
i2c0: i2c@04000000 {
compatible = "snps,designware-i2c";
clocks = <&clk CV180X_CLK_I2C>;
reg = <0x0 0x04000000 0x0 0x1000>;
clock-frequency = <400000>;
#size-cells = <0x0>;
#address-cells = <0x1>;
resets = <&rst RST_I2C0>;
reset-names = "i2c0";
};
这里的4000000就是i2c0控制器的地址,对应的device tree路径/sys/firmware/devicetree/base/i2c@04000000
三、bh1750驱动
注意需要和dtsi中匹配
ko基础:如何编译linux驱动ko_linux编译模块驱动ko_liyinuo2017的博客-CSDN博客
添加驱动两种方法,我才用的是第二种。
3.1 编写驱动最终生成ko文件
参考:基于RK3399Pro的BH1750驱动开发_bh1750程序流程图_冷静的领头狼的博客-CSDN博客 1
优点:可以手动添加及卸载
缺点:需要自己实现驱动,可以参考git和csdn上检索“sensor名称+linux“检索的相关code
3.2 打开config,将现有的驱动编译进img(config=y)
优点:不用自己实现驱动
缺点:适用于sdk已经有了驱动,不可动态卸载
bh1750驱动路径:
milkv-duo/duo-buildroot-sdk/blob/develop/linux_5.10/drivers/iio/light/bh1750.c
// SPDX-License-Identifier: GPL-2.0
/*
* ROHM BH1710/BH1715/BH1721/BH1750/BH1751 ambient light sensor driver
*
* Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
*
* Data sheets:
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1710fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1715fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1751fvi-e.pdf
*
* 7-bit I2C slave addresses:
* 0x23 (ADDR pin low)
* 0x5C (ADDR pin high)
*
*/
#include <linux/delay.h>
具体内容分析放到应用层介绍
查看驱动的Config配置流程
duo-buildroot-sdk\linux_5.10\drivers\Makefile
obj-$(CONFIG_IIO) += iio/
duo-buildroot-sdk\linux_5.10\drivers\iio\Makefile
obj-y += light/
duo-buildroot-sdk\linux_5.10\drivers\iio\light\Makefile
obj-$(CONFIG_BH1750) += bh1750.o
配置config文件
路径:
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\cvitek_cv1800b_milkv_duo_sd_defconfig
添加内容如下
CONFIG_IIO=y
CONFIG_BH1750=y
查看编译log
CC drivers/iio/light/bh1750.o
表示已经bh1750的驱动编译完成。
完成后刷到tf卡后开机。
检索bh1750,发现有驱动以及设备树信息
3.3 i2c0报错
查看i2c是否加载上
i2cdetect -y -r 0
发现没有i2c地址显示
报错
[ 1.943778] i2c_designware 4000000.i2c: controller timed out
[ 1.949738] bh1750: probe of 0-0023 failed with error -110
提示i2c0 控制器time out。
3.4 解决
方法1:通过uboot中的驱动更改默认的pin配置
查看io默认状态
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\u-boot\cvi_board_init.c
原先配置
PINMUX_CONFIG(IIC0_SDA, XGPIOA_29);
PINMUX_CONFIG(IIC0_SCL, XGPIOA_28);
默认配置会导致i2c0无法加载成功,报错提示i2c超时。
更改为如下内容,注意放在最后。
PINMUX_CONFIG(IIC0_SDA, IIC0_SDA);
PINMUX_CONFIG(IIC0_SCL, IIC0_SCL);
更改原因:参考电路图中,引脚名称为IIC0_SDA,可以复用为左侧的这些引脚。
例如复用为uart2就设置
PINMUX_CONFIG(IIC0_SDA, UART2_RX);
PINMUX_CONFIG(IIC0_SCL, UART2_TX);
方法2:使用官方技术支持提供的工具
Milk-V Duo 引脚复用配置工具 cvi_pinmux Duo
下载文末工具包:cvi_pinmux.tar.gz 通过scp或其他方式传到Duo上 scp cvi_pinmux.tar.gz root@192.168.42.1:/root/ 在Duo终端中解压安装(会安装到/usr/bin目录下) : tar zxf cvi_pinmux.tar.gz -C / 查看当前所有IO信息 cvi_pinmux -l 该工具查询或设置某个引脚,首先要知道这个引脚的名字,名字可以在原理图中找到 比如Duo的第6、7引脚,想配置为I2C接口 [duo_pinout_i2c1] 先查一下第6脚当前的状态,在原理图中找到引脚连接到CPU端的位置,靠近引脚的标注名就是我们需要的引脚的名字,这里是SD1_D2 [duo_pinout_6] 查询这个引脚当前的配置: cvi_pinmux -r SD1_D2 [duo_pinout_i2c1_02] 可以看到当前复用为GPIO_19, 我们这里需要设置为IIC1_SCL cvi_pinmux -w SD1_D2/IIC1_SCL 再用cvi_pinmux -r SD1_D2查看的…
四、驱动分析
基础知识点
iio介绍:一文带你深入了解Linux IIO 子系统_iio框架_Linux加油站的博客-CSDN博客 1
bh1750驱动:基于RK3399Pro的BH1750驱动开发_bh1750程序流程图_冷静的领头狼的博客-CSDN博客 1
misc介绍:创建misc设备,同时创建对应的设备属性文件_dts定义misc设备_驱动小马达的博客-CSDN博客 1
iio驱动:iio驱动_lkdcom的博客-CSDN博客
bh驱动路径:
duo-buildroot-sdk\linux_5.10\drivers\iio\light\bh1750.c
probe函数中定义了iio device的mode为DIRECT,表示生成sysfs,我们可以通过sysfs接口获取bh1750数据
iio通道
其中raw是我们需要的光感数据
参考资料:
iio生成sysfs接口:
iio驱动与sysfs子系统的调用关系_sysfs_attr_init_弋阳yoga的博客-CSDN博客 1
前几天在看bmp280的驱动,也就接触到了iio驱动,但是网上的很多文章都对iio驱动如何创建sysfs分析的很少,正好当时调驱动时输出的值有点问题,于是就想分析分析创建过程与调用的函数。内核版本:5.4.24-dirty平台:imx8qxp使用的器件为bmp280 源码位于/drivers/iio/pressure/bmp280-i2c.c整个匹配过程从probe开始static int bmp280_i2c_probe(struct…_sysfs_attr_init
应用程序调用iio的sysfs接口:
嵌入式Linux设备驱动程序开发指南17(IIO子系统一)——读书笔记_Jack.Jia的博客-CSDN博客 2
IIO子系统一
文件接口:
STM32MP157驱动开发——Linux IIO驱动(上)_Amonter的博客-CSDN博客
Linux的IIO子系统,通常适用于ADC和DAC传感器的驱动开发。
测试驱动添加的sysfs接口
cat /sys/devices/platform/4000000.i2c/i2c-0/0-0023/iio:device0\in_illuminance_raw
测试结果:
遮挡raw为2
未遮挡raw为182
五、应用层
5.1 代码
代码
test_bh1750.c
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include <poll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
//https://blog.csdn.net/weixin_45682654/article/details/128571696
static int file_data_read(char *filename, char *str)
{
int ret = 0;
FILE *data_stream;
data_stream = fopen(filename, "r"); /* 只读打开 */
if(data_stream == NULL) {
printf("can't open file %s\r\n", filename);
return -1;
}
ret = fscanf(data_stream, "%s", str);
if(!ret) {
printf("file read error!\r\n");
} else if(ret == EOF) {
/* 读到文件末尾的话将文件指针重新调整到文件头 */
fseek(data_stream, 0, SEEK_SET);
}
fclose(data_stream); /* 关闭文件 */
return 0;
}
int main(int argc, char *argv[])
{
int fd;
int light_value;
int test_time = 50;
char str[50];
int ret = 0;
// char* filename = "/dev/iio:device0";
// iio生成的sysfs接口
char* filename = "/sys/devices/platform/4000000.i2c/i2c-0/0-0023/iio:device0/in_illuminance_raw";
while(test_time){
memset(str,0,50);
file_data_read(filename, str);
light_value = atof(str);
printf("test_time %d :%d\r\n",50-test_time,light_value);
sleep(1);
test_time--;
}
return 0;
}
5.2 编译
先编译完整的img,因为改动过dts。
用balenaEtcher刷入tf卡后插到板子上,上电。
编译应用代码,生成可执行文件
编译及传输
riscv64-unknown-linux-musl-gcc -static -o test_bh1750 test_bh1750.c
scp test_bh1750 root@192.168.42.1:~/
输入密码:milkv
5.3 运行执行文件
登录设备
ssh root@192.168.42.1
执行文件
./test_bh1750
测试结果
六、小结
本章从电路图开始,介绍了引脚信息、dts配置、驱动添加流程、驱动简单分析、sysfs接口测试以及实现了光感的测试文件。
试用过程中遇到的问题主要是i2c0无法使用,后来发现是需要配置引脚的默认功能。
开发应用层的时候虽然可以通过cat命令读取到sysfs接口,但是代码实现还是需要参考一些教程,通过fopen等接口实现。
后续可以以此为例增加其他的传感器。