迅为i.MX6ULL终结者设备树下的Platform驱动实验程序编写

发布者:huanli最新更新时间:2025-03-31 来源: cnblogs关键字:i  MX6ULL  Platform 手机看文章 扫描二维码
随时随地手机看文章

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');

  

[1] [2]
关键字:i  MX6ULL  Platform 引用地址:迅为i.MX6ULL终结者设备树下的Platform驱动实验程序编写

上一篇:迅为-iMX6ULL开发板-设置yocto文件系统开机自启动
下一篇:迅为i.MX6ULL终结者设备树下的Platform驱动运行测试

推荐阅读最新更新时间:2026-03-20 11:47

i.MX6ULL终结者设备树下Platform驱动运行测试
1 编译驱动程序 和前面章节中驱动测试程序一样需要一个Makefile文件,只是将obj-m的值改为led_driver.o,Makefile文件内容如下: 首先我们在终端输入两个命令(设置两个环境变量): 然后执行“make”命令编译模块,编译完成生成led_driver.ko模块文件。 2 编译应用测试程序 应用测试程序直接使用上一章44.3.2编译好的led_test应用程序即可。 3 运行测试 启动开发板,将编译好的led_driver.ko模块文件和led_test应用程序拷贝到/lib/modules/4.1.15目录下(检查开发板根文件系统中有没有“/lib/modules/4.1.15”这个目录,如果没有的话需
[单片机]
<font color='red'>迅</font><font color='red'>为</font><font color='red'>i</font>.MX6ULL终结者<font color='red'>设备</font><font color='red'>树下</font>的<font color='red'>Platform</font>驱动运行测试
i.MX6ULL开发板启动方式和镜像文件格式
i.MX6ULL 启动方式 启动方式 I.MX6ULL 支持多种启动方式,可以从 EMMC、SD 卡、NAND FLASH、USB、QSPI 等设备启动。通过查看《IMX6ULL 参考手册.pdf》手册的第 8 章 System Boot,可我们可以了解到 i.MX6ULL 在上电以后,芯片 ROM里面固化的程序会根据 BOOT_MODE 寄存器的值来选择启动方式。 BOOT_MODE 寄存器的值有两种方式可以修改:一种是采用 eFuses(熔丝)的方式;另一种是是通过设置 BOOT_MODE 对应的 GPIO 的状态。我们在平常使用的时候基本都是采用设置 BOOT_MODE 对应的 GPIO 状态来选择启动方式的。 BOOT_M
[单片机]
<font color='red'>迅</font><font color='red'>为</font><font color='red'>i</font>.MX6ULL开发板启动方式和镜像文件格式
恩智浦i.MX8MM开发平台虚拟机安装Ubuntu16.04系统
1) “ Ubuntu16.04”的系统安装镜像可以到网盘“i.MX8MM 开发板2-i.MX8MM 开发板网盘资料汇总(不含光 盘 内 容 )2_i.MX8MM 开 发 板 搭 建 好 编 译 环 境 的 Ubuntu16.04 虚 拟 机 镜 像 ” 下 载 , 文 件“ubuntu16_04_6.7z.001 系列压缩包 ”即为 Ubuntu 系统的安装镜像,将压缩包全部下载下来,如下图所示: 2) 全部下载下来后,选中第一个文件 ubuntu16_04_6.7z.001,然后点击鼠标右键进行解压,解压完毕生成一个 ubuntu16_04_6 的文件夹,如下图所示: 3)打开虚拟机,如下图所示: 4)如下图所示,红色框
[单片机]
<font color='red'>迅</font><font color='red'>为</font>恩智浦<font color='red'>i</font>.MX8MM开发平台虚拟机安装Ubuntu16.04系统
iTOP-i.MX6ULL开发板-网络通信-套字节UDP
iTOP-IMX6ULL 实现基于 UDP 的 socket 编程。 78.1 实验操作 UDP 是用户数据报协议,它是一种无连接的传输层协议,提供面向事物的简单不可靠信息传送服务,所以在一些网络质量不满意的环境下,UDP 协议数据包丢失会比较严重,会造成数据的丢失。UDP 的特点是它不属于连接型协议,所以资源消耗小。处理速度快的优点,所以通常音频,视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。 UDP 的通信框图如图 78.1.1 所示 从上图可以看到基于 UDP 通信的程序也是由服务器和客户端组成。与 TCP 的服务器不同,UDP 的服务器不需要 listen 和
[单片机]
<font color='red'>迅</font><font color='red'>为</font>iTOP-<font color='red'>i</font>.MX6ULL开发板-网络通信-套字节UDP
i.MX6ULL开发板-移植OpenCv2.4.9-搭建OpenCv编译环境
我们需要准备的资料: 1. 开发板使用的是 i.MX6ULL 终结者,开发板里面是 Yocto 文件系统。 2. 使用 Ubuntu 16.04 3. 提供 opencv 源码“opencv-2.4.9.zip” 4. QT 测试例程 85.1 安装交叉编译工具 移植的 QT 系统需要的交叉编译器就是我们编译 qt 的编译器,因为我们是 Yocto 系统,所以我们用编译 Yocto 的编译器来编译 OpenCV。交叉编译器为:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf。设置交叉编译器请参考 i.MX6ULL 终结者-开发板使用手册 4.3 章节 搭建交叉编译环境。 85.
[单片机]
<font color='red'>迅</font><font color='red'>为</font><font color='red'>i</font>.MX6ULL开发板-移植OpenCv2.4.9-搭建OpenCv编译环境
i.MX6ULL终结者Mfgtools修改单独只烧写Uboot,内核,文件系统
1.打开mfgtools_for_6ULL文件夹,找到cfg.ini文件,如果您的板子是EMMC的修改如图 1: 如果您的板子是NAND的,修改如图 2: 2.打开“Profiles Linux OS Firmwareucl2.xml文件,修改此文件 如果您想mfgtools只烧写uboot,就把下图的代码注释掉,其余的不要动 图 3是修改NAND的板子 图 4是修改EMMC的板子 图 5是修改NAND的板子,如果您想mfgtools只烧写内核,就把下面图一的代码注释掉,其余的不要动。 图 6是修改EMMC的板子,如果您想mfgtools只烧写zImage,就注释掉下面图二的代码,其余的不要动。 图 7是修改EMMC的板子
[单片机]
<font color='red'>迅</font><font color='red'>为</font><font color='red'>i</font>.MX6ULL终结者Mfgtools修改单独只烧写Uboot,内核,文件系统
i.MX6ULL终结者进程基础 exec函数族
用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序,该子进程被新的程序替换,改变地址空间,进程映像和一些属性,但是pid号不变。 execve(): #include int execve(const char *filename, char *const argv , char *const envp ); 参数含义: filename:路径名,表示载入进程空间的新程序路径。 argv :命令行参数,argv 为命令名。 envp :新程序的环境变量。 返回值:成功时不会返回,使用时不用检查返回值,可通过errno检查。 以下函数都是根据execve实现: int execl(const char *p
[单片机]
<font color='red'>迅</font><font color='red'>为</font><font color='red'>i</font>.MX6ULL终结者进程基础 exec函数族
【IMX6ULL学习笔记】十六、设备树下LED驱动
一、修改设备树文件 在根节点“/”下创建一个名为“alphaled”的子节点,打开 imx6ull-alientek-emmc.dts 文件,在根节点“/”最后面输入如下所示内容: alphaled { #address-cells = 1 ; #size-cells = 1 ; compatible = atkalpha-led ; status = okay ; reg = 0X020C406C 0X04 /* CCM_CCGR1_BASE */ 0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */ 0X020E02F4 0X04 /* SW_PAD_GPIO1_IO0
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved