嵌入式Linux设备驱动开发:Mastering Embedded Linux Programming中的GPIO和I2C实战
【免费下载链接】Mastering-Embedded-Linux-Programming-Third-EditionMastering Embedded Linux Programming Third Edition, published by Packt项目地址: https://gitcode.com/gh_mirrors/ma/Mastering-Embedded-Linux-Programming-Third-Edition
嵌入式Linux设备驱动开发是连接硬件与软件的桥梁,而GPIO(通用输入输出)和I2C(集成电路总线)则是最常用的硬件接口。本文将基于《Mastering Embedded Linux Programming》第三版中的实战案例,带你快速掌握这两种接口的驱动开发方法,让你的嵌入式项目轻松与外部硬件交互。
📌 什么是GPIO?嵌入式开发的"万能接口"
GPIO(General Purpose Input/Output)是嵌入式系统中最基础也最灵活的接口,几乎所有微处理器都配备了GPIO控制器。它可以配置为输入或输出模式,用于连接LED、按键、传感器等简单外设。
在《Mastering Embedded Linux Programming》的Chapter11/gpio-int/gpio-int.c示例中,展示了如何使用epoll机制监听GPIO中断:
/* * Demonstration of using epoll(2) to wait for an interrupt on GPIO. * * To try this out on a BeagleBone Black, connect a push button switch * between P9 15 (gpio1_16) and P9 1 (ground). * * gpio1_15 is configured as gpio 48, so to make it an input which * triggers on a falling edge, write * * echo 48 > /sys/class/gpio/export * echo falling > /sys/class/gpio/gpio48/edge */这个示例通过sysfs接口配置GPIO,使用epoll_wait()函数阻塞等待中断事件,实现了高效的按键检测功能。
🔌 GPIO驱动开发实战:从用户空间到内核空间
快速配置GPIO的3种方法
- sysfs接口:最简单的用户空间控制方式,如上述示例中使用的
/sys/class/gpio文件系统 - 设备树配置:在设备树中定义GPIO引脚功能和属性,如Chapter04/nova.dts
- 内核驱动:编写内核模块直接操作GPIO控制器寄存器
实战案例:按键中断处理
Chapter11/gpio-int/gpio-int.c中的核心代码展示了如何使用epoll监听GPIO中断:
ev.events = EPOLLPRI; ev.data.fd = f; ret = epoll_ctl(ep, EPOLL_CTL_ADD, f, &ev); if (ret == -1) { perror("Can't register target file descriptor with epoll"); return 1; } while (1) { printf("Waiting\n"); ret = epoll_wait(ep, &events, 1, -1); if (ret > 0) { n = read(f, &value, sizeof(value)); printf("Button pressed: read %d bytes, value=%c\n", n, value[0]); lseek(f, 0, SEEK_SET); } }这段代码创建了epoll实例,添加GPIO文件描述符到监听集合,然后进入循环等待中断事件。当按键被按下时,epoll_wait()返回,程序读取GPIO值并处理。
📡 I2C总线:连接传感器的"高速公路"
I2C(Inter-Integrated Circuit)是一种多主从架构的串行总线,只需要两根线(SDA和SCL)就能连接多个设备,非常适合连接传感器、EEPROM、ADC等外设。
《Mastering Embedded Linux Programming》在Chapter11/i2c-example/i2c-eeprom-read.c中提供了I2C设备访问的示例,演示了如何读取EEPROM数据:
/* Address of the EEPROM on the BeagleBone Black board */ #define I2C_ADDRESS 0x50 /* Open the adapter and set the address of the I2C device */ f = open("/dev/i2c-0", O_RDWR); if (f < 0) { perror("/dev/i2c-0:"); return 1; } /* Set the address of the i2c slave device */ if (ioctl(f, I2C_SLAVE, I2C_ADDRESS) == -1) { perror("ioctl I2C_SLAVE"); return 1; }🛠️ I2C驱动开发全流程
从设备树配置到用户空间访问
- 设备树配置I2C控制器和设备:在Chapter04/nova.dts中定义I2C总线和连接的设备
- 内核I2C驱动:实现I2C设备驱动,注册设备和操作函数
- 用户空间访问:通过
/dev/i2c-x设备节点与I2C设备通信
实战案例:读取I2C EEPROM
Chapter11/i2c-example/i2c-eeprom-read.c完整展示了如何从用户空间访问I2C设备:
/* Set the 16-bit address to read (0) */ buf[0] = 0; /* address byte 1 */ buf[1] = 0; /* address byte 2 */ n = write(f, buf, 2); if (n == -1) { perror("write"); return 1; } /* Now read 4 bytes from that address */ n = read(f, buf, 4); if (n == -1) { perror("read"); return 1; } printf("0x%x 0x%x 0x%x 0x%x\n", buf[0], buf[1], buf[2], buf[3]);这段代码首先向I2C设备写入要读取的地址,然后读取指定长度的数据,实现了对I2C EEPROM的基本访问。
📚 进阶学习资源
《Mastering Embedded Linux Programming》第三版提供了更多嵌入式Linux驱动开发的实战案例:
- SPI接口:Chapter12/spidev-read/和Chapter12/spidev-test/
- 内核模块开发:Chapter11/dummy-driver/
- 设备树详解:Chapter04/nova.dts和Chapter06/buildroot/board/melp/nova/nova.dts
🔖 总结
GPIO和I2C是嵌入式Linux开发中最常用的硬件接口,掌握它们的驱动开发方法是构建嵌入式系统的基础。通过《Mastering Embedded Linux Programming》提供的实战案例,你可以快速上手这两种接口的开发,从用户空间的简单控制到内核空间的驱动编写。
无论是连接简单的LED和按键,还是复杂的传感器和外设,GPIO和I2C都能满足你的需求。现在就动手实践吧,体验嵌入式Linux驱动开发的乐趣!
要开始学习,你可以克隆项目仓库:
git clone https://gitcode.com/gh_mirrors/ma/Mastering-Embedded-Linux-Programming-Third-Edition然后进入Chapter11/目录,查看GPIO和I2C的示例代码。
【免费下载链接】Mastering-Embedded-Linux-Programming-Third-EditionMastering Embedded Linux Programming Third Edition, published by Packt项目地址: https://gitcode.com/gh_mirrors/ma/Mastering-Embedded-Linux-Programming-Third-Edition
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考