历史上的今天
今天是:2024年12月30日(星期一)
2021年12月30日 | 4412 i2c驱动
2021-12-30 来源:eefocus
1.Linux主机驱动和外设驱动分离思想
外设驱动→API→主机驱动→板机逻辑--具体的i2c设备(camera,ts,eeprom等等)
2.主机驱动
根据控制器硬件手册,操作具体的寄存器,产生波形。
Linux应用工程师:屏蔽了驱动和硬件
Linux驱动工程师:屏蔽硬件,提供标准的主机驱动。驱动工程师需要完成“外设驱动”
内核函数接口:(API)。主机驱动提供給外设驱动的函数接口
注册i2c设备:i2c_board_info
驱动注册和卸载函数以及结构体:i2c_del_driver/i2c_add_driver, i2c_driver
读写函数和结构体:i2c_transfer, i2c_msg
这些函数放之四海之内皆准
3.外设驱动
针对具体的外部器件的代码。
摄像头以及声卡中i2c用来配置外部设备(声卡和摄像头)→地址和配置的内容都不一样!
4.板级逻辑
描述主机和外部设备是怎么连接的
5.设备-i2c设备注册以及设备注册之后的查询方法
查询i2c设备地址:ls /sys/bus/i2c/devices/
怎么和原理图以及外部设备对应:3-0038→I2C_3_SCL(addr:datasheet中查0x38)
查询i2c设备名称:cat /sys/bus/i2c/devices/3-0038/name
menuconfig中去掉触摸的驱动
Device Drivers --->
Input device support --->
Touchscreens --->
FT5X0X based touchscreens(去掉)
添加i2c设备:i2c_devs3[]中添加
{
I2C_BOARD_INFO("i2c_test", 0x70>>1),
},
cat /sys/bus/i2c/devices/3-0038/name结果是i2c_test
6.驱动-i2c驱动注册和卸载
i2c设备初始化完成-进入probe函数
i2c_del_driver/i2c_add_driver, i2c_driver
module_init和late_initcall:前面的优先加载,后面的延迟加载
驱动代码:
i2c.c
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define I2C_TEST_NAME "i2c_test" static int i2c_test_probe(struct i2c_client *client, const struct i2c_device_id *id) { printk("==%s: n", __FUNCTION__); return 0; } static int __devexit i2c_test_remove(struct i2c_client *client) { i2c_set_clientdata(client, NULL); //设置client为NULL printk("==%s: n", __FUNCTION__); return 0; } static const struct i2c_device_id i2c_test_id[] = { { "i2c_test", 0 }, { } }; static struct i2c_driver i2c_test_driver = { .probe = i2c_test_probe, .remove = __devexit_p(i2c_test_remove), .id_table = i2c_test_id, .driver = { .name = I2C_TEST_NAME, .owner = THIS_MODULE, }, }; static void i2c_io_init() { int ret; ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN"); if(ret) { printk(KERN_ERR "failed to request TP1_EN for I2C controln"); } gpio_direction_output(EXYNOS4_GPL0(2), 1); s3c_gpio_cfgpin(EXYNOS4_GPL0(2), S3C_GPIO_OUTPUT); gpio_free(EXYNOS4_GPL0(2)); mdelay(5); ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3"); if(ret) { gpio_free(EXYNOS4_GPX0(3)); ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3"); if(ret) { printk("i2c_io_test: Fialed to request GPX0_3 n"); } } gpio_direction_output(EXYNOS4_GPX0(3), 0); mdelay(200); gpio_direction_output(EXYNOS4_GPX0(3), 1); s3c_gpio_cfgpin(EXYNOS4_GPX0(3), S3C_GPIO_OUTPUT); gpio_free(EXYNOS4_GPX0(3)); msleep(300); } static int __init i2c_test_init(void) { printk("==%s: n", __FUNCTION__); i2c_io_init(); printk("==%s: n", __FUNCTION__); return i2c_add_driver(&i2c_test_driver); } static void __exit i2c_test_exit(void) { printk("==%s: n", __FUNCTION__); i2c_del_driver(&i2c_test_driver); } late_initcall(i2c_test_init); module_exit(i2c_test_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("TSI2CTEST"); MODULE_AUTHOR("iTOP"); Makefile: TARGET_NAME = i2c #APP_NAME = app_pollkey obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3.0 PWD ?= $(shell pwd) all: make -C $(KDIR) M=$(PWD) modules #app:$(APP_NAME) # arm-none-linux-gnueabi-gcc $(APP_NAME).c -o $(APP_NAME) -static clean: rm -rf *.o *.ko *.mod.c *.symvers *.order .$(TARGET_NAME)* $(APP_NAME) 测试结果: [root@iTOP-4412]# insmod i2c.ko [ 381.451187] ==i2c_test_init: [ 382.020037] ==i2c_test_init: [ 382.021601] ==i2c_test_probe: [root@iTOP-4412]# rmmod i2c [ 385.294465] ==i2c_test_exit: [ 385.296008] ==i2c_test_remove: 7.驱动-i2c数据的传输(9.7寸或者7寸屏幕) i2c_transfer, i2c_msg struct i2c_msg { __u16 addr; /* slave address */ __u16 flags; #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_RD 0x0001 /* read data, from slave to master */ #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ }; int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); 参数1:probe传进的client里的adapter 代码: i2c_test_read_9x7_7.c #include #include #include #include #include #include #include #include #ifdef CONFIG_HAS_EARLYSUSPEND #include #endif #include #include #include #include static int i2c_tes_read_reg(struct i2c_client *client,u8 addr, u8 *pdata) { u8 buf1[4] = { 0 }; u8 buf2[4] = { 0 }; struct i2c_msg msgs[] = { { .addr = client->addr, //0x38 .flags = 0, //写 .len = 1, //要写的数据的长度 .buf = buf1, }, { .addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = buf2, }, }; int ret; buf1[0] = addr; ret = i2c_transfer(client->adapter, msgs, 2); if (ret < 0) { pr_err("read reg (0x%02x) error, %dn", addr, ret); } else { *pdata = buf2[0]; } return ret; } static int i2c_tes_read_fw_reg(struct i2c_client *client,unsigned char *val) { int ret; *val = 0xff; ret = i2c_tes_read_reg(client,0xa6, val); printk("ts reg 0xa6 val is %dn",*val); return ret; } static int i2c_test_probe(struct i2c_client *client, const struct i2c_device_id *id) { unsigned char val; printk("==%s:n", __FUNCTION__); i2c_tes_read_fw_reg(client,&val); return 0; } static int __devexit i2c_test_remove(struct i2c_client *client) { i2c_set_clientdata(client, NULL); printk("==%s:n", __FUNCTION__); return 0; } static const struct i2c_device_id i2c_test_id[] = { { "i2c_test", 0 }, { } }; static struct i2c_driver i2c_test_driver = { .probe = i2c_test_probe, .remove = __devexit_p(i2c_test_remove), .id_table = i2c_test_id, .driver = { .name = "i2c_test", .owner = THIS_MODULE,
上一篇:4412 SPI驱动
下一篇:4412 按键和中断
史海拾趣
|
俺想学习FPGA--有偿寻求合作开发FPGA学习板 看到现在FPGA现在这么火爆,忍不住想学习一下。 但是本人对FPGA了解甚少。想寻求高手共同合作搞一个FPGA开发板。 我负责:元件费用,打样费用。以及适当给与合作者一定酬劳(这个不多,呵呵,俺也是 ...… 查看全部问答> |
|
作者: Ian Poole Adrio Communications Ltd 第一部分解释了调幅(AM)和调频(FM)的基础,并阐述了优点和缺点。第二部分解析了频移键控(PSK)和正交幅度调制(QAM)。第三部分讨论扩频通信技术,包括被广泛应用的直接序列扩频通信(DSSS),和 ...… 查看全部问答> |
|
我的wince上咋就不能运行dotnet的程序呢,点击应用程序一点反应也没有,也不报错。另外,保证dotnet的支持包已经打入wince,1.1和2.0都打了。 把SYSGEN_DOTNET和SYSGEN_DOTNET_SUPPORT还有DOTNETV2的所有选项加上,则运行dotnet的程序既不报错 ...… 查看全部问答> |
|
我看很多资料都写得是AD7705的参考电平时2.5v,但是今天看到有人用ref195的输出做AD7705的参考电平,ref195接ref+输出5v,ref-接地请问这样合适吗。 还有AD7705的资料上写着采样范围是0-20mv或0-2.5v,一直不太明白这是什么意思,0-2.5v不是包括0- ...… 查看全部问答> |
|
An unspecified Debug Toolbox call failed 我在使用ADS1.2套件的AXD时,连接了Easyjtag,并进行了设置,但是却出现了如题的An unspecified Debug Toolbox call failed的错误,请高人指点,该如何解决这个问题?… 查看全部问答> |
|
keil编译ARM报--- Error: can't execute 'BIN30\ArmAsm'怎么解决 我安装的keil 3.3版本,以前用来编译C51,现在添加上ARM,操作系统是U COS II,编译时报--- Error: can\'t execute \'BIN30\\ArmAsm\',我把C:\\Keil\\ARM\\BIN30中的ARMASM.EXE拷贝到BIN中无法解决此问题,请教高手要怎么处理… 查看全部问答> |
|
斑竹: 我用vc33-120做了一块卡,外部晶阵是12m,5倍频,定时中断置数30000,理论计算 我的定时中断应该是1000hz,但是发现是100hz,我晶阵换过,都没有用.请教斑竹 最可能是什么原因啊 急!文字… 查看全部问答> |
|
TI OMAP 5平台不仅全面提升了性能,还采用了能够带来新机遇和用户体验的新特性,从而使应用处理器能够满足更广泛的要求。简而言之,OMAP 5平台将以其全新的性能及功能水平推动移动设备的变革,让我们共同开启“变革”新时代!$(\'swf_eBM\').innerH ...… 查看全部问答> |
|
#include #define uchar unsigned char #define uint unsigned int sbit uln=P2^0;//uln2803 sbit DQ=P2^1;//ds18b20与单片机连接口 sbit ming=P2^2;// sbit hong1=P2^3; sbit hong2=P2^4; sbit RS=P2^5; sbit RW=P2^6; sbit EN=P2^7; u ...… 查看全部问答> |




