泰斗模块GPS双模默认是串口输出nema 数据,根据数据手册说明泰斗模块也支持i2c 输出nema 数据。我们板子主控自带的串口太少,所以用i2c 接口方式连接。用串口方式用泰斗提供的hal 层代码,打开硬件对应的串口就可以了。 用i2c接口就需要写个驱动提供一个字符设备让HAL层仍然用读文件方式打开文件。
hal 层修改
打开串口改成打开我们注册的字符设备,去掉串口控制等代码。
kernel
1. i2c 设备驱动
static struct of_device_id td_i2c_dt_ids[] = {
{ .compatible = "td,gps_i2c" },
{ }
};
static const struct i2c_device_id td_i2c_id[] = {
{ "tdgps_i2c", 0 },{ }
};
MODULE_DEVICE_TABLE(i2c, td_i2c_id);
static struct i2c_driver td_i2c_driver = {
.probe = td_i2c_probe,
.remove = td_i2c_remove,
.id_table = td_i2c_id,
.driver = {
.name = "tdgps_i2c",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(td_i2c_dt_ids),
},
};
static int __init chardev_init(void)
{
int ret;
ret = i2c_add_driver(&td_i2c_driver);
if (ret)
{
printk("Register tdgps_i2c driver failed.\n");
return ret;
}
exit:
return ret;
}
2. probe 函数里面注册字符设备
char startrmc[13] = {0x00,0x23,0x3E,0x03,0x51,0x04,0x00,0x03,0x04,0x01,0x01,0x61,0x82};
char startgga[13] = {0x00,0x23,0x3E,0x03,0x51,0x04,0x00,0x04,0x04,0x01,0x01,0x62,0x86};
char startgsa[13] = {0x00,0x23,0x3E,0x03,0x51,0x04,0x00,0x05,0x04,0x01,0x01,0x63,0x8A};
char startgsv[13] = {0x00,0x23,0x3E,0x03,0x51,0x04,0x00,0x06,0x04,0x01,0x01,0x64,0x8E};
static int td_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret;
this_client = client;
// 更改nema 从i2c 接口输出
td_i2c_write(client,startrmc,13);
td_i2c_write(client,startgga,13);
td_i2c_write(client,startgsa,13);
td_i2c_write(client,startgsv,13);
//td_i2c_read(this_client,tdgps_data->buffer,1024);
tdgps_data = kzalloc(sizeof(struct td_gps_dev), GFP_KERNEL);
if (tdgps_data == NULL) {
printk(KERN_ALERT "%s: kzalloc failed.\n", __func__);
ret = -ENOMEM;
goto exit;
}
//init_MUTEX(&tdgps_data->sem);
sema_init(&tdgps_data->sem, 1);
INIT_LIST_HEAD(&nema_buff_list_head);
ret = misc_register(&char_miscdev);
if (ret != 0) {
printk( "cannot register miscdev on minor=%d (err=%d)\n",CHAR_MINOR, ret);
goto exit;
}
printk("--------- chardev init success ---------\n\n\n");
INIT_WORK(&add_nema_work, add_nema_work_func);
setup_timer(&mytimer, myfunc, (unsigned long)"hermantest");
mytimer.expires = jiffies + HZ;
add_timer(&mytimer);
printk("--------- timer---------\n\n\n");
return 0;
exit:
kfree(tdgps_data);
}
3. 用定时器定时从i2c 读数据到buff ,把buff 里面数据按着32字节大小写入一个双向链表,字符驱动读函数从双向链表中读数据。