作 者:道哥,10 年嵌入式开发老兵,专注于:C/C 、嵌入式、Linux。
关注下方公众号,回复【书籍】,获取 Linux、嵌入式领域经典书籍;回复【PDF】,获取所有原创文章( PDF 格式)。
目录
别人的经验,我们的阶梯!
大家好,我是道哥。
在前几篇文章中,我们一块讨论了:在Linux系统中,编写
字符设备驱动程序的基本框架,主要是从
代码流程和 API 函数这两方面触发。
这篇文章,我们就以此为基础,写一个有
实际应用功能的驱动程序:
-
在驱动程序中,初始化 GPIO 设备,自动创建设备节点;
-
在应用程序中,打开 GPIO 设备,并发送控制指令设置 GPIO 口的状态;
示例程序目标
编写一个驱动程序模块:
mygpio.ko。
当这个驱动模块被加载的时候,在系统中创建一个mygpio类设备,并且在/dev目录下,创建4个设备节点:
/dev/mygpio0
/dev/mygpio1
/dev/mygpio2
/dev/mygpio3
因为我们现在是在x86平台上来
模拟 GPIO的控制操作,
并没有实际的GPIO硬件设备。
因此,在驱动代码中,与硬件相关部分的代码,使用宏MYGPIO_HW_ENABLE控制起来,并且在其中使用printk输出打印信息来体现硬件的操作。
在应用程序中,可以分别打开以上这4个GPIO设备,并且通过发送
控制指令,来设置GPIO的状态。
以下所有操作的工作目录,都是与上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。
创建驱动目录和驱动程序
$ cd linux-4.15/drivers/
$ mkdir mygpio_driver
$ cd mygpio_driver
$ touch mygpio.c
mygpio.c文件的内容如下(
不需要手敲,文末有代码下载链接):
#include
#include
#include
#include
#include
// GPIO 硬件相关宏定义
#define MYGPIO_HW_ENABLE
// 设备名称
#define MYGPIO_NAME "mygpio"
// 一共有4个 GPIO 口
#define MYGPIO_NUMBER 4
// 设备类
static struct class *gpio_class;
// 用来保存设备
struct cdev gpio_cdev[MYGPIO_NUMBER];
// 用来保存设备号
int gpio_major = 0;
int gpio_minor = 0;
#ifdef MYGPIO_HW_ENABLE
// 硬件初始化函数,在驱动程序被加载的时候(gpio_driver_init)被调用
static void gpio_hw_init(int gpio)
{
printk("gpio_hw_init is called: %d. \n", gpio);
}
// 硬件释放
static void gpio_hw_release(int gpio)
{
printk("gpio_hw_release is called: %d. \n", gpio);
}
// 设置硬件GPIO的状态,在控制GPIO的时候(gpio_ioctl)被调研
static void gpio_hw_set(unsigned long gpio_no, unsigned int val)
{
printk("gpio_hw_set is called. gpio_no = %ld, val = %d. \n", gpio_no, val);
}
#endif
// 当应用程序打开设备的时候被调用
static int gpio_open(struct inode *inode, struct file *file)
{
printk("gpio_open is called. \n");
return 0;
}
// 当应用程序控制GPIO的时候被调用
static long gpio_ioctl(struct file* file, unsigned int val, unsigned long gpio_no)
{
printk("gpio_ioctl is called. \n");
// 检查设置的状态值是否合法
if (0 != val
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。