1 修改设备树文件
设备树文件可以直接使用第三十五章中添加的gpioled子节点即可,不用重复添加。
2 platform驱动程序
本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/15_gpioled_dts
创建led_driver.c文件,具体内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | 1 #include <linux/types.h> 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 #include 21 #include 22 #include 23 24 #define LEDDEV_CNT 1 /* 设备号长度 */ 25 #define LEDDEV_NAME 'dtsplatled' /* 设备名字 */ 26 #define LEDOFF 0 27 #define LEDON 1 28 29 /* leddev设备结构体 */ 30 struct leddev_dev{ 31 dev_t devid; /* 设备号 */ 32 struct cdev cdev; /* cdev */ 33 struct class *class; /* 类 */ 34 struct device *device; /* 设备 */ 35 int major; /* 主设备号 */ 36 struct device_node *node; /* LED设备节点 */ 37 int led0; /* LED灯GPIO标号 */ 38 }; 39 40 struct leddev_dev leddev; /* led设备 */ 41 42 /* 43 * @description : LED打开/关闭 44 * @param - sta : LEDON(0) 打开LED,LEDOFF(1) 关闭LED 45 * @return : 无 46 */ 47 void led0_switch(u8 sta) 48 { 49 if (sta == LEDON ) 50 gpio_set_value(leddev.led0, 0); 51 else if (sta == LEDOFF) 52 gpio_set_value(leddev.led0, 1); 53 } 54 55 /* 56 * @description : 打开设备 57 * @param - inode : 传递给驱动的inode 58 * @param - filp : 设备文件,file结构体有个叫做private_data的成员变量 59 * 一般在open的时候将private_data指向设备结构体。 60 * @return : 0 成功;其他 失败 61 */ 62 static int led_open(struct inode *inode, struct file *filp) 63 { 64 filp->private_data = &leddev; /* 设置私有数据 */ 65 return 0; 66 } 67 68 /* 69 * @description : 向设备写数据 70 * @param - filp : 设备文件,表示打开的文件描述符 71 * @param - buf : 要写给设备写入的数据 72 * @param - cnt : 要写入的数据长度 73 * @param - offt : 相对于文件首地址的偏移 74 * @return : 写入的字节数,如果为负值,表示写入失败 75 */ 76 static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) 77 { 78 int retvalue; 79 unsigned char databuf[2]; 80 unsigned char ledstat; 81 82 retvalue = copy_from_user(databuf, buf, cnt); 83 if(retvalue < 0) { 84 85 printk('kernel write failed!rn'); 86 return -EFAULT; 87 } 88 89 ledstat = databuf[0]; 90 if (ledstat == LEDON) { 91 led0_switch(LEDON); 92 } else if (ledstat == LEDOFF) { 93 led0_switch(LEDOFF); 94 } 95 return 0; 96 } 97 98 /* 设备操作函数 */ 99 static struct file_operations led_fops = { 100 .owner = THIS_MODULE, 101 .open = led_open, 102 .write = led_write, 103 }; 104 105 /* 106 * @description : flatform驱动的probe函数,当驱动与 107 * 设备匹配以后此函数就会执行 108 * @param - dev : platform设备 109 * @return : 0,成功;其他负值,失败 110 */ 111 static int led_probe(struct platform_device *dev) 112 { 113 printk('led driver and device was matched!rn'); 114 /* 1、设置设备号 */ 115 if (leddev.major) { 116 leddev.devid = MKDEV(leddev.major, 0); 117 register_chrdev_region(leddev.devid, LEDDEV_CNT, LEDDEV_NAME); 118 } else { 119 alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME); 120 leddev.major = MAJOR(leddev.devid); 121 } 122 123 /* 2、注册设备 */ 124 cdev_init(&leddev.cdev, &led_fops); 125 cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT); 126 127 /* 3、创建类 */ 128 leddev.class = class_create(THIS_MODULE, LEDDEV_NAME); 129 if (IS_ERR(leddev.class)) { 130 return PTR_ERR(leddev.class); 131 } 132 133 /* 4、创建设备 */ 134 leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME); 135 if (IS_ERR(leddev.device)) { 136 return PTR_ERR(leddev.device); 137 } 138 139 /* 5、初始化IO */ 140 leddev.node = of_find_node_by_path('/gpioled'); 141 if (leddev.node == NULL){ 142 printk('gpioled node nost find!rn'); 143 return -EINVAL; 144 } 145 146 leddev.led0 = of_get_named_gpio(leddev.node, 'led-gpio', 0); 147 if (leddev.led0 < 0) { 148 printk('can't get led-gpiorn'); 149 return -EINVAL; 150 } 151 152 gpio_request(leddev.led0, 'led0'); 153 gpio_direction_output(leddev.led0, 1); /* led0 IO设置为输出,默认高电平 */ 154 return 0; 155 } 156 157 /* 158 * @description : platform驱动的remove函数,移除platform 驱动的时候此函数会执行 159 * @param - dev : platform设备 160 * @return : 0,成功;其他负值,失败 161 */ 162 static int led_remove(struct platform_device *dev) 163 { 164 gpio_set_value(leddev.led0, 1); /* 卸载驱动的时候关闭LED */ 165 166 cdev_del(&leddev.cdev); /* 删除cdev */ 167 unregister_chrdev_region(leddev.devid, LEDDEV_CNT); /* 注销设备号 */ 168 device_destroy(leddev.class, leddev.devid); 169 class_destroy(leddev.class); 170 return 0; 171 } 172 173 /* 匹配列表 */ 174 static const struct of_device_id led_of_match[] = { 175 { .compatible = 'gpioled' }, 176 { /* Sentinel */ } 177 }; 178 179 /* platform驱动结构体 */ 180 static struct platform_driver led_driver = { 181 .driver = { 182 .name = 'imx6ul-led', /* 驱动名字,用于和设备匹配 */ 183 .of_match_table = led_of_match, /* 设备树匹配表 */ 184 }, 185 .probe = led_probe, 186 .remove = led_remove, 187 }; 188 189 /* 190 * @description : 驱动模块加载函数 191 * @param : 无 192 * @return : 无 193 */ 194 static int __init leddriver_init(void) 195 { 196 return platform_driver_register(&led_driver); 197 } 198 199 /* 200 * @description : 驱动模块卸载函数 201 * @param : 无 202 * @return : 无 203 */ 204 static void __exit leddriver_exit(void) 205 { 206 platform_driver_unregister(&led_driver); 207 } 208 209 module_init(leddriver_init); 210 module_exit(leddriver_exit); 211 MODULE_LICENSE('GPL'); 212 MODULE_AUTHOR('topeet'); |
上一篇:迅为-iMX6ULL开发板-设置yocto文件系统开机自启动
下一篇:迅为i.MX6ULL终结者设备树下的Platform驱动运行测试
推荐阅读最新更新时间:2026-03-20 11:47
- 使用 ON Semiconductor 的 FAN2518S 的参考设计
- LTC1530S8、3.3V/3A 稳压器
- 使用 ON Semiconductor 的 ADP3167 的参考设计
- 使用 Analog Devices 的 LT3420EDD 的参考设计
- 基于Kinetis® M的低成本单相电表参考设计
- LTC3708、具有上升/下降轨跟踪功能的 2.5V/15A 和 1.2V/15A 稳压器
- NXQ1TXH5插件板
- 应变仪仪表放大器
- WRL-13287,基于 ESP8266 802.11 无线局域网的 SparkFun Wi-Fi Shield
- 4.1W、3-LED 通用 LED 照明驱动器



Esp32-S3任务代码合集
基于i.MX93的soft PLC源码及可执行代码
实用深度学习:基于Python的入门指南 (Edition)
非常经典的关于LLC的杨波博士论文
1-292148-8






京公网安备 11010802033920号