日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

misc类设备与蜂鸣器驱动

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 misc类设备与蜂鸣器驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以下內容源于朱有鵬《物聯網大講堂》課程的學習,如有侵權,請告知刪除。


一、板載蜂鳴器驅動測試

1、驅動部分

(1)九鼎移植內核已經提供了蜂鳴器驅動源碼,但如何查找是否已經有驅動文件?

  • 法一,在源碼文件集合中搜索關鍵字buzzer,x210-buzzer……
  • 法二,make menuconfig,然后查找關鍵字buzzer,知道路徑……


(2)是否被編譯?

  • 取決于Makefile文件中的宏:obj-$(CONFIG_X210_BUZZER_DRIVER) += x210-buzzer.o;
  • 而宏又取決于Kconfig文件中的項目(X210_BUZZER_DRIVER)是否顯示“y”;
  • 而Kconfig文件中的項目是否顯示“y”,是通過make menuconfig來配置的(路徑和源碼文件的路徑基本一致的)。

(3)bug排查

  • 修改Makefile中的宏名(將CONFIG_BUZZER_DRIVER改為CONFIG_X210_BUZZER_DRIVER,因為Makefile中的要和Kconfig中的對應(make menuconfig是以Kconfig的為準的,配置后可以在.config文件中看到CONFIG_X210_BUZZER_DRIVER是“y”),最終可以在系統中看到/dev/buzzer

2、應用部分

(1)應用編寫

  • 先查看自己編寫的驅動文件x210_buzzer.c,看都有哪些操作:打開文件+ioctl;然后針對地編寫應用。

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/poll.h> #include <asm/irq.h> #include <asm/io.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include <mach/hardware.h> #include <plat/regs-timer.h> #include <mach/regs-irq.h> #include <asm/mach/time.h> #include <linux/clk.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/miscdevice.h>#include <linux/gpio.h>#include <plat/gpio-cfg.h> //#include <plat/regs-clock.h> //#include <plat/regs-gpio.h>//#include <plat/gpio-bank-e.h> //#include <plat/gpio-bank-f.h> //#include <plat/gpio-bank-k.h>#define DEVICE_NAME "buzzer"#define PWM_IOCTL_SET_FREQ 1 #define PWM_IOCTL_STOP 0static struct semaphore lock;// TCFG0在Uboot中設置,這里不再重復設置 // Timer0輸入頻率Finput=pclk/(prescaler1+1)/MUX1 // =66M/16/16 // TCFG0 = tcnt = (pclk/16/16)/freq; // PWM0輸出頻率Foutput =Finput/TCFG0= freq static void PWM_Set_Freq( unsigned long freq ) {unsigned long tcon;unsigned long tcnt;unsigned long tcfg1;struct clk *clk_p;unsigned long pclk;//unsigned tmp;//設置GPD0_2為PWM輸出s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(2));tcon = __raw_readl(S3C2410_TCON);tcfg1 = __raw_readl(S3C2410_TCFG1);//mux = 1/16tcfg1 &= ~(0xf<<8);tcfg1 |= (0x4<<8);__raw_writel(tcfg1, S3C2410_TCFG1);clk_p = clk_get(NULL, "pclk");pclk = clk_get_rate(clk_p);tcnt = (pclk/16/16)/freq;__raw_writel(tcnt, S3C2410_TCNTB(2));__raw_writel(tcnt/2, S3C2410_TCMPB(2));//占空比為50%tcon &= ~(0xf<<12);tcon |= (0xb<<12); //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0__raw_writel(tcon, S3C2410_TCON);tcon &= ~(2<<12); //clear manual update bit__raw_writel(tcon, S3C2410_TCON); }void PWM_Stop( void ) {//將GPD0_2設置為inputs3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(0)); }static int x210_pwm_open(struct inode *inode, struct file *file) {if (!down_trylock(&lock))return 0;elsereturn -EBUSY;}static int x210_pwm_close(struct inode *inode, struct file *file) {up(&lock);return 0; }// PWM:GPF14->PWM0 static int x210_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {switch (cmd) {case PWM_IOCTL_SET_FREQ://printk("PWM_IOCTL_SET_FREQ:\r\n");if (arg == 0)return -EINVAL;PWM_Set_Freq(arg);break;case PWM_IOCTL_STOP:default:printk("PWM_IOCTL_STOP:\r\n");PWM_Stop();break;}return 0; }static struct file_operations dev_fops = {.owner = THIS_MODULE,.open = x210_pwm_open,.release = x210_pwm_close, .ioctl = x210_pwm_ioctl, };static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops, };static int __init dev_init(void) {int ret;init_MUTEX(&lock);ret = misc_register(&misc);/* GPD0_2 (PWMTOUT2) */ret = gpio_request(S5PV210_GPD0(2), "GPD0");if(ret)printk("buzzer-x210: request gpio GPD0(2) fail");s3c_gpio_setpull(S5PV210_GPD0(2), S3C_GPIO_PULL_UP);s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(1));gpio_set_value(S5PV210_GPD0(2), 0);printk ("x210 "DEVICE_NAME" initialized\n");return ret; }static void __exit dev_exit(void) {misc_deregister(&misc); }module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("www.9tripod.com"); MODULE_DESCRIPTION("x210 PWM Driver");

(2)測試實踐

  • 編寫完下面的app_buzzer.c后,執行 arm-linux-gcc app_buzzer.c -o app.buzzer;
  • 然后將app.buzzer拷貝到開發板根文件系統下,最后./app.buzzer執行。
  • 注意,必須將buzzer編譯進內核才能如此操作!

#include <stdio.h> #include <sys/stat.h> #include <fcntl.h>#define DEVNAME "/dev/buzzer" //蜂鳴器對應的設備文件#define PWM_IOCTL_SET_FREQ 1 //命令來自驅動文件,應用層知道這些宏的含義 #define PWM_IOCTL_STOP 0int main(void) {int fd = -1;fd = open(DEVNAME, O_RDWR);if (fd < 0){perror("open");return -1;}ioctl(fd, PWM_IOCTL_SET_FREQ, 10000);sleep(3);ioctl(fd, PWM_IOCTL_STOP);sleep(3);ioctl(fd, PWM_IOCTL_SET_FREQ, 3000);sleep(3);ioctl(fd, PWM_IOCTL_STOP);sleep(3);close(fd);return 0; }


二、misc類設備介紹

1、何為misc?

(1)中文名:雜項設備\雜散設備,不明確的分類。

(2)在/sys/class/misc目錄下。

(3)都屬于字符設備。

(4)有一套驅動框架,內核實現一部分(misc.c),驅動實現一部分(x210-buzzer.c)

(5)misc是對原始的字符設備注冊接口的一個類層次的封裝,很多典型字符設備都可以歸類到misc類中,使用misc驅動框架來管理。

(6)這些字符設備不符合預先確定的字符設備范疇

  • 所有這些設備采用主編號10,次設備號不一樣。它們一起歸于misc device,其實misc_register就是用主標號10調用register_chrdev()的。

2、misc類設備驅動架構

(1)內核開發者實現部分,關鍵點有2個

  • 一個是類的創建(因此驅動開發者不需要再創建類);
  • 一個是開放給驅動開發者的接口misc_deregister函數。

(2)具體設備驅動工程師實現部分

3、本部分學習方法

(1)蜂鳴器驅動源碼已有,分析為主;

(2)復習并驗證前面講的驅動框架的思維;

(3)開始注意一些細節。


三、misc驅動框架源碼分析1(內核開發者實現的部分)

1、misc源碼框架基礎

(1)在/driver/char/misc.c中。

(2)源碼框架本身也是一個模塊(因此可以實現裁剪),內核啟動時自動加載


  • 因此會在/sys/class目錄下創建misc子目錄,即misc這個類


(3)源碼框架的主要工作

  • 注冊miscc類;
  • 使用老接口注冊字符設備驅動(主設備號為10);
  • 開放device注冊的接口misc_register給驅動工程師。

2、misc類設備的注冊


(1)驅動工程師需要借助misc來加載自己的驅動時,只需要調用misc_register接口注冊自己的設備即可,其余均不用管。

(2)misc_list鏈表的作用

  • 內核定義了一個misc_list鏈表(static LIST_HEAD(misc_list);),用來記錄所有內核中注冊了的雜散類設備。
  • 當我們向內核注冊一個misc類設備時,內核就會向misc_list鏈表中insert一個節點。
  • 之前字符設備時,是固定大小(255)的數組。
  • 當使用cat /proc/misc打印出信息時,其實就是遍歷此鏈表。

#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)原式子:static LIST_HEAD(misc_list); 展開后:static struct list_head misc_list = { &(misc_list), &(misc_list) }//被初始化的內核鏈表

(3)主設備號和次設備號的作用和區分。

  • 主設備號,表示類;次設備號,表示某具體設備。


四、misc驅動框架源碼分析2(misc.c文件,內核開發者提供)

1、open函數分析



  • 最終還是會映射到x210_buzzer.c中的open函數。

2、misc在proc下的展現


3、內核互斥鎖

(1)何為互斥鎖?

  • 實現互斥訪問。類似于圖書館借書。

(2)定義:DEFINE_MUTEX

  • 解析方法同上面三2(2)

原式子:static DEFINE_MUTEX(misc_mtx);……


(3)上鎖mutex_lock和解鎖mutex_unlock

  • 要訪問某資源時,要給該資源上鎖;使用完后,要解鎖。
  • 當某進程想訪問已經被上鎖的資源時,會休眠,直到其他進程解鎖后此進程才能訪問該資源。類似于上廁所(休眠鎖、等待鎖)。




(4)內核防止競爭狀態的手段:原子訪問,自旋鎖、互斥鎖、信號量

  • 原子訪問主要用來做計數;如int count;count++(這個可能被打斷)
  • 自旋鎖后面講中斷會詳細講;應用于多核心。
  • 互斥鎖和信號量很相似(其實就是計數值為1的信號量),互斥鎖的出現比信號量晚,實現上比信號量優秀,盡量使用互斥鎖。


五、蜂鳴器驅動源碼分析1

1、dev_init


(1)信號量

  • init_MUTEX(&lock);//將信號量初始化為1,其示就是互斥鎖

(2)miscdevice

static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,//動態次設備號.name = DEVICE_NAME,.fops = &dev_fops, };

(3)gpio_request

(4)printk

2、ioctl


(1)為什么需要ioctl(input output control,輸入輸出控制)?

  • 這個函數讓設備進行輸入輸出,但為何不用read和write?(因為read和write有缺陷,驅動和應用的交互有麻煩。)
  • 缺陷:寫驅動的人定義亮滅,但應用層的人怎么知道呢?

(2)ioctl怎么用


六、蜂鳴器驅動源碼分析2

硬件操作有關的代碼



總結

以上是生活随笔為你收集整理的misc类设备与蜂鸣器驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。