欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > [linux驱动开发--API框架]--platform、gpio、pinctrl

[linux驱动开发--API框架]--platform、gpio、pinctrl

2025/11/11 13:06:40 来源:https://blog.csdn.net/weixin_51226647/article/details/143605885  浏览:    关键词:[linux驱动开发--API框架]--platform、gpio、pinctrl

1. 结构体定义和实例化

// 这个结构体样式并不固定,按需增减成员,可以参考内核的其他驱动代码
struct leddev_dev{dev_t devid;                /* 设备号*/struct cdev cdev;           /* cdev*/struct class *class;        /* 类*/struct device *device;      /* 设备*/int major;                  /* 主设备号*/	struct device_node *node;   /* LED设备节点*/int led0;                   /* LED灯GPIO标号*/
}leddev;/*这个结构体最少也要有这些成员,可以参考内核的驱动代码*/
struct platform_driver led_platform_driver = {.probe = led_probe,.driver = {.name = "leds-platform_gpio",.owner = THIS_MODULE,.of_match_table = led_ids,}
};

2. 注册与卸载配套API

注意:顺序注册,逆序卸载

  1. 执行led_platform_driver_initled_platform_driver_exit函数
module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);
  1. 注册卸载平台驱动
DriverState = platform_driver_register(&led_platform_driver);
platform_driver_unregister(&led_platform_driver);
  1. /proc/devices/LEDDEV_NAME下生成名称对应LEDDEV_NAME的主设备号
alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);
unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
cdev_init(&leddev.cdev, &led_fops);
cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
cdev_del(&leddev.cdev);	
  1. /sys/class/LEDDEV_NAME下创建类
leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
class_destroy(leddev.class);
  1. /dev/LEDDEV_NAME下创建设备节点,在/sys/devices/virtual/gpio_lab_led下创建设备
leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);
device_destroy(leddev.class, leddev.devid);
  1. 试验了一下,现在的内核不需要显式释放leddev.led0
leddev.led0 = of_get_named_gpio(leddev.node, "led-gpio", 0);
gpio_direction_output(leddev.led0, 1);

3. 完整代码(仅供参考)

#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/of_gpio.h>
#define LEDDEV_CNT      1
#define LEDDEV_NAME     "gpio_lab_led"
/* leddev设备结构体 */
struct leddev_dev{dev_t devid;				/* 设备号	*/struct cdev cdev;			/* cdev		*/struct class *class;		/* 类 		*/struct device *device;		/* 设备		*/int major;					/* 主设备号	*/	struct device_node *node;	/* LED设备节点 */int led0;					/* LED灯GPIO标号 */
};struct leddev_dev leddev; 		/* led设备 */static int led_open(struct inode *inode, struct file *filp)
{return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}// /* 设备操作函数 */
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.write = led_write,
};/*----------------平台驱动函数集-----------------*/
static int led_probe(struct platform_device *pdv)
{printk(KERN_EMERG "led driver and device was matched!\r\n");// 注册的设备ID保存到leddev.devid// LEDDEV_NAME对应/proc/devices下的名字alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);leddev.major = MAJOR(leddev.devid);printk(KERN_EMERG "\tleddev.major = %d\n",leddev.major);// 绑定操作函数cdev_init(&leddev.cdev, &led_fops);// 绑定设备IDcdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);/* 3、创建类      */leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);if (IS_ERR(leddev.class)) {return PTR_ERR(leddev.class);}/* 4、创建设备 */leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);if (IS_ERR(leddev.device)) {return PTR_ERR(leddev.device);}leddev.node = of_find_node_by_path("/lab_led");if(leddev.node == NULL){printk(KERN_EMERG "get lab_led failed!  \n");}leddev.led0 = of_get_named_gpio(leddev.node, "gpios", 0);printk("led = %d \n",leddev.led0);/*设置gpio输出高电平*/gpio_direction_output(leddev.led0, 1);return 0;
}static const struct of_device_id led_ids[] = {{ .compatible = "gpio_lab_led"},{ /* sentinel */ }
};/*定义平台设备结构体*/
struct platform_driver led_platform_driver = {.probe = led_probe,.driver = {.name = "leds-platform_gpio",.owner = THIS_MODULE,.of_match_table = led_ids,}
};/*
*驱动初始化函数
*/
static int __init led_platform_driver_init(void)
{int DriverState;DriverState = platform_driver_register(&led_platform_driver);printk(KERN_EMERG "\tDriverState is %d\n",DriverState);return 0;
}/*
*驱动注销函数
*/
static void __exit led_platform_driver_exit(void)
{printk(KERN_EMERG "led_test exit!\n");gpio_direction_output(leddev.led0, 0);device_destroy(leddev.class, leddev.devid);class_destroy(leddev.class);cdev_del(&leddev.cdev);				/*  删除cdev */unregister_chrdev_region(leddev.devid, LEDDEV_CNT); /* 注销设备号 */platform_driver_unregister(&led_platform_driver);
}
module_init(led_platform_driver_init);
module_exit(led_platform_driver_exit);MODULE_LICENSE("GPL");

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com