1. IIC设备

i2c设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。通过platform_add_devices(platform_device_register)函数将定义的平台设备注册到内核中,用于匹配设备驱动。

内核在drivers\i2c\i2c-s3c2410.c目录中实现了s3c2416 i2c驱动,在mach-home2416.c中实现i2c设备。

  1. static struct resources3c_i2c0_resource[] = {
  2. [0]= DEFINE_RES_MEM(S3C_PA_IIC, SZ_4K),
  3. [1]= DEFINE_RES_IRQ(IRQ_IIC),
  4. };
  5. struct platform_device s3c_device_i2c0 ={
  6. .name = "s3c2410-i2c",
  7. .id = 0,
  8. .num_resources = ARRAY_SIZE(s3c_i2c0_resource),
  9. .resource = s3c_i2c0_resource,
  10. };
  11. struct s3c2410_platform_i2cdefault_i2c_data __initdata = {
  12. .flags = 0,
  13. .slave_addr = 0x10,
  14. .frequency = 100*1000,
  15. .sda_delay = 100,
  16. };
  17. void __init s3c_i2c0_set_platdata(structs3c2410_platform_i2c *pd)
  18. {
  19. structs3c2410_platform_i2c *npd;
  20. if(!pd) {
  21. pd= &default_i2c_data;
  22. pd->bus_num= 0;
  23. }
  24. npd= s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
  25. &s3c_device_i2c0);
  26. if(!npd->cfg_gpio)
  27. npd->cfg_gpio= s3c_i2c0_cfg_gpio;
  28. }

在板级初始化函数home2416_machine_init ()中加入i2c平台数据,s3c_i2c0_set_platdata(NULL),在static struct platform_device *home2416_devices[]板级平台设备列表中加入&s3c_device_i2c0,使i2c设备能够注册到内核中。

2. 内核配置

Linux内核配置支持i2c设备驱动,选中Device Drivers->I2C support->I2CHardware Bus support->S3C2410 I2C Driver。 12_I2C驱动 - 图1

3. 应用编程

cat/proc/devices可以知道i2c的主设备号为89,次设备号为0,在/dev目录中创建i2c设备文件。

  1. mknod /dev/i2c-0 c 89 0

应用程序可以通过设备文件访问i2c,i2c应用测试代码i2c_test.c实现对eeprom at24cxx的读写。

  1. #include "fcntl.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <linux/i2c.h>
  5. #include <linux/i2c-dev.h>
  6. #include <sys/ioctl.h>
  7. int main(void)
  8. {
  9. unsignedchar addr;
  10. intret;
  11. intfd;
  12. inti;
  13. unsignedchar buf[9];
  14. fd= open("/dev/i2c-0", O_RDWR);
  15. if(fd == -1) {
  16. printf("Openi2c-0 failed\n");
  17. exit(1);
  18. }
  19. ret= ioctl(fd, I2C_TENBIT, 0); // 7 bit address
  20. if(ret == -1) {
  21. printf("IO1failed\n");
  22. close(fd);
  23. exit(1);
  24. }
  25. ioctl(fd,I2C_SLAVE_FORCE, 0x50); // at24c08 slave address 0x50(7 bit)
  26. ioctl(fd,I2C_TIMEOUT, 1);
  27. ioctl(fd,I2C_RETRIES, 2);
  28. buf[0]= 0x20; // write address
  29. buf[1]= 0x12; // write 8 bytes
  30. buf[2]= 0x34;
  31. buf[3]= 0x56;
  32. buf[4]= 0x78;
  33. buf[5]= 0x98;
  34. buf[6]= 0x76;
  35. buf[7]= 0x54;
  36. buf[8]= 0x32;
  37. ret= write(fd, buf, 9);
  38. if(ret == -1) {
  39. printf("Writefailed\n");
  40. close(fd);
  41. exit(1);
  42. }
  43. printf("write:");
  44. for(i=1; i<9; i++) {
  45. printf("%02x", buf[i]);
  46. }
  47. sleep(1);// wait done
  48. //read test
  49. ret= write(fd, buf, 1); // read address
  50. if(ret == -1) {
  51. printf("Writefailed\n");
  52. close(fd);
  53. exit(1);
  54. }
  55. ret= read(fd, buf, 8); // read 8 bytes
  56. if(ret == -1) {
  57. printf("Readfailed\n");
  58. close(fd);
  59. exit(1);
  60. }
  61. close(fd);
  62. printf("read:");
  63. for(i=0; i<8; i++) {
  64. printf("%02x", buf[i]);
  65. }
  66. return 0;
  67. }

用arm-linux-gcc静态编译,使之生成arm cpu可执行的指令,并且可脱离任何库独立运行,arm-linux-gcc -static -o i2c_test i2c_test.c,生成i2c_test可执行文件。复制可执行文件到根文件系统,目标板启动后在目录输入./i2c_test即可执行。 12_I2C驱动 - 图2