ublox-M8Q GNSS模组驱动与冷热启动定位设置
·
测试冷热启动定位
对于GNSS模组,产品测试中需要测试冷启动定位和热启动定位。
测试工程师问我怎么设置冷热启动,一时还真不知道。
GNSS模组驱动
推测复位就能实现冷启动
查看原理,看到模组有复位引脚,复位引脚是GPIO255。
尝试操作gpio255复位GNSS模组。
查看gpio255的状态:
[rsu7012: ~]$ cat /sys/kernel/debug/gpio
GPIOs 0-255, gpio:
gpio-0 (sd card detect ) in lo
gpio-45 (comip-otg ) in lo
gpio-72 (ver3 ) in lo
gpio-73 (ver2 ) in lo
gpio-74 (led upd ) out lo
gpio-75 (ver1 ) in hi
gpio-99 ( LC1160 irq ) in lo
gpio-153 (system run ) out lo
gpio-154 (led err ) out hi
gpio-185 (wifi_reset ) out hi
gpio-255 (GPS reset GPIO ) out hi
gpio255引脚已经被导出,直接操作gpio,发现/sys/class/gpio/下没有gpio255目录,说gpio255已经被某个驱动占用。
通过gpio-255 (GPS reset GPIO ) out hi可以知道gpio255的名字是GPS reset GPIO。
在内核中搜索GPS reset GPIO,最后找到相应的驱动kernel/linux-3.10.79/drivers/comip/wireless/ublox-gps.c
static int __init gps_gpio_probe(struct platform_device *pdev)
{
int retval = 0;
struct proc_dir_entry *ent;
#ifndef CONFIG_GPS_UBLOX_NODTS
struct ublox_gps_platform_data *pdata = NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"allocate memory for platform data failed\n");
return -ENOMEM;
}
g_gps_data = pdata;
printk("%s, %s\n", __func__, pdev->dev.kobj.name);
comip_mfp_config(MFP_PIN_GPIO(255), MFP_PIN_MODE_GPIO);
/*pdata->gpio_d1v8_ctrl = of_get_named_gpio(pdev->dev.of_node, "gps_d1v8_ctrl", 0);
if (pdata->gpio_d1v8_ctrl < 0) {
dev_err(&pdev->dev, "get gps_d1v8_ctrl failed\n");
return -EINVAL;
}
gpio_request(pdata->gpio_d1v8_ctrl, "GPS d1v8 ctrl GPIO");
gpio_direction_output(pdata->gpio_d1v8_ctrl, GPS_D1V8_OFF);*/
pdata->gpio_reset = of_get_named_gpio(pdev->dev.of_node, "gps_rst", 0);
if (pdata->gpio_reset < 0) {
dev_err(&pdev->dev, "get gps_rst failed\n");
return -EINVAL;
}
gpio_request(pdata->gpio_reset, "GPS reset GPIO");
gpio_direction_output(pdata->gpio_reset, GPS_RESET_OFF);
comip_mfp_config(MFP_PIN_GPIO(34), MFP_PIN_MODE_GPIO);
pdata->gpio_pps = of_get_named_gpio(pdev->dev.of_node, "gps_pps", 0);
if (pdata->gpio_pps < 0) {
dev_err(&pdev->dev, "get gps_pps failed\n");
return -EINVAL;
}
gpio_request(pdata->gpio_pps, "GPS pps GPIO");
gpio_direction_input(pdata->gpio_pps);
comip_mfp_config_pull(pdata->gpio_pps, MFP_PULL_DISABLE);
gpio_free(pdata->gpio_pps);
#else
struct ublox_gps_platform_data *pdata = pdev->dev.platform_data;
printk("ublox gps_gpio_probe\n");
gpio_request(pdata->gpio_reset, "GPS Reset GPIO");
gpio_direction_output(pdata->gpio_reset, GPS_RESET_OFF);
#endif
gps_gpio_dir = proc_mkdir("ublox-gps", NULL);
if (gps_gpio_dir == NULL) {
printk("Unable to create /proc/ublox-gps directory");
return -ENOMEM;
}
/* Creating read/write "powerctrl" entry */
ent = proc_create_data("powerctrl", 0, gps_gpio_dir, &file_ops_proc_powerctrl, pdata);
if (ent == NULL) {
printk("Unable to create /proc/ublox-gps/powerctrl entry");
remove_proc_entry("powerctrl", gps_gpio_dir);
retval = -ENOMEM;
goto fail;
}
/* Creating write "reset" entry */
ent = proc_create_data("reset", 0, gps_gpio_dir, &file_ops_proc_reset, pdata);
if (ent == NULL) {
printk("Unable to create /proc/ublox-gps/reset entry");
remove_proc_entry("reset", gps_gpio_dir);
retval = -ENOMEM;
goto fail;
}
/* Creating write "ppsacc" entry */
ent = proc_create_data("ppsacc", 0, gps_gpio_dir, &file_ops_proc_ppsacc, pdata);
if (ent == NULL) {
printk("Unable to create /proc/ublox-gps/reset entry");
remove_proc_entry("ppsacc", gps_gpio_dir);
retval = -ENOMEM;
goto fail;
}
comip_devinfo_register(gps_info_attributes, ARRAY_SIZE(gps_info_attributes));
#ifndef CONFIG_GPS_UBLOX_NODTS
pdata->power = comip_gps_power_ctrl;
#endif
GPS_DBG("%s END\n", __func__);
return retval;
fail:
remove_proc_entry("ublox-gps", 0);
return retval;
}
static int __exit gps_gpio_remove(struct platform_device *pdev)
{
struct ublox_gps_platform_data *pdata = pdev->dev.platform_data;
remove_proc_entry("powerctrl", gps_gpio_dir);
remove_proc_entry("reset", gps_gpio_dir);
remove_proc_entry("gps", 0);
gpio_direction_output(pdata->gpio_reset, GPS_RESET_OFF);
gpio_free(pdata->gpio_reset);
#ifndef CONFIG_GPS_UBLOX_NODTS
gpio_direction_output(pdata->gpio_d1v8_ctrl, GPS_D1V8_OFF);
gpio_free(pdata->gpio_d1v8_ctrl);
#endif
return 0;
}
#ifndef CONFIG_GPS_UBLOX_NODTS
static struct of_device_id of_ublox_gps_match[] = {
{ .compatible = "morningcore,ublox-gps", },
{}
};
#endif
static struct platform_driver gps_gpio_driver = {
.remove = __exit_p(gps_gpio_remove),
.driver = {
.name = "ublox-gps",
.owner = THIS_MODULE,
#ifndef CONFIG_GPS_UBLOX_NODTS
.of_match_table = of_ublox_gps_match,
#endif
},
};
/**
* Initializes the module.
* @return On success, 0. On error, -1, and <code>errno</code> is set
* appropriately.
*/
static int __init gps_gpio_init(void)
{
return platform_driver_probe(&gps_gpio_driver, gps_gpio_probe);
}
/**
* Cleans up the module.
*/
static void __exit gps_gpio_exit(void)
{
platform_driver_unregister(&gps_gpio_driver);
}
late_initcall(gps_gpio_init);
module_exit(gps_gpio_exit);
MODULE_DESCRIPTION("GPS gpio Driver ver %s " VERSION);
分析驱动代码可以发现,驱动在proc文件系统创建路径ublox-gps
gps_gpio_dir = proc_mkdir("ublox-gps", NULL);
然后创建了几个proc文件系统属性
ent = proc_create_data("powerctrl", 0, gps_gpio_dir, &file_ops_proc_powerctrl, pdata);
ent = proc_create_data("reset", 0, gps_gpio_dir, &file_ops_proc_reset, pdata);
ent = proc_create_data("ppsacc", 0, gps_gpio_dir, &file_ops_proc_ppsacc, pdata);
从上述驱动分析中就可以知道操作GNSS模组的方法了。
GNSS冷启动测试
看原理图可以知道给复位引脚写0实现复位。
echo 0 > /proc/ublox-gps/reset
经过测试,复位后的GNSS模组会清除星历,实现控制冷启动。
GNSS热启动测试
/**
* <code>gps power control </code> via the proc interface.
* @param file the ublox gps data included.
* @param buffer The buffer to read from.
* @param count The number of bytes to be read.
* @param data power on/off cmd.
* @return On success, the number of bytes written. On error, -1, and
* <code>errno</code> is set appropriately.
*/
static int gps_write_proc_powerctrl(struct file *file, const char *buffer,
size_t count, loff_t *data)
{
char *buf;
struct ublox_gps_platform_data *pdata = PDE_DATA(file_inode(file));
if (count < 1)
return -EINVAL;
if(!pdata->power)
return EPERM;
buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, buffer, count)) {
kfree(buf);
return -EFAULT;
}
GPS_DBG("%s, buf[0] %c\n", __func__, buf[0]);
if (buf[0] == '0') {
if(pdata->power_state){
pdata->power(0);
pdata->power_state = 0;
}
} else if (buf[0] == '1') {
if(!pdata->power_state){
pdata->power(1);
pdata->power_state = 1;
}
} else {
kfree(buf);
return -EINVAL;
}
kfree(buf);
return count;
}
看驱动代码可以知道,往powerctrl属性写入’1’或’0’就可以控制模组上下电。
经过测试,这样就实现可以控制的GNSS热启动测试。
更多推荐
所有评论(0)