资讯详情

RK3566调试VL53L01

一、添加、编译驱动

1、从ST官方下载en.STSW-IMG目前最新的005软件包是1.0.软件包里有4个版本LinuxDriverMassMarket_1.0.继续打开7个文件夹LinuxDriverMassMarket_1.0.7\kernel\drivers\input\misc目录,将目录下的vl53L0X复制文件夹和内容SDK的\kernel\drivers\input\misc修改目录misc目录下的Makefile及Kconfig添加VL53L01。

Makefile末尾添加:

obj-$(CONFIG_STMVL53L0X)   = vl53L0X/

Kconfig末尾添加:

config STMVL53L0X     tristate "ST VL53L0x haptics support"  depends on INPUT && I2C  select INPUT_FF_MEMLESS  select REGMAP_I2C  help    Say Y to enable support for the ST VL53L0x haptics driver.     To compile this driver as a module, choose M here: the    module will be called vl53l0x-haptics.

添加再endif之前。

2、修改vl53L0X目录下的Makefile,改为以下内容:

# # Makefile for the vl53L0X drivers. #  # Each configuration option enables a list of files. FEATURE_USE_CCI := false #FEATURE_USE_CCI := true  ifeq ($(FEATURE_USE_CCI), true) ccflags-y  = -Idrivers/input/misc/vl53L0X/inc -DCAMERA_CCI else ccflags-y  = -Idrivers/input/misc/vl53L0X/inc -DSTM_TEST ccflags-y  = -Idrivers/input/misc/vl53L0X endif  ccflags-y  = -Idrivers/media/platform/msm/camera_v2/sensor/io ccflags-y  = -Idrivers/media/platform/msm/camera_v2 ccflags-y  = -Idrivers/media/platform/msm/camera_v2/common ccflags-y  = -Idrivers/media/platform/msm/camera_v2/sensor/cci  SRCS := $(wildcard ./src/*.c) OBJS = $(SRCS:.c=.o)  obj-$(CONFIG_STMVL53L0X)    = stmvl53l0x.o stmvl53l0x-objs    := stmvl53l0x_module.o stmvl53l0x_module-i2c.o stmvl53l0x_module-cci.o src/vl53l0x_api_calibration.o src/vl53l0x_api_core.o src/vl53l0x_api_ranging.o src/vl53l0x_api_strings.o src/vl53l0x_api.o src/vl53l0x_platform.o src/vl53l0x_i2c_platform.o src/vl53l0x_port_i2c.o 

不修改编译会报错。

3、DTS在文件中添加设备节点,需要根据电路图确定VL53L01传感器挂在那里i2c比如总线I2C需要在总线上I2C2节点以下增加vl53l01的节点:

 vl53l0x: vl53l0x@29 {   compatible = "st,stmvl53l0";   reg = <0x29>;      status = "okay";  };

4、进入SDK的kernel执行在目录下make menuconfig ARCH=arm64修改内核配置文件,添加 ST VL53L0x xxx

然后选择save,然后Exit,然后执行cp .config arch/arm64/configs/rockchip_linux_defconfig保存配置文件,重新编译内核,编译完成后烧写入主板。

5、接上传感器并将主板的日志打印串口连接到电脑的终端软件,然后启动主板,系统启动完成之后在终端输入dmesg | grep vl,查看vl53l01加载日志:

[root@RK356X:/]# dmesg | grep stmvl [    0.896764] stmvl53l0x_init: Enter [    0.896781] stmvl53l0x_init_i2c: Enter [    0.896824] stmvl53l0x_init_i2c: End with rc:-22 [    0.896839] stmvl53l0x_init: 1986 failed with -22 [    0.896849] stmvl53l0x_init: End [    1.021873] stmvl53l0x_probe: Enter [    1.021899] stmvl53l0x_parse_vdd: Enter [    1.021919] stmvl53l0 2-0029: Looking up vdd-supply from device tree [    1.021926] stmvl53l0 2-0029: Looking up vdd-supply property in node /i2c@fe5b0000/vl53l0x@29 failed [    1.021953] stmvl53l0 2-0029: 2-0029 supply vdd not found, using dummy regulator [    1.022028] stmvl53l0 2-0029: Linked as a consumer to regulator.0 [    1.022043] stmvl53l0x_parse_vdd: End [    1.022056] stmvl53l0x_setup: Enter [    1.022220] stmvl53l0x_poll_thread(758) : Starting Polling thread [    1.022524] stmvl53l0x_setup: Misc device registration name:2-0029 [    1.022660] stmvl53l0x_setup: support ver. 1.0.5 enabled [    1.022676] stmvl53l0x_setup: End [    1.022678] stmvl53l0x_probe: End

实际测试后,无论传感器是否与主板连接,都是这些日志,因此无法通过启动日志来判断传感器是否正常连接。

6、可通过i2c tool检查传感器是否连接,命令终端输入i2cdetect -y 2即可查看i2c如果传感器连接正常,2总线上挂载的设备可以看到0x地址设备。

7、测试传感器读取距离值

使用SDK编译工具LinuxDriverMassMarket_1.0.7\kernel目录下的vl53l0x_test应用程序,编译成功后,将执行文件推到主板,然后运行。在正常情况下,可以看到日志打印的距离值。由于没有传感器校准,读取的距离值与实际距离值有偏差。

运行vl53l01x_test的日志

[root@RK356X:/userdata/bin]# ./vl53l0x_test  [  175.411550] VL53L0X_GetDeviceInfo: [  175.420316] Device Name : VL53L0X ES1 or later [  175.420355] Device Type : VL53L0X [  175.420363] Device ID : VL53L0C [  175.420370] Product type: 238 [  175.420378] ProductRevisionMajor : 1 [  175.420385] ProductRevisionMinor : 1 [  175.420391] Call of VL53L0X_StaticInit [  175.497162] Call of VL53L0X_SetDeviceMode [  175.501836] DeviceMode:0x1, interMeasurems:30== [  175.503118] Configure Long Ranging [  175.503555] Set Timing Budget = 26000 Range:  45, Error:0, SigRate_mcps:1744896, AmbRate_mcps:   1536

8.中断或查询模式

stmvl53l0x_module.cwe文件中有#define USE_INT宏定义用于定义使用中断模式或查询模式读取寄存器状态USE_INT注释使用中断模式,需要连接传感器的中断模式INT管脚到处理器GPIO上。

二、修改驱动

1.需要修改宏定义打开或关闭日志打印stmvl53l0x.h文件:

#define DEBUG #define vl53l0x_dbgmsg(str, args...) \  p_err("%s: " str, __func__, ##args)
#define vl53l0x_errmsg(str, args...) \
	pr_err("%s: " str, __func__, ##args)

改为:

#define DEBUG

#ifdef DEBUG
#define vl53l0x_dbgmsg(str, args...)	\
	pr_err("%s: " str, __func__, ##args)
#define vl53l0x_errmsg(str, args...) \
	pr_err("%s: " str, __func__, ##args)
#else
#define vl53l0x_dbgmsg(str, args...)	\
	(void)0
#define vl53l0x_errmsg(str, args...) \
	(void)0
#endif

如果想关闭日志打印,则注释#define DEBUG即可。

2、在stmvl53l0x_module-i2c.c文件的stmvl53l0x_probe()加入检测传感器是否连接的代码,通过读取传感器的ID号以判断传感器是否连接,在stmvl53l0x_parse_vdd(&i2c_object->client->dev, i2c_object);之后加入如下代码:

	/* read VL53L0X ID */
	
	Status = VL53L0X_RdByte(vl53l0x_data, VL53L0X_REG_IDENTIFICATION_MODEL_ID,
	&module_id);

	if( Status )
	{
		vl53l0x_dbgmsg("get module_id err:%d\n", Status );
	}
	else
	{
		vl53l0x_dbgmsg("module_id:%02X\n", module_id );
	}

3、中断模式的IRQ_NUM从DTS文件中解析

驱动默认注释了USE_INT (/* #define USE_INT */),即不使用中断模式,并且中断的GPIO号实在驱动中定义的,这样方便管脚的更换,可修改为从DTS文件中解析。

stmvl53l0x.h文件的struct stmvl53l0x_data{ }结构中增加irq_gpiounsigned和irq_gpio_flags两个变量:

struct stmvl53l0x_data {

	/* !<embed ST VL53L0 Dev data as "dev_data" */
	VL53L0X_DevData_t Data;
	/*!< i2c device address user specific field*/
	uint8_t   I2cDevAddr;
	/*!< Type of comms : VL53L0_COMMS_I2C or VL53L0_COMMS_SPI */
	uint8_t   comms_type;
	/*!< Comms speed [kHz] : typically 400kHz for I2C */
	uint16_t  comms_speed_khz;
	/* CCI_BUS; I2C_BUS */
	uint8_t   bus_type;

	void *client_object; /* cci or i2c client */

	struct mutex update_lock;
	struct delayed_work	dwork;		/* for PS  work handler */
	struct input_dev *input_dev_ps;
	struct kobject *range_kobj;

	const char *dev_name;
	/* function pointer */

	/* misc device */
	struct miscdevice miscdev;

	int irq_gpio;
	unsigned int irq_gpio_flags;

	int irq;
	unsigned int reset;

	/* control flag from HAL */
	unsigned int enable_ps_sensor;

	/* PS parameters */
	unsigned int ps_data;			/* to store PS data */

	/* Calibration parameters */
	unsigned int offsetCalDistance;
	unsigned int xtalkCalDistance;


	/* Range Data */
	VL53L0X_RangingMeasurementData_t rangeData;

	/* Device parameters */
	VL53L0X_DeviceModes	deviceMode;
	uint32_t		interMeasurems;
	VL53L0X_GpioFunctionality gpio_function;
	VL53L0X_InterruptPolarity gpio_polarity;
	FixPoint1616_t low_threshold;
	FixPoint1616_t high_threshold;

	/* delay time in miniseconds*/
	uint8_t delay_ms;

	/* Timing Budget */
	uint32_t	timingBudget;
	/* Use this threshold to force restart ranging */
	uint32_t       noInterruptCount;
	/* Use this flag to use long ranging*/
	int			  useLongRange;

	/* Polling thread */
	struct task_struct *poll_thread;
	/* Wait Queue on which the poll thread blocks */
	wait_queue_head_t poll_thread_wq;

	/* Recent interrupt status */
	uint32_t		interruptStatus;

	struct mutex work_mutex;

	/* Debug */
	unsigned int enableDebug;
	uint8_t interrupt_received;
};

stmvl53l0x_module-i2c.c文件中增加#include <linux/of_device.h>

 stmvl53l0x_module-i2c.c文件中增加stmvl53l0x_parse_dt()函数:

static int stmvl53l0x_parse_dt(struct device *dev, struct stmvl53l0x_data *pdata)
{
	int ret = 0;
	struct device_node *np = dev->of_node;

	const  struct of_device_id *match;

	match=of_match_device(st_stmvl53l0x_dt_match,dev);
	if(!match){
		vl53l0x_errmsg("DTS Unable to find matchv device.");
		return -1; 
	}

	pdata->irq_gpio = of_get_named_gpio_flags(np, "st,irq-gpio", 0, &pdata->irq_gpio_flags);
	if (pdata->irq_gpio < 0){
		vl53l0x_errmsg("DTS Unable to get irq_gpio");
		ret = -1;
	}
	else
	{
		vl53l0x_dbgmsg("irq gpio:%d", pdata->irq_gpio);
	}

	return ret;
}

在stmvl53l0x_probe()函数中调用此函数:

static int stmvl53l0x_probe(struct i2c_client *client,
				   const struct i2c_device_id *id)
{
	int rc = 0;
	struct stmvl53l0x_data *vl53l0x_data = NULL;
	struct i2c_data *i2c_object = NULL;
	VL53L0X_Error Status = VL53L0X_ERROR_NONE;
	uint8_t module_id;

	vl53l0x_dbgmsg("Enter\n");

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
		rc = -EIO;
		return rc;
	}

	vl53l0x_data = kzalloc(sizeof(struct stmvl53l0x_data), GFP_KERNEL);
	if (!vl53l0x_data) {
		rc = -ENOMEM;
		return rc;
	}
	if (vl53l0x_data) {
		vl53l0x_data->client_object =
			kzalloc(sizeof(struct i2c_data), GFP_KERNEL);
		i2c_object = (struct i2c_data *)vl53l0x_data->client_object;
	}
	i2c_object->client = client;

	/* setup bus type */
	vl53l0x_data->bus_type = I2C_BUS;

	/* setup regulator */
	stmvl53l0x_parse_vdd(&i2c_object->client->dev, i2c_object);

	/* setup dt */
	stmvl53l0x_parse_dt(&i2c_object->client->dev, vl53l0x_data);

	/* read VL53L0X ID */
	
	Status = VL53L0X_RdByte(vl53l0x_data, VL53L0X_REG_IDENTIFICATION_MODEL_ID,
	&module_id);

	if( Status )
	{
		vl53l0x_dbgmsg("get module_id err:%d\n", Status );
	}
	else
	{
		vl53l0x_dbgmsg("module_id:%02X\n", module_id );
	}
		
	/* setup device name */
	vl53l0x_data->dev_name = dev_name(&client->dev);

	/* setup device data */
	dev_set_drvdata(&client->dev, vl53l0x_data);

	/* setup client data */
	i2c_set_clientdata(client, vl53l0x_data);

	
	/* setup other stuff */
	rc = stmvl53l0x_setup(vl53l0x_data);

	/* init default value */
	i2c_object->power_up = 0;

	vl53l0x_dbgmsg("End\n");
	return rc;
}

修改stmvl53l0x_module.c文件,

	gpio_request(IRQ_NUM, "vl53l0x_gpio_int");
	gpio_direction_input(IRQ_NUM);
	irq = gpio_to_irq(IRQ_NUM);

	if (irq < 0) {
		vl53l0x_errmsg("filed to map GPIO: %d to interrupt:%d\n",
			IRQ_NUM, irq);

改为

	gpio_request( data->irq_gpio, "vl53l0x_gpio_int");
	gpio_direction_input(data->irq_gpio);
	irq = gpio_to_irq(data->irq_gpio);

	if (irq < 0) {
		vl53l0x_errmsg("filed to map GPIO: %d to interrupt:%d\n",
			data->irq_gpio, irq);

标签: 传感器中spl

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台