以下内容源于朱有鹏《物联网大讲堂》课程的学习,如有侵权,请告知删除。

一、板载蜂鸣器驱动测试

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类设备与蜂鸣器驱动相关推荐

  1. Linux驱动框架之misc类设备驱动框架

    1.何为misc设备 (1)misc中文名就是杂项设备\杂散设备,因为现在的硬件设备多种多样,有好些设备不好对他们进行一个单独的分类,所以就将这些设备全部归属于 杂散设备,也就是misc设备,例如像a ...

  2. misc类设备驱动2——misc类设备的简介

    以下内容源于朱有鹏嵌入式课程的学习与整理,如有其侵权请告知删除. 一.misc类设备的含义 1.名字含义 misc是英文Miscellaneous的缩写,中文意思是"杂项.混杂", ...

  3. linux驱动 — switch_dev类设备的使用

    前言 在项目中碰到有人用switch_dev_register注册了switch_dev类设备,并且应用层能读到它的状态信息,感觉挺好奇,于是网上搜了些资料,自个又琢磨了一下,算是理解了,现在整理一下 ...

  4. Linux驱动(14)--字符类设备与驱动

    字符类设备 1. 静态申请字符类设备号 1.1 所需函数与头文件 1.2 源码与注释 1.3 运行结果 2. 动态申请字符类设备号 2.1 所需函数与头文件 2.2 源码与注释 2.3 运行结果 3. ...

  5. Misc杂项设备驱动框架

    Misc杂项设备驱动框架 由于设备号比较紧张,所以一些不相关的设备可以使用同一个主设备号,不同的次设备号.主设备号通常是10. 杂项设备结构体 struct miscdevice {int minor ...

  6. 4412 字符类设备的设备号

    一.静态申请字符类设备号 字符类设备函数在文件"include/linux/fs.h"中 内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev ...

  7. 十五、linux 注册字符类设备和生成节点

    一. 注册字符类设备 • 分配内存空间函数kmalloc         – 分配连续的虚拟地址,用于小内存分配.在include/linux/slab.h文件中.         – 参数1:申请的 ...

  8. Linux设备模型组件-类设备-设备类及subsystem

    Linux设备模型   一.sysfs文件系统: sysfs文件系统是Linux2.6内核引入的,它被看成是与proc.devfs和devpty等同类别的文件系统,sysfs文件系统也是一个虚拟文件系 ...

  9. ARM(IMX6U)裸机C语言蜂鸣器驱动实验(BSP+SDK)

    参考:Linux之ARM(IMX6U)裸机C语言蜂鸣器驱动实验–驱动编写,编译 作者:一只青木呀 发布时间: 2020-08-16 14:47:23 网址:https://blog.csdn.net/ ...

最新文章

  1. 聊聊Mysql的那些破事儿
  2. Android BaseAdapter 例子
  3. 软考-信息系统项目管理师-信息系统安全管理
  4. 严重红色警告-虾子+维C=砒霜
  5. org.apache.hadoop.hive.metastore.api.SerDeInfo; local class incompatible
  6. Error:scalac: Error: scala.collection.immutable.$colon$colon.tl$1()Lscala/collection/immutable/List;
  7. python数字字符串乘以2_Python基础(2)_数字和字符串类型
  8. linux shell sql赋值,Linux下shell执行SQL
  9. 【linux】Permission denied (publickey) SSH用户名密码登录报错
  10. 学校网络安全事故救助机制初探
  11. python类之间传参_没看懂这11 条,别说你精通 Python 装饰器
  12. [新功能]文章预览功能
  13. Windows Server 2012 R2 Update 64位 MSDN原版
  14. 14款超实用的Unity3D常用插件推荐
  15. watir学习系列--对话框处理
  16. python+django+mysql多用户B2C商城系统毕业设计毕设开题报告
  17. 深度学习中的多任务学习介绍
  18. 二十余岁时的社会观(三)
  19. 【毕设选题】基于STM32的毕业设计题目项目汇总 - 350例
  20. 计算机合成音乐的交换标准,音乐合成器

热门文章

  1. BZOJ 3329: Xorequ(数位dp+递推)
  2. 实习期间的一些思考整理(3)2018.4.12~4.13
  3. 通过取父级for循环的i来理解闭包,iife,匿名函数
  4. 杂记-字符串的字节长度
  5. STRUTS2 标签调用静态方法
  6. “电脑人才”是怎么炼成的
  7. 告诉你银行在年底为存储做的小动作
  8. Unity AI副总裁Danny Lange:如何用AI助推游戏行业?
  9. Andorid Scrolling Activity(CoordinatorLayout详情)
  10. Autowire异常