首页 > 技术知识 > 正文

硬件问题:

  将安卓设备的芯片直接替换成海思hi3516dv300,降低生产成本,直接改完后发现io口不够,所以新添加一个tca9539的gpio扩展芯片作gpio扩展。

TCA9539芯片

  芯片通过i2c控制通信,将一个i2c控制器扩展为16个gpio口,控制方法也比较简单,一共8个寄存器,寄存器0、1用来读取管脚状态,寄存器2,3控制输出管脚的高低,4,5是什么极性翻转,具体也不知道什么意思,驱动中并没有用到;最后6,7两组寄存器控制io口的方向,贴张图说明一下,文章末尾有手册的下载地址。 (开发记录)tca9539芯片驱动(一)   因为我们不同设备用的同一套应用代码,tca9539芯片只用在了一种设备上,所以在编写驱动程序的时候应该尽量不对应用代码做太大的改动,防止代码繁冗的像依托shift。   所以我将驱动程序写成了类似gpio文件操作一样的形式,通过export导出io口,然后通过操作目录下的direction和value文件对相应的io口进行操作,因为我们系统层控制gpio口也是通过操作文件的方式,所以使用这种方法后应用层代码只需要做一次判断将文件路径替换就可以操作tca9539的io口了。   内核版本使用的是4.9.37,在内核目录下的drivers/gpio/gpiolib-sysfs.c中介绍了内核是如何用过文件去操作gpio口的。   抛开代码中各种各样的结构体,可以看到在用户每次调用export函数的时候, 内核通过device_create_with_groups函数创建一个新的设备文件节点,而我所需要的就是这个。 初始化过程

ASSERT(!tca_i2c_init(), return FAILURE); ret = alloc_chrdev_region(&devno,minor,count, “xxx”); if(ret) { printk(“Failed to alloc_chrdev_region.\n”); return ret; } ptca = cdev_alloc(); if(ptca == NULL) { printk(“Failed to cdev_alloc.\n”); goto err1; } cdev_init(ptca, &fops); ret = cdev_add(ptca, devno, count); if(ret < 0) { printk(“Failed to cdev_add.”); goto err2; } ret = class_register(&tca_class); if (ret < 0) { return ret; }
<

export函数:

static ssize_t export_store(struct class *class, struct class_attribute *attr, const char *buf, size_t len) { struct device *dev; long gpio; int ret ; ret = kstrtol(buf, 0, &gpio); if (ret < 0) return -1; printk(“gpio = %ld \n”, gpio); printk(“export_store\n”); dev = device_create_with_groups(&tca_class, NULL, MKDEV(MAJOR(devno), MINOR(devno)+gpio), NULL, gpio_groups, “tgpio%ld”, gpio); return len; }

还有就是direction和value的操作函数了,这两个函数基本同内核中的函数一致就可以了。然后就可以通过操作文件来操作芯片扩展的io口了。 (开发记录)tca9539芯片驱动(一)1

tca9539数据手册地址: 链接:https://pan.baidu.com/s/18v1OiTwFjewRWUF8TazIzw 提取码:rifo

猜你喜欢