建设一个最普通网站要多少钱,网络推广网站推广,网站建设 天津,股票配资网站建设Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发
1、platform设备与驱动程序开发
53 /*
54 * 设备资源信息#xff0c;也就是 LED0 所使用的所有寄存器
55 */
56 static str…Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发
1、platform设备与驱动程序开发
53 /*
54 * 设备资源信息也就是 LED0 所使用的所有寄存器
55 */
56 static struct resource led_resources[] {
57 [0] {
58 .start CCM_CCGR1_BASE,
59 .end (CCM_CCGR1_BASE REGISTER_LENGTH - 1),
60 .flags IORESOURCE_MEM,
61 },
62 [1] {
63 .start SW_MUX_GPIO1_IO03_BASE,
64 .end (SW_MUX_GPIO1_IO03_BASE REGISTER_LENGTH - 1),
65 .flags IORESOURCE_MEM,
66 },
67 [2] {
68 .start SW_PAD_GPIO1_IO03_BASE,
69 .end (SW_PAD_GPIO1_IO03_BASE REGISTER_LENGTH - 1),
70 .flags IORESOURCE_MEM,
71 },
72 [3] {
73 .start GPIO1_DR_BASE,
74 .end (GPIO1_DR_BASE REGISTER_LENGTH - 1),
75 .flags IORESOURCE_MEM,
76 },
77 [4] {
78 .start GPIO1_GDIR_BASE,
79 .end (GPIO1_GDIR_BASE REGISTER_LENGTH - 1),
80 .flags IORESOURCE_MEM,
81 },
82 }; led_resources 数组也就是设备资源描述了 LED 所要使用到的寄存器信息也就是 IORESOURCE_MEM 资源。
85 /*
86 * platform 设备结构体
87 */
88 static struct platform_device leddevice {
89 .name imx6ul-led,
90 .id -1,
91 .dev {
92 .release led_release,
93 },
94 .num_resources ARRAY_SIZE(led_resources),
95 .resource led_resources,
96 }; platform 设备结构体变量 leddevice这里要注意 name 字段为“imx6ul-led”所 以稍后编写 platform 驱动中的 name 字段也要为“imx6ul-led”否则设备和驱动匹配失败。
98 /*
99 * description : 设备模块加载
100 * param : 无
101 * return : 无
102 */
103 static int __init leddevice_init(void)
104 {
105 return platform_device_register(leddevice);
106 } 设备模块加载函数在此函数里面通过 platform_device_register 向 Linux 内核注册 leddevice 这个 platform 设备。
108 /*
109 * description : 设备模块注销
110 * param : 无
111 * return : 无
112 */
113 static void __exit leddevice_exit(void)
114 {
115 platform_device_unregister(leddevice);
116 } 设备模块卸载函数在此函数里面通过 platform_device_unregister 从 Linux内核中删除掉 leddevice 这个 platform 设备。
34 #define LEDDEV_CNT 1 /* 设备号长度 */
35 #define LEDDEV_NAME platled /* 设备名字 */
36 #define LEDOFF 0
37 #define LEDON 1
38
39 /* 寄存器名 */
40 static void __iomem *IMX6U_CCM_CCGR1;
41 static void __iomem *SW_MUX_GPIO1_IO03;
42 static void __iomem *SW_PAD_GPIO1_IO03;
43 static void __iomem *GPIO1_DR;
44 static void __iomem *GPIO1_GDIR;
45
46 /* leddev 设备结构体 */
47 struct leddev_dev{
48 dev_t devid; /* 设备号 */
49 struct cdev cdev; /* cdev */
50 struct class *class; /* 类 */
51 struct device *device; /* 设备 */
52 int major; /* 主设备号 */
53 };
54
55 struct leddev_dev leddev; /* led 设备 */
56
57 /*
58 * description : LED 打开/关闭
59 * param - sta : LEDON(0) 打开 LED LEDOFF(1) 关闭 LED
60 * return : 无
61 */
62 void led0_switch(u8 sta)
63 {
64 u32 val 0;
65 if(sta LEDON){
66 val readl(GPIO1_DR);
67 val ~(1 3);
68 writel(val, GPIO1_DR);
69 }else if(sta LEDOFF){
70 val readl(GPIO1_DR);
71 val| (1 3);
72 writel(val, GPIO1_DR);
73 }
74 }
75
76 /*
77 * description : 打开设备
78 * param – inode : 传递给驱动的 inode
79 * param - filp : 设备文件 file 结构体有个叫做 private_data 的成员变量
80 * 一般在 open 的时候将 private_data 指向设备结构体。
81 * return : 0 成功;其他 失败
82 */
83 static int led_open(struct inode *inode, struct file *filp)
84 {
85 filp-private_data leddev; /* 设置私有数据 */
86 return 0;
87 }
88
89 /*
90 * description : 向设备写数据
91 * param – filp : 设备文件表示打开的文件描述符
92 * param - buf : 要写给设备写入的数据
93 * param - cnt : 要写入的数据长度
94 * param - offt : 相对于文件首地址的偏移
95 * return : 写入的字节数如果为负值表示写入失败
96 */
97 static ssize_t led_write(struct file *filp, const char __user *buf,
size_t cnt, loff_t *offt)
98 {
99 int retvalue;
100 unsigned char databuf[1];
101 unsigned char ledstat;
102
103 retvalue copy_from_user(databuf, buf, cnt);
104 if(retvalue 0) {
105 return -EFAULT;
106 }
107
108 ledstat databuf[0]; /* 获取状态值 */
109 if(ledstat LEDON) {
110 led0_switch(LEDON); /* 打开 LED 灯 */
111 }else if(ledstat LEDOFF) {
112 led0_switch(LEDOFF); /* 关闭 LED 灯 */
113 }
114 return 0;
115 }
116
117 /* 设备操作函数 */
118 static struct file_operations led_fops {
119 .owner THIS_MODULE,
120 .open led_open,
121 .write led_write,
122 }; 以上是传统的字符设备驱动。
124 /*
125 * description : flatform 驱动的 probe 函数当驱动与设备
126 * 匹配以后此函数就会执行
127 * param - dev : platform 设备
128 * return : 0成功;其他负值,失败
129 */
130 static int led_probe(struct platform_device *dev)
131 {
132 int i 0;
133 int ressize[5];
134 u32 val 0;
135 struct resource *ledsource[5];
136
137 printk(led driver and device has matched!\r\n);
138 /* 1、获取资源 */
139 for (i 0; i 5; i) {
140 ledsource[i] platform_get_resource(dev, IORESOURCE_MEM, i);
141 if (!ledsource[i]) {
142 dev_err(dev-dev, No MEM resource for always on\n);
143 return -ENXIO;
144 }
145 ressize[i] resource_size(ledsource[i]);
146 }
147
148 /* 2、初始化 LED */
149 /* 寄存器地址映射 */
150 IMX6U_CCM_CCGR1 ioremap(ledsource[0]-start, ressize[0]);
151 SW_MUX_GPIO1_IO03 ioremap(ledsource[1]-start, ressize[1]);
152 SW_PAD_GPIO1_IO03 ioremap(ledsource[2]-start, ressize[2]);
153 GPIO1_DR ioremap(ledsource[3]-start, ressize[3]);
154 GPIO1_GDIR ioremap(ledsource[4]-start, ressize[4]);
155
156 val readl(IMX6U_CCM_CCGR1);
157 val ~(3 26); /* 清除以前的设置 */
158 val | (3 26); /* 设置新值 */
159 writel(val, IMX6U_CCM_CCGR1);
160
161 /* 设置 GPIO1_IO03 复用功能将其复用为 GPIO1_IO03 */
162 writel(5, SW_MUX_GPIO1_IO03);
163 writel(0x10B0, SW_PAD_GPIO1_IO03);
164
165 /* 设置 GPIO1_IO03 为输出功能 */
166 val readl(GPIO1_GDIR);
167 val ~(1 3); /* 清除以前的设置 */
168 val | (1 3); /* 设置为输出 */
169 writel(val, GPIO1_GDIR);
170
171 /* 默认关闭 LED1 */
172 val readl(GPIO1_DR);
173 val | (1 3) ;
174 writel(val, GPIO1_DR);
175
176 /* 注册字符设备驱动 */
177 /*1、创建设备号 */
178 if (leddev.major) { /* 定义了设备号 */
179 leddev.devid MKDEV(leddev.major, 0);
180 register_chrdev_region(leddev.devid, LEDDEV_CNT,
LEDDEV_NAME);
181 } else { /* 没有定义设备号 */
182 alloc_chrdev_region(leddev.devid, 0, LEDDEV_CNT,
LEDDEV_NAME);
183 leddev.major MAJOR(leddev.devid);
184 }
185
186 /* 2、初始化 cdev */
187 leddev.cdev.owner THIS_MODULE;
188 cdev_init(leddev.cdev, led_fops);
189
190 /* 3、添加一个 cdev */
191 cdev_add(leddev.cdev, leddev.devid, LEDDEV_CNT);
192
193 /* 4、创建类 */
194 leddev.class class_create(THIS_MODULE, LEDDEV_NAME);
195 if (IS_ERR(leddev.class)) {
196 return PTR_ERR(leddev.class);
197 }
198
199 /* 5、创建设备 */
200 leddev.device device_create(leddev.class, NULL, leddev.devid,
NULL, LEDDEV_NAME);
201 if (IS_ERR(leddev.device)) {
202 return PTR_ERR(leddev.device);
203 }
204
205 return 0;
206 } probe 函数当设备和驱动匹配以后此函数就会执行当匹配成功以后会在终端上输出“led driver and device has matched!”这样语句。在 probe 函数里面初始化 LED、注册字符设备驱动。也就是将原来在驱动加载函数里面做的工作全部放到 probe 函数里面完成。
208 /*
209 * description :移除 platform 驱动的时候此函数会执行
210 * param - dev : platform 设备
211 * return : 0成功;其他负值,失败
212 */
213 static int led_remove(struct platform_device *dev)
214 {
215 iounmap(IMX6U_CCM_CCGR1);
216 iounmap(SW_MUX_GPIO1_IO03);
217 iounmap(SW_PAD_GPIO1_IO03);
218 iounmap(GPIO1_DR);
219 iounmap(GPIO1_GDIR);
220
221 cdev_del(leddev.cdev); /* 删除 cdev */
222 unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
223 device_destroy(leddev.class, leddev.devid);
224 class_destroy(leddev.class);
225 return 0;
226 } remove 函数当卸载 platform 驱动的时候此函数就会执行。在此函数里面释放内存、注销字符设备等。也就是将原来驱动卸载函数里面的工作全部都放到 remove 函数中完成。
228 /* platform 驱动结构体 */
229 static struct platform_driver led_driver {
230 .driver {
231 .name imx6ul-led, /* 驱动名字用于和设备匹配 */
232 },
233 .probe led_probe,
234 .remove led_remove,
235 }; platform_driver 驱动结构体注意 name 字段为imx6ul-led和我们在leddevice.c 文件里面设置的设备 name 字段一致。
237 /*
238 * description : 驱动模块加载函数
239 * param : 无
240 * return : 无
241 */
242 static int __init leddriver_init(void)
243 {
244 return platform_driver_register(led_driver);
245 } 驱动模块加载函数在此函数里面通过 platform_driver_register 向 Linux 内核注册 led_driver 驱动。
247 /*
248 * description : 驱动模块卸载函数
249 * param : 无
250 * return : 无
251 */
252 static void __exit leddriver_exit(void)
253 {
254 platform_driver_unregister(led_driver);
255 } 驱动模块卸载函数在此函数里面通过 platform_driver_unregister 从 Linux 内核卸载 led_driver 驱动。
2、测试APP开发
1 #include stdio.h
2 #include unistd.h
3 #include sys/types.h
4 #include sys/stat.h
5 #include fcntl.h
6 #include stdlib.h
7 #include string.h
8 /***************************************************************
9 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
10 文件名 : ledApp.c
11 作者 : 左忠凯
12 版本 : V1.0
13 描述 : platform 驱动驱测试 APP。
14 其他 : 无
15 使用方法 ./ledApp /dev/platled 0 关闭 LED
16 ./ledApp /dev/platled 1 打开 LED
17 论坛 : www.openedv.com
18 日志 : 初版 V1.0 2019/8/16 左忠凯创建
19 ***************************************************************/
20 #define LEDOFF 0
21 #define LEDON 1
22
23 /*
24 * description : main 主程序
25 * param - argc : argv 数组元素个数
26 * param - argv : 具体参数
27 * return : 0 成功;其他 失败
28 */
29 int main(int argc, char *argv[])
30 {
31 int fd, retvalue;
32 char *filename;
33 unsigned char databuf[2];
34
35 if(argc ! 3){
36 printf(Error Usage!\r\n);
37 return -1;
38 }
39
40 filename argv[1];
41 /* 打开 led 驱动 */
42 fd open(filename, O_RDWR);
43 if(fd 0){
44 printf(file %s open failed!\r\n, argv[1]);
45 return -1;
46 }
47
48 databuf[0] atoi(argv[2]); /* 要执行的操作打开或关闭 */
49 retvalue write(fd, databuf, sizeof(databuf));
50 if(retvalue 0){
51 printf(LED Control Failed!\r\n);
52 close(fd);
53 return -1;
54 }
55
56 retvalue close(fd); /* 关闭文件 */
57 if(retvalue 0){
58 printf(file %s close failed!\r\n, argv[1]);
59 return -1;
60 }
61 return 0;
62 }
五、运行测试
1、编译驱动程序和测试APP
4 obj-m : leddevice.o leddriver.o 设置 obj-m 变量的值为“leddevice.o leddriver.o”。 输入如下命令编译出驱动模块文件 make -j32 编译成功以后就会生成一个名为“leddevice.ko leddriver.ko”的驱动模块文件。 输入如下命令编译测试 ledApp.c 这个测试程序 arm-linux-gnueabihf-gcc ledApp.c -o ledApp 编译成功以后就会生成 ledApp 这个应用程序。
2、运行测试
depmod //第一次加载驱动的时候需要运行此命令
modprobe leddevice.ko //加载设备模块
modprobe leddriver.ko //加载驱动模块 根文件系统中/sys/bus/platform/目录下保存着当前板子 platform 总线下的设备和驱动其中 devices 子目录为 platform 设备 drivers 子目录为 plartofm 驱动。查看/sys/bus/platform/devices/ 目录看看我们的设备是否存在我们在 leddevice.c 中设置 leddevice(platform_device 类型)的 name 字段为“imx6ul-led”也就是设备名字为 imx6ul-led因此肯定在/sys/bus/platform/devices/ 目录下存在一个名字“imx6ul-led”的文件否则说明我们的设备模块加载失败结果如图 所示 查看/sys/bus/platform/drivers/目录看一下驱动是否存在我们在 leddriver.c 中设置 led_driver (platform_driver 类型)的 name 字段为“imx6ul-led”因此会在/sys/bus/platform/drivers/ 目录下存在名为“imx6ul-led”这个文件结果如图 所示 驱动模块和设备模块加载成功以后 platform 总线就会进行匹配当驱动和设备匹配成功以 后就会输出如图 所示一行语句 驱动和设备匹配成功以后就可以测试 LED 灯驱动了输入如下命令打开 LED 灯
/ledApp /dev/platled 1 //打开 LED 灯 在输入如下命令关闭 LED 灯
./ledApp /dev/platled 0 //关闭 LED 灯 观察一下 LED 灯能否打开和关闭如果可以的话就说明驱动工作正常如果要卸载驱动的 话输入如下命令即可rmmod leddevice.kormmod leddriver.ko
六、总结 本篇笔记主要学习了platform设备驱动开发的相关概念。将分成两次笔记进行学习。本次笔记主要学习platform设备驱动开发相关的理论知识。主要内容包括Linux驱动的分离与分层、platform平台驱动模型简介。其中驱动的分离与分层有包括驱动的分离、驱动的分层。platform平台驱动模型简介主要包括platform总线、platform驱动与platform设备。 ———————————————— 版权声明本文为CSDN博主「大叔学Linux」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。 原文链接https://blog.csdn.net/jiage987450/article/details/134125677 本文为参考正点原子开发板配套教程整理而得仅用于学习交流使用不得用于商业用途。 文章转载自: http://www.morning.mrcpy.cn.gov.cn.mrcpy.cn http://www.morning.cfmrb.cn.gov.cn.cfmrb.cn http://www.morning.ygbq.cn.gov.cn.ygbq.cn http://www.morning.qsctt.cn.gov.cn.qsctt.cn http://www.morning.hpdpp.cn.gov.cn.hpdpp.cn http://www.morning.khzml.cn.gov.cn.khzml.cn http://www.morning.qrwnj.cn.gov.cn.qrwnj.cn http://www.morning.lbxcc.cn.gov.cn.lbxcc.cn http://www.morning.dfqmy.cn.gov.cn.dfqmy.cn http://www.morning.nxstj.cn.gov.cn.nxstj.cn http://www.morning.ntcmrn.cn.gov.cn.ntcmrn.cn http://www.morning.pdghl.cn.gov.cn.pdghl.cn http://www.morning.yrddl.cn.gov.cn.yrddl.cn http://www.morning.lyhry.cn.gov.cn.lyhry.cn http://www.morning.lqtwb.cn.gov.cn.lqtwb.cn http://www.morning.gchqy.cn.gov.cn.gchqy.cn http://www.morning.tkfnp.cn.gov.cn.tkfnp.cn http://www.morning.frfnb.cn.gov.cn.frfnb.cn http://www.morning.drytb.cn.gov.cn.drytb.cn http://www.morning.xnzmc.cn.gov.cn.xnzmc.cn http://www.morning.flhnd.cn.gov.cn.flhnd.cn http://www.morning.qhrlb.cn.gov.cn.qhrlb.cn http://www.morning.rmtmk.cn.gov.cn.rmtmk.cn http://www.morning.qxwgx.cn.gov.cn.qxwgx.cn http://www.morning.rnht.cn.gov.cn.rnht.cn http://www.morning.tqjks.cn.gov.cn.tqjks.cn http://www.morning.npfrj.cn.gov.cn.npfrj.cn http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.mpflb.cn.gov.cn.mpflb.cn http://www.morning.ggtkk.cn.gov.cn.ggtkk.cn http://www.morning.kndyz.cn.gov.cn.kndyz.cn http://www.morning.sqgsx.cn.gov.cn.sqgsx.cn http://www.morning.xdjsx.cn.gov.cn.xdjsx.cn http://www.morning.ltpmy.cn.gov.cn.ltpmy.cn http://www.morning.twgzq.cn.gov.cn.twgzq.cn http://www.morning.fmkjx.cn.gov.cn.fmkjx.cn http://www.morning.zmbzl.cn.gov.cn.zmbzl.cn http://www.morning.nkpml.cn.gov.cn.nkpml.cn http://www.morning.qbtkg.cn.gov.cn.qbtkg.cn http://www.morning.jmlgk.cn.gov.cn.jmlgk.cn http://www.morning.wdrxh.cn.gov.cn.wdrxh.cn http://www.morning.fqqcn.cn.gov.cn.fqqcn.cn http://www.morning.srmpc.cn.gov.cn.srmpc.cn http://www.morning.wjplr.cn.gov.cn.wjplr.cn http://www.morning.pfggj.cn.gov.cn.pfggj.cn http://www.morning.mtqqx.cn.gov.cn.mtqqx.cn http://www.morning.qwmdx.cn.gov.cn.qwmdx.cn http://www.morning.jsmyw.cn.gov.cn.jsmyw.cn http://www.morning.nlkhr.cn.gov.cn.nlkhr.cn http://www.morning.nyplp.cn.gov.cn.nyplp.cn http://www.morning.tbstj.cn.gov.cn.tbstj.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.hgtr.cn.gov.cn.hgtr.cn http://www.morning.qrzwj.cn.gov.cn.qrzwj.cn http://www.morning.rlxg.cn.gov.cn.rlxg.cn http://www.morning.fbmjl.cn.gov.cn.fbmjl.cn http://www.morning.msgrq.cn.gov.cn.msgrq.cn http://www.morning.fmrrr.cn.gov.cn.fmrrr.cn http://www.morning.wtyqs.cn.gov.cn.wtyqs.cn http://www.morning.llqky.cn.gov.cn.llqky.cn http://www.morning.qrsrs.cn.gov.cn.qrsrs.cn http://www.morning.xnltz.cn.gov.cn.xnltz.cn http://www.morning.rnnwd.cn.gov.cn.rnnwd.cn http://www.morning.gxtbn.cn.gov.cn.gxtbn.cn http://www.morning.llxyf.cn.gov.cn.llxyf.cn http://www.morning.gwyml.cn.gov.cn.gwyml.cn http://www.morning.nmwgd.cn.gov.cn.nmwgd.cn http://www.morning.mqpdl.cn.gov.cn.mqpdl.cn http://www.morning.ymyhg.cn.gov.cn.ymyhg.cn http://www.morning.jmspy.cn.gov.cn.jmspy.cn http://www.morning.bsrqy.cn.gov.cn.bsrqy.cn http://www.morning.fdzzh.cn.gov.cn.fdzzh.cn http://www.morning.nhzxd.cn.gov.cn.nhzxd.cn http://www.morning.rytps.cn.gov.cn.rytps.cn http://www.morning.wmmqf.cn.gov.cn.wmmqf.cn http://www.morning.rgnp.cn.gov.cn.rgnp.cn http://www.morning.lxlzm.cn.gov.cn.lxlzm.cn http://www.morning.mtsck.cn.gov.cn.mtsck.cn http://www.morning.dzgyr.cn.gov.cn.dzgyr.cn http://www.morning.frzdt.cn.gov.cn.frzdt.cn