国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 879|回復: 0
打印 上一主題 下一主題

迅為IMX6ULL開發(fā)板Linux蜂鳴器實驗

[復制鏈接]
跳轉到指定樓層
樓主
發(fā)表于 2020-8-14 11:41:19 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
在上一章講解了添加 LED 燈驅動的整個流程和測試結果,這一章在來看一下蜂鳴器的驅動,蜂鳴器和
LED 燈的驅動其實是一樣的,都是控制 GPIO 引腳輸出高低電平,在本章繼續(xù)學習一下蜂鳴器的驅動,也算
是在鞏固一遍驅動的添加流程。
37.1 蜂鳴器設備注冊流程 蜂鳴器設備注冊流程
和 LED 燈驅動注冊一樣,蜂鳴器注冊流程也分為下面幾步:
5 硬件原理圖分析,確定控制 LED 的 GPIO 信息。
6 根據(jù) GPIO 信息在設備樹文件中添加 pinctrl 信息
7 在設備樹中創(chuàng)建 LED 的設備節(jié)點,并加入 GPIO 信息
8 編寫 LED 設備驅動程序
接下來根據(jù)上面這四步來添加一下蜂鳴器的設備驅動。
2 37.2 蜂鳴器硬件原理圖分析

蜂鳴器一端接 VSYS 電壓(3.3V),另一端接控制引腳,只不過多了一個三極管。控制引腳為:SNVS_TAMPER1。
3 37.3 修改設備樹文件 修改設備樹文件
37.3.1  添加 pinctrl  信息
在 i.MX6UL 終結者開發(fā)板中使用 SNVS_TAMPER1 這個引腳來控制蜂鳴器設備。打開 topeet_emmc_4_3.dts
文件在 iomux 節(jié)點的 imx6ul-evk 子節(jié)點下創(chuàng)建一個名為“pinctrl_beep”的子節(jié)點,具體內容如下:
pinctrl_beep: gpio-beep {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x10B0 /* beep */
>;
};
在 pinctrl_beep 節(jié)點中,將 SNVS_TAMPER1 引腳復用為 GPIO5_IO01,宏定義
MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 在 arch/arm/boot/dts/imx6ull-pinfunc-snvs.h 文件中。
37.3.2  添加 beep  設備節(jié)點
在 topeet_emmc_4_3.dts 文件下,在根節(jié)點“/”下創(chuàng)建 LED 節(jié)點,節(jié)點名為“beep”,具體內容如下:
1 beep {
2 #address-cells = <1>;
3 #size-cells = <1>;
4 compatible = "beep";
5 pinctrl-names = "default";
6 pinctrl-0 = <&pinctrl_beep>;
7 beep-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
8 status = "okay";
9 };
第 6 行,pinctrl-0 屬性設置蜂鳴器所使用的 GPIO 對應的 pinctrl 節(jié)點。
第 7 行,beep-gpio 屬性指定了蜂鳴器所使用的 GPIO。
接下來就是檢查蜂鳴器使用的GPIO引腳SNVS_TAMPER1有沒有被其他pinctrl節(jié)點使用,在檢查GPIO5_IO01
這個 GPIO 有沒有被其他外設使用,如果有的話都屏蔽掉。
設備樹編寫完成以后使用“make dtbs”命令重新編譯設備樹,然后使用新編譯出來的 topeet_emmc_4_3.dtb
文件啟動 Linux 系統(tǒng)。啟動成功以后進入“/proc/device-tree”目錄中查看“beep”節(jié)點是否存在,如果存
在的話就說明設備樹基本修改成功(具體作用還要驅動驗證),結果如下圖所示:

37.4 編寫蜂鳴器驅動程序 編寫蜂鳴器驅動程序
本實驗例程路徑:i.MX6UL 終結者光盤資料/06_Linux 驅動例程/03_beep
蜂鳴器的驅動程序和 LED 的驅動程序基本一致,創(chuàng)建 beep.c 文件。具體內容如下:
1 #include
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
18 #define BEEP_CNT 1 /* 設備號個數(shù) */
19 #define BEEP_NAME "beep" /* 名字 */
20 #define BEEPOFF 0 /* 關蜂鳴器 */
21 #define BEEPON 1 /* 開蜂鳴器 */
22
23
24 /* beep 設備結構體 */
25 struct beep_dev{
26 dev_t devid; /* 設備號 */
27 struct cdev cdev; /* cdev */
28 struct class *class; /* 類 */
29 struct device *device; /* 設備 */
30 int major; /* 主設備號 */
31 int minor; /* 次設備號 */
32 struct device_node *nd; /* 設備節(jié)點 */
33 int beep_gpio; /* beep 所使用的 GPIO 編號 */
34 };
35
36 struct beep_dev beep; /* beep 設備 */
37
38 /*
39 * @description : 打開設備
40 * @param – inode : 傳遞給驅動的 inode
41 * @param - filp : 設備文件,file 結構體有個叫做 private_data 的成員變量
42 * 一般在 open 的時候將 private_data 指向設備結構體。
43 * @return : 0 成功;其他 失敗
44 */
45 static int beep_open(struct inode *inode, struct file *filp)
46 {
47 filp->private_data = &beep; /* 設置私有數(shù)據(jù) */
48 return 0;
49 }
50
51 /*
52 * @description : 向設備寫數(shù)據(jù)
53 * @param - filp : 設備文件,表示打開的文件描述符
54 * @param - buf : 要寫給設備寫入的數(shù)據(jù)
55 * @param - cnt : 要寫入的數(shù)據(jù)長度
56 * @param - offt : 相對于文件首地址的偏移
57 * @return : 寫入的字節(jié)數(shù),如果為負值,表示寫入失敗
58 */
59 static ssize_t beep_write(struct file *filp, const char __user *buf,
60 size_t cnt, loff_t *offt)
61 {
62 int retvalue;
63 unsigned char databuf[1];
64 unsigned char beepstat;
65 struct beep_dev *dev = filp->private_data;
66
67 retvalue = copy_from_user(databuf, buf, cnt);
68 if(retvalue < 0) {
69 printk("kernel write failed!\r\n");
70 return -EFAULT;
71 }
72
73 beepstat = databuf[0]; /* 獲取狀態(tài)值 */
74
75 if(beepstat == BEEPON) {
76 gpio_set_value(dev->beep_gpio, 1); /* 打開蜂鳴器 */
77 } else if(beepstat == BEEPOFF) {
78 gpio_set_value(dev->beep_gpio, 0); /* 關閉蜂鳴器 */
79 }
80 return 0;
81 }
82
83 /*
84 * @description : 關閉/釋放設備
85 * @param - filp : 要關閉的設備文件(文件描述符)
86 * @return : 0 成功;其他 失敗
87 */
88 static int beep_release(struct inode *inode, struct file *filp)
89 {
90 return 0;
91 }
92
93 /* 設備操作函數(shù) */
94 static struct file_operations beep_fops = {
95 .owner = THIS_MODULE,
96 .open = beep_open,
97 .write = beep_write,
98 .release = beep_release,
99 };
100
101 /*
102 * @description : 驅動入口函數(shù)
103 * @param : 無
104 * @return : 無
105 */
106 static int __init beep_init(void)
107 {
108 int ret = 0;
109
110 /* 設置 BEEP 所使用的 GPIO */
111 /* 1、獲取設備節(jié)點:beep */
112 beep.nd = of_find_node_by_path("/beep");
113 if(beep.nd == NULL) {
114 printk("beep node not find!\r\n");
115 return -EINVAL;
116 } else {
117 printk("beep node find!\r\n");
118 }
119
120 /* 2、 獲取設備樹中的 gpio 屬性,得到 BEEP 所使用的 GPIO 編號 */
121 beep.beep_gpio = of_get_named_gpio(beep.nd, "beep-gpio", 0);
122 if(beep.beep_gpio < 0) {
123 printk("can't get beep-gpio");
124 return -EINVAL;
125 }
126 printk("led-gpio num = %d\r\n", beep.beep_gpio);
127
128 /* 3、設置 GPIO5_IO01 為輸出,并且輸出低電平,默認關閉 BEEP */
129 ret = gpio_direction_output(beep.beep_gpio, 0);
130 if(ret < 0) {
131 printk("can't set gpio!\r\n");
132 }
133
134 /* 注冊字符設備驅動 */
135 /* 1、創(chuàng)建設備號 */
136 if (beep.major) { /* 定義了設備號 */
137 beep.devid = MKDEV(beep.major, 0);
138 register_chrdev_region(beep.devid, BEEP_CNT, BEEP_NAME);
139 } else { /* 沒有定義設備號 */
140 alloc_chrdev_region(&beep.devid, 0, BEEP_CNT, BEEP_NAME);
141 beep.major = MAJOR(beep.devid); /* 獲取分配號的主設備號 */
142 beep.minor = MINOR(beep.devid); /* 獲取分配號的次設備號 */
143 }
144 printk("beep major=%d,minor=%d\r\n",beep.major, beep.minor);
145
146 /* 2、初始化 cdev */
147 beep.cdev.owner = THIS_MODULE;
148 cdev_init(&beep.cdev, &beep_fops);
149
150 /* 3、添加一個 cdev */
151 cdev_add(&beep.cdev, beep.devid, BEEP_CNT);
152
153 /* 4、創(chuàng)建類 */
154 beep.class = class_create(THIS_MODULE, BEEP_NAME);
155 if (IS_ERR(beep.class)) {
156 return PTR_ERR(beep.class);
157 }
158
159 /* 5、創(chuàng)建設備 */
160 beep.device = device_create(beep.class, NULL, beep.devid, NULL,
161 BEEP_NAME);
162 if (IS_ERR(beep.device)) {
163 return PTR_ERR(beep.device);
164 }
165
166 return 0;
167 }
168
169 /*
170 * @description : 驅動出口函數(shù)
171 * @param : 無
172 * @return : 無
173 */
174 static void __exit beep_exit(void)
175 {
176 /* 注銷字符設備驅動 */
177 cdev_del(&beep.cdev); /* 刪除 cdev */
178 unregister_chrdev_region(beep.devid, BEEP_CNT); /* 注銷設備號 */
179
180 device_destroy(beep.class, beep.devid);
181 class_destroy(beep.class);
182 }
183
184 module_init(beep_init);
185 module_exit(beep_exit);
186 MODULE_LICENSE("GPL");
187 MODULE_AUTHOR("topeet");
5 37.5 編寫應用測試程序 編寫應用測試程序
創(chuàng)建應用測試程序 beep_test.c,內容如下:
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 #define BEEPOFF 0
10 #define BEEPON 1
11
12 /*
13 * @description : main 主程序
14 * @param - argc : argv 數(shù)組元素個數(shù)
15 * @param - argv : 具體參數(shù)
16 * @return : 0 成功;其他 失敗
17 */
18 int main(int argc, char *argv[])
19 {
20 int fd, retvalue;
21 char *filename;
22 unsigned char databuf[1];
23
24 if(argc != 3){
25 printf("Error Usage!\r\n");
26 return -1;
27 }
28
29 filename = argv[1];
30
31 /* 打開 beep 驅動 */
32 fd = open(filename, O_RDWR);
33 if(fd < 0){
34 printf("file %s open failed!\r\n", argv[1]);
35 return -1;
36 }
37
38 databuf[0] = atoi(argv[2]); /* 要執(zhí)行的操作:打開或關閉 */
39
40 /* 向/dev/beep 文件寫入數(shù)據(jù) */
41 retvalue = write(fd, databuf, sizeof(databuf));
42 if(retvalue < 0){
43 printf("BEEP Control Failed!\r\n");
44 close(fd);
45 return -1;
46 }
47
48 retvalue = close(fd); /* 關閉文件 */
49 if(retvalue < 0){
50 printf("file %s close failed!\r\n", argv[1]);
51 return -1;
52 }
53 return 0;
54 }
beep_test.c 的文件內容和 gpioled_test.c 的內容差不多,都是對文件的打開、關閉、寫操作。
6 37.6 編譯運行測試 編譯運行測試
37.6.1  編譯蜂鳴器驅動文件
同 LED 驅動文件一樣,創(chuàng)建 Makefile 文件,將 obj-m 的值改為 beep.o,Makefile 文件內容如下:
KERNELDIR := /home/topeet/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga
CURRENT_PATH := $(shell pwd)
obj-m := beep.o
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
首先我們在終端輸入兩個命令(設置兩個環(huán)境變量):
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
然后執(zhí)行“make”命令編譯模塊,編譯完成生成 beep.ko,如下圖所示:

37.6.2  編譯應用測試程序
輸入如下命令編譯應用測試程序:
arm-linux-gnueabihf-gcc -o beep_test beep_test.c
編譯完成后,會生成 beep_test 可執(zhí)行文件。如下圖所示:

37.6.3  運行測試
啟動開發(fā)板,將編譯好的 beep.ko 驅動模塊和 beep_test 應用測試文件拷貝到/lib/modules/4.1.15 目錄下(檢
查開發(fā)板根文件系統(tǒng)中有沒有“/lib/modules/4.1.15”這個目錄,如果沒有的話需要自行創(chuàng)建一下。開發(fā)板
中使用的是光盤資料里面提供的 busybox 文件系統(tǒng),光盤資料的“i.MX6UL 終結者光盤資料\08_開發(fā)板系統(tǒng)
鏡像\03_文件系統(tǒng)鏡像\01_Busybox 文件系統(tǒng)”目錄下)。輸入下面命令加載模塊:
depmod
modprobe beep
驅動加載成功后,顯示下面的信息:

然后使用應用測試程序來驗證一下驅動是否正確,輸入下面的命令打開蜂鳴器:
./beep_test /dev/beep 1 //打開蜂鳴器
查看開發(fā)板上的蜂鳴器是否有響聲,如果有鳴叫聲說明驅動正常工作。
然后輸入下面命令關閉蜂鳴器:
./beep_test /dev/beep 0 //關閉蜂鳴器
正常情況下,蜂鳴器停止鳴叫。
使用下面的命令卸載模塊:
rmmod beep //卸載模塊


您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 免费福利片 | 黄视频网站大全 | 少妇高潮太爽了在线视频 | 久久亚洲这里只有精品18 | 国产精品国产三级国产普通 | 高清一级毛片一本到免费观看 | 日韩中文字幕在线播放 | 欧美精品一区二区三区四区 | 免费国产不卡午夜福在线观看 | 免费理论片高清西瓜影院 | 精品一区二区三区中文 | 日日夜夜视频 | 日日摸日日 | 日本www色视频成人免费免费 | 四虎成人精品国产一区a | 日日夜夜摸 | 最好免费观看韩国+日本 | 午夜精品在线 | 亚洲 中文 欧美 日韩 在线人 | 99热在| 日本不卡免费高清一级视频 | 精品国精品国产自在久国产不卡 | 天天在线干 | 一级毛片特级毛片免费的 | 毛片女人毛片一级毛片毛片 | 四虎永久免费网站 | 亚洲精品视频在线观看免费 | 欧洲欧美人成在线视频免费下载 | 男女强吻摸下面揉免费 | 国产综合91| 微拍秒拍99福利精品小视频 | 欧美激情视频一区二区三区 | 免费看黄片毛片 | 日本xxxⅹ69xxxx护士 | 四虎sihu新版影院亚洲精品 | 91果冻制片厂天美传媒 | 在线免费观看日本 | 视频在线观看国产 | jizz日本在线观看 | 亚洲综合色婷婷在线观看 | 日韩精品一区二区三区 在线观看 |