当前位置:网站首页>i.MX6ULL驱动开发 | 24 - 基于platform平台驱动模型点亮LED
i.MX6ULL驱动开发 | 24 - 基于platform平台驱动模型点亮LED
2022-07-04 21:34:00 【Mculover666】
一、编写基本设备驱动模块
编写驱动模块源码:
#include <linux/module.h>
#include <linux/init.h>
static int __init platform_led_init(void)
{
return 0;
}
static void __exit platform_led_exit(void)
{
}
module_init(platform_led_init);
module_exit(platform_led_exit);
MODULE_AUTHOR("Mculover666");
MODULE_LICENSE("GPL");
编写Makefile:
KERNEL_DIR = /home/mculover666/develop/imx6ull/linux-imx6ull
obj-m := platform_led.o
build: kernel_module
kernel_module:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
编译:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make
二、编写platform驱动框架
添加platform驱动框架:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
static int led_probe(struct platform_device *dev)
{
return 0;
}
static int led_remove(struct platform_device *dev)
{
return 0;
}
/** * @brief 设备树匹配列表 */
static const struct of_device_id plat_led_of_match[] = {
{
.compatible = "atk,plat_led" },
{
},
};
/** * @brief 传统id方式匹配列表 */
static const struct platform_device_id plat_led_id[] = {
{
"atk,plat_led", 0 },
{
},
};
static struct platform_driver led_driver = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "platform_led",
.owner = THIS_MODULE,
.of_match_table = plat_led_of_match,
},
.id_table = plat_led_id,
};
static int __init platform_led_init(void)
{
int ret;
ret = platform_driver_register(&led_driver);
if (ret < 0) {
printk("platform_driver_register fail!\n");
return -1;
}
return 0;
}
static void __exit platform_led_exit(void)
{
platform_driver_unregister(&led_driver);
}
module_init(platform_led_init);
module_exit(platform_led_exit);
MODULE_AUTHOR("Mculover666");
MODULE_LICENSE("GPL");
三、编写字符设备驱动
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
dev_t led_dts_dev;
struct cdev *led_dts_cdev;
struct class *led_dts_class;
struct device *led_dts_device0;
static int led_dts_open(struct inode *inode, struct file *fp)
{
return 0;
}
static int led_dts_read(struct file *fp, char __user *buf, size_t size, loff_t *off)
{
return 0;
}
static int led_dts_write(struct file *fp, const char __user *buf, size_t size, loff_t *off)
{
return 0;
}
static int led_dts_release(struct inode *inode, struct file *fp)
{
return 0;
}
static struct file_operations led_dts_fops = {
.owner = THIS_MODULE,
.open = led_dts_open,
.read = led_dts_read,
.write = led_dts_write,
.release = led_dts_release,
};
static int led_probe(struct platform_device *dev)
{
int ret;
printk("led probe called!\n");
//分配cdev设备号
ret = alloc_chrdev_region(&led_dts_dev, 0, 1, "led_dts");
if (ret != 0) {
printk("alloc_chrdev_region fail!");
return -1;
}
//初始化cdev
led_dts_cdev = cdev_alloc();
if (!led_dts_cdev) {
printk("cdev_alloc fail!");
return -1;
}
//设置fop操作函数
led_dts_cdev->owner = THIS_MODULE;
led_dts_cdev->ops = &led_dts_fops;
//注册cdev
cdev_add(led_dts_cdev, led_dts_dev, 1);
// 创建设备类
led_dts_class = class_create(THIS_MODULE, "led_dts_class");
if (!led_dts_class) {
printk("class_create fail!");
return -1;
}
//创建设备节点
led_dts_device0 = device_create(led_dts_class, NULL, led_dts_dev, NULL, "led0");
if (IS_ERR(led_dts_device0)) {
printk("device_create led_dts_device0 fail!");
return -1;
}
return 0;
}
static int led_remove(struct platform_device *dev)
{
printk("led remove called!\n");
// 将设备从内核删除
cdev_del(led_dts_cdev);
// 释放设备号
unregister_chrdev_region(led_dts_dev, 1);
// 删除设备节点
device_destroy(led_dts_class, led_dts_dev);
// 删除设备类
class_destroy(led_dts_class);
return 0;
}
四、编写LED驱动
和i.MX6ULL驱动开发 | 08 -基于pinctrl子系统和gpio子系统点亮LED一样。
五、测试结果
1. 加载驱动模块
查看platform总线是否注册:
ls /sys/bus/platform/drivers
查看总线设备是否注册(因为有设备树节点的描述):
ls /sys/bus/platform/devices/
注意,这里驱动加载的时候,内核会去匹配对应的设备,所以设备树节点描述的兼容性要与驱动中的兼容性一致:
2. led测试
查看设备节点:
ls /dev/
运行测试程序,可以看到led闪烁:
边栏推荐
- Compréhension approfondie du symbole [langue C]
- HDU - 2859 Phalanx(DP)
- Cadeus has never stopped innovating. Decentralized edge rendering technology makes the metauniverse no longer far away
- 股票开户流程是什么?使用同花顺手机炒股软件安全吗?
- MP3是如何诞生的?
- Telephone encryption, middle 4 is replaced by * * * *
- WebGIS框架---kalrry
- 【活动早知道】LiveVideoStack近期活动一览
- How was MP3 born?
- TCP三次握手,四次挥手,你真的了解吗?
猜你喜欢
El tree combined with El table, tree adding and modifying operations
From repvgg to mobileone, including mobileone code
【公开课预告】:视频质量评价基础与实践
Redis has three methods for checking big keys, which are necessary for optimization
MP3是如何诞生的?
[leetcode] 17. Letter combination of telephone number
KDD2022 | 什么特征进行交互才是有效的?
广电五舟与华为签署合作协议,共同推进昇腾AI产业持续发展
QT—双缓冲绘图
从RepVgg到MobileOne,含mobileone的代码
随机推荐
Nat. Commun.| 机器学习对可突变的治疗性抗体的亲和力和特异性进行共同优化
【C语言】符号的深度理解
解决异步接口慢导致的数据错乱问题
Flutter 返回按钮的监听
广电五舟与华为签署合作协议,共同推进昇腾AI产业持续发展
How to use concurrentlinkedqueue as a cache queue
AcWing 2022 每日一题
玩转gRPC—深入概念与原理
并列图的画法,多排多列
【公开课预告】:视频质量评价基础与实践
力扣98:验证二叉搜索树
For MySQL= No data equal to null can be found. Solution
挖财学院股票开户安全吗?开户只能在挖财开户嘛?
Cloudcompare & open3d DBSCAN clustering (non plug-in)
File read write
一文掌握数仓中auto analyze的使用
Minidom module writes and parses XML
Bizchart+slider to realize grouping histogram
Solve the problem of data disorder caused by slow asynchronous interface
Daily question-leetcode556-next larger element iii-string-double pointer-next_ permutation