Foreword
This chapter introduces adding the light sensor bh1750 to the milkv-duo development board and implementing application layer testing.
1. View circuit diagram
1.1 duo development board i2c pins
https://github.com/milkv-duo/duo-files
These are the pins that can be used as i2c
Note: gpio0 and 1 in the circuit diagram correspond to gpio28 and 29 on the chip, and they are also 28 and 29 when viewed in dtsi.
Search gpio0 and 1 in the circuit diagram to find the corresponding circuit.
As shown in the figure, the default functions of gpio0 and 1 of the small board are IIC_SCL and IIC_SDA.
What comes out of the leftmost border is the reusable function of this pin. Specifically, you need to open the corresponding node in dtsi.
1.2 Light sensor bh1750 pins
What I bought is Hezhou’s bh1750. It has been taken off the shelves. You can find something already on the market.
From left to right they are addr | sda | scl | gnd | vcc
Light sensor and duo board connection circuit
bh1750 | duo vcc | 3.3v(out) gnd | gnd scl | gpio0(gpio28) sda | gpio1(gpio29) addr | gnd
2. dtsi added
Dts basics: https://blog.csdn.net/qq_53144843/article/details/123829747
dts file path: build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts
Add the following content to dts
&i2c0 { status = "okay"; clock-frequency = <100000>; bh1750:bh1750@23 { compatible = "rohm,bh1750"; reg = #; status = "okay"; }; };
Among them, 23 is the i2c address of the addr grounding of bh1750. For details, please refer to the documentation of the driver and sensor.
After adding it to Dtsi, compile img and flash the machine to check whether it is added under devicetree.
# cd /sys/firmware/devicetree/base/i2c@04000000/bh1750@23 # cat name bh1750
duo-buildroot-sdk\build\boards\default\dts\cv180x\cv180x_base.dtsi
i2c0: i2c@04000000 { compatible = "snps,designware-i2c"; clocks = < & amp;clk CV180X_CLK_I2C>; reg = <0x0 0x04000000 0x0 0x1000>; clock-frequency = <400000>; #size-cells = <0x0>; #address-cells = <0x1>; resets = < & amp;rst RST_I2C0>; reset-names = "i2c0"; };
The 4000000 here is the address of the i2c0 controller, and the corresponding device tree path is /sys/firmware/devicetree/base/i2c@04000000
3. bh1750 driver
Note that it needs to match the dtsi
ko basics: https://blog.csdn.net/li_man_man_man/article/details/126534271
There are two ways to add a driver, and I used the second one.
3.1 Write the driver and finally generate the ko file
Reference: https://blog.csdn.net/ZOROE123/article/details/117442036
Advantages: Can be added and uninstalled manually
Disadvantages: You need to implement the driver yourself. You can refer to the relevant code retrieved by “sensor name + linux” on git and csdn.
3.2 Open config and compile the existing driver into img (config=y)
Advantages: No need to implement the driver yourself
Disadvantages: It is suitable for SDKs that already have drivers and cannot be dynamically uninstalled.
bh1750 driver path:
https://github.com/milkv-duo/duo-buildroot-sdk/blob/develop/linux_5.10/drivers/iio/light/bh1750.c
The specific content analysis is put into the application layer introduction.
View the driver’s Config configuration process
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
Configure config file
path:
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\cvitek_cv1800b_milkv_duo_sd_defconfig
Add the following content
CONFIG_IIO=y CONFIG_BH1750=y
Check the compilation log
CC drivers/iio/light/bh1750.o
Indicates that the driver compilation of bh1750 has been completed.
After completion, flash to the tf card and boot.
Search bh1750 and find driver and device tree information
3.3 i2c0 error
Check if i2c is loaded
i2cdetect -y -r 0
Found that no i2c address is displayed
Report an error
[ 1.943778] i2c_designware 4000000.i2c: controller timed out [ 1.949738] bh1750: probe of 0-0023 failed with error -110
Prompt i2c0 controller time out.
3.4 Solution
Method 1: Change the default pin configuration through the driver in uboot
View io default status
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\u-boot\cvi_board_init.c
Original configuration
PINMUX_CONFIG(IIC0_SDA, XGPIOA_29); PINMUX_CONFIG(IIC0_SCL, XGPIOA_28);
The default configuration will cause i2c0 to fail to load successfully and an error will be reported indicating that i2c has timed out.
Change to the following content, put it at the end.
PINMUX_CONFIG(IIC0_SDA, IIC0_SDA); PINMUX_CONFIG(IIC0_SCL, IIC0_SCL);
Reason for change: In the reference circuit diagram, the pin name is IIC0_SDA, which can be reused as these pins on the left.
For example, if reuse is uart2, set
PINMUX_CONFIG(IIC0_SDA, UART2_RX); PINMUX_CONFIG(IIC0_SCL, UART2_TX);
Method 2: Use tools provided by official technical support
https://community.milkv.io/t/milk-v-duo-cvi-pinmux/292
4. Driver analysis
Basic knowledge points
Introduction to iio: https://blog.csdn.net/m0_74282605/article/details/128098034
bh1750 driver: https://blog.csdn.net/ZOROE123/article/details/117442036
misc introduction: https://blog.csdn.net/rj_ys/article/details/112791330
iio driver: https://blog.csdn.net/weixin_68294039/article/details/124931816
bh driver path:
duo-buildroot-sdk\linux_5.10\drivers\iio\light\bh1750.c
The probe function defines the mode of the iio device as DIRECT, which means generating sysfs. We can obtain bh1750 data through the sysfs interface.
iio channel
where raw is the light sensing data we need
References:
iio generates sysfs interface:
https://blog.csdn.net/qq_17270067/article/details/109989738
The application calls the sysfs interface of iio:
https://blog.csdn.net/qq_27094347/article/details/125926093
File interface:
https://blog.csdn.net/weixin_45682654/article/details/128571696
Test the sysfs interface added by the driver
cat /sys/devices/platform/4000000.i2c/i2c-0/0-0023/iio:device0\in_illuminance_raw
Test Results:
Occlusion raw is 2
Unoccluded raw is 182
5. Application layer
5.1 Code
code
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"); /* open for reading only */ if(data_stream == NULL) { printf("can't open file %s\r\\ ", filename); return -1; } ret = fscanf(data_stream, "%s", str); if(!ret) { printf("file read error!\r\\ "); } else if(ret == EOF) { /* Read the end of the file and readjust the file pointer to the beginning of the file */ fseek(data_stream, 0, SEEK_SET); } fclose(data_stream); /* Close the file */ 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"; // sysfs interface generated by iio 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\\ ",50-test_time,light_value); sleep(1); test_time--; } return 0; }
5.2 Compilation
Compile the complete img first, because the dts has been changed.
Use balenaEtcher to flash the tf card, insert it into the board, and power on.
Compile application code and generate executable file
Compilation and transmission
riscv64-unknown-linux-musl-gcc -static -o test_bh1750 test_bh1750.c scp test_bh1750 [email protected]:~/
Enter password: milkv
5.3 Run executable file
Log into device
executable file
./test_bh1750
Test Results
6. Summary
This chapter starts with the circuit diagram and introduces the pin information, dts configuration, driver addition process, simple driver analysis, sysfs interface test, and test files that implement light sensing.
The main problem encountered during the trial process was that i2c0 could not be used. Later, it was discovered that the default function of the pin needs to be configured.
When developing the application layer, although the sysfs interface can be read through the cat command, the code implementation still needs to refer to some tutorials and implement it through interfaces such as fopen.
You can use this as an example to add other sensors later.