S3C2440内核蜂鸣器驱动解读

发布时间:2024-08-21  

首先介绍需要的一些头文件的位置


linux-2.6.32.内核重要文件目录:

linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach/regs-gpio.h

linux-2.6.32.2/arch/arm/plat-s3c24xx/gpio.c

linux-2.6.32.2/linux/asm-generic/io.h

linux-2.6.32.2/include/linux/wait.h

asm -- linux-2.6.32.2/linux/asm-generic

mach -- linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach

plat -- linux-2.6.32.2/arch/arm/plat-s3c24xx/include/plat

-- linux-2.6.32.2/arch/arm/plat/include/plat


1、2440蜂鸣器内核驱动

展示内核驱动


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#include

#include

#include

#include

#include

 

#include

#include


static int beep_major = 0;

module_param(beep_major, int, 0);//传参函数,并在模块目录下会生成parameter目录及参数文件

/*

MODULE_AUTHOR ( 声明谁编写了模块 ),

MODULE_DESCRIPION( 一个人可读的关于模块做什么的声明 ),

MODULE_VERSION ( 一个代码修订版本号; 看 的注释以便知道创建版本字串使用的惯例),

MODULE_ALIAS ( 模块为人所知的另一个名字 ), 以及 MODULE_DEVICE_TABLE ( 来告知用户空间, 模块支持那些设备 ). 

MODULE_LICENSE(“GPL”);

内核认识的特定许可有, “GPL”( 适用 GNU 通用公共许可的任何版本 ), “GPL v2”( 只适用 GPL 版本 2 ), “GPL and additional rights”, “Dual BSD/GPL”, “Dual MPL/GPL”, 和 “Proprietary”. 除非你的模块明确标识是在内核认识的一个自由许可下, 否则就假定它是私有的

*/

MODULE_AUTHOR('All');

MODULE_LICENSE('Dual BSD/GPL');


#define BEEP_MAGIC 'b'

#define BEEP_START_CMD _IO (BEEP_MAGIC, 1)//使用内核函数库提供的_IO函数,最后参考文献详细查看

#define BEEP_STOP_CMD _IO (BEEP_MAGIC, 2)


/*

 * Open the device; in fact, there's nothing to do here.

 */

int beep_open (struct inode *inode, struct file *filp)

{

return 0;

}


ssize_t beep_read(struct file *file, char __user *buff, size_t count, loff_t *offp)

{

return 0;

}


ssize_t beep_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)

{

return 0;

}

//一般像read、write一般这些函数不会写什么内容,open有时候会放入初始化函数


/*

使用s3c2410_gpio_cfgpin函数初始化端口,设置为输出,s3c2410_gpio_setpin设置端口输出高低电压,对着开发手册进行设置自己所需要的输出电压。s3c2410_gpio_pullup控制上拉电阻。

*/

void beep_stop( void )

{

//set GPB0 as output

s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);

s3c2410_gpio_setpin(S3C2410_GPB(0),0);

}


void beep_start( void )

{

//set GPB0 as output

s3c2410_gpio_pullup(S3C2410_GPB(0),1);

s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);

s3c2410_gpio_setpin(S3C2410_GPB(0),1);

}


/*函数调用,使用ioctl可以通过不同的cmd数,选择所调用的内核函数*/

static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

//add your src HERE!!!

switch ( cmd ) {

case BEEP_START_CMD: {

beep_start(); break;

}

case BEEP_STOP_CMD: {

beep_stop(); break;

}

default: {

break;

}

}

return 0;


}


static int beep_release(struct inode *node, struct file *file)

{

return 0;

}


/*

 * Set up the cdev structure for a device.

 */

static void beep_setup_cdev(struct cdev *dev, int minor,

struct file_operations *fops)

{

int err, devno = MKDEV(beep_major, minor);

    

cdev_init(dev, fops);

    //注册设备,或者应该说是初始化

dev->owner = THIS_MODULE;

dev->ops = fops;

err = cdev_add (dev, devno, 1);

    //向内核添加设备失败,linux-2.6之后使用者两个函数进行注册和添加

if (err)

printk (KERN_NOTICE 'Error %d adding beep%d', err, minor);

}


 /*

 file_operations结构体

 Linux使用file_operations结构访问驱动程序的函数,这个结构的每一个成员的名字都对应着一个函数调用。

  用户进程利用在对设备文件进行诸如read/write操作的时候,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数,这是Linux的设备驱动程序工作的基本原理。

  struct module *owner

  第一个 file_operations 成员根本不是一个操作,它是一个指向拥有这个结构的模块的指针。这个成员用来在它的操作还在被使用时阻止模块被卸载. 几乎所有时间中, 它被简单初始化为 THIS_MODULE, 一个在 中定义的宏.这个宏比较复杂,在进行简单学习操作的时候,一般初始化为THIS_MODULE。

https://blog.csdn.net/zqixiao_09/article/details/50850475

*/

static struct file_operations beep_remap_ops = {

.owner   = THIS_MODULE,

.open    = beep_open,

.release = beep_release,

.read    = beep_read,

.write   = beep_write,

.ioctl   = beep_ioctl,

};


/*

 * There's no need for us to maintain any

 * special housekeeping info, so we just deal with raw cdevs.

 */

static struct cdev BeepDevs;


/*

 * Module housekeeping.

 */

/*beep_init函数主要用于获取设备号,用于内核识别*/

static int beep_init(void)

{

int result;

dev_t dev = MKDEV(beep_major, 0);

    //格式转换,beep_major是主设备号,这里是靠调用驱动时的传参,默认为0 

char dev_name[]='beep';


/* Figure out our device number. */

if (beep_major)

result = register_chrdev_region(dev, 1, dev_name);

    //手动分配注册设备号,如果之前没有分配设备号,beep_major为0因此调用动态分配设备号进行注册,但是内核分配后beep_major不为0,就会调用该函数,也就是说知道主设备号才来使用该函数

else {

result = alloc_chrdev_region(&dev, 0, 1, dev_name);

beep_major = MAJOR(dev);

    //动态分配注册设备号,并更新主设备号,详细查看https://blog.csdn.net/welbell_uplooking/article/details/83654312

}

if (result < 0) {

printk(KERN_WARNING 'beep: unable to get major %dn', beep_major);

return result;

}

if (beep_major == 0)

beep_major = result;


/* Now set up cdev. */

beep_setup_cdev(&BeepDevs, 0, &beep_remap_ops);

printk('beep device installed, with major %dn', beep_major);

printk('The device name is: %sn', dev_name);

return 0;

}



static void beep_cleanup(void)

{

cdev_del(&BeepDevs);

    //注销设备,删除一个cdev

unregister_chrdev_region(MKDEV(beep_major, 0), 1);

    //释放注销的所占用的设备号

printk('beep device uninstalledn');

}



module_init(beep_init);

module_exit(beep_cleanup);

//驱动加载系统传参

EXPORT_SYMBOL(beep_major);



加载驱动模块


insmod beep_dev.ko


创建dev下面beep设备文件与我们的beep_dev驱动绑定


mknod /dev/beep c 251 0


原命令形式:mknod /dev/node_name c major minor


只有创建了beep文件用户才能通过open之类的操作访问或者调用内核驱动函数


2、2440蜂鸣器用户函数

其次是蜂鸣器内核外的应用层函数


#include

#include

#include

#include

#include


#define BEEP_MAGIC 'b'

#define BEEP_START_CMD _IO (BEEP_MAGIC, 1)

#define BEEP_STOP_CMD _IO (BEEP_MAGIC, 2)




int main()

{

int i = 0;

int dev_fd;

dev_fd = open('/dev/beep',O_RDWR | O_NONBLOCK);

if ( dev_fd == -1 ) {

printf('Cann't open file /dev/beepn');

exit(1);

}

printf('Start beepn');

ioctl (dev_fd, BEEP_START_CMD,0);

getchar();

ioctl (dev_fd, BEEP_STOP_CMD,0);

printf('Stop beep and Close devicen');

close(dev_fd);

return 0;

}



关系大概如下:

image-20230613190752929


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    说明以及其他一些细节内容,包括8051微控制器的基本电路。 当然,首先来介绍8051微控制器引脚图和引脚说明,这样会更容易理解8051微控制器架构,因为设备的引脚图或引脚输出将指定电连接器的引脚及其功能。 8051微控制器引脚图......
    查看整个电路,您必须使用此原理图和本文上一节中显示的步进电机控制器的原理图。 这是 PICAXE 14M2 的引脚图。请注意,只有两个 C 端口引脚具有 ADC(模数转换)功能:C.0 和 C.4......
    系统框图 3.2 74HC595原理图和LED8x8原理图 4 软件设计  1 #include "reg52.h"  2   3 typedef unsigned int     u16......
    本文的内容对初学的朋友有一定帮助。 常见问题: 1.我开发板是STM32F103ZE芯片,但网上找到的软件工程基于STM32F103R8芯片的,我能直接将工程下载并调试吗? 2.我有STM32F205R8的原理图和......
    还搞不懂TIP147是什么管子?看这一文,引脚图+参数+工作原理;我是小七,干货满满。大家不要错过,建议收藏,错过就不一定找得到了,内容仅供参考,图片记得放大,观看。本文引用地址:如果......
    高精度AD、数字隔离器和高精度DA后形成1:1的差分模拟信号,该信号可直接进入后续的差分AD进行采样。  GLa1311典型应用原理图 在部分场景中,后级AD可能为单端输入AD,比如MCU集成AD,此时......
    通过创建一条正反馈路径来给比较器增加磁滞。晶闸管是一种半导体器件,其内部结构包含正反馈,从而以闭锁动作的形式显示磁滞。图5显示了一种称为可控硅整流器(SCR)的晶闸管的物理结构、等效电路和示意图符号。 SCR物理图、等效原理图和原理图......
    家呈现关于PLC,究竟有哪些基础内容,需要先去了解! 当然了这只是一些简单的控制,梯形图和原理图非常类似,同时PLC还要学会一些常见的指令。 ......
    ; } void delay(int a) { int i; for(i=0;i} 注释就没有写了,原理图跟着连是不会有太大问题吧 作业题:修改原理图及代码,用p2.0引脚控制LED闪烁 也是直接放原理图和......
    功能等信息。这个我们开发板芯片原理图内已经将引脚所有功能都标进去了,所以后面也不需要查找具体引脚有什么功能,直接看原理图即可。 二、GPIO 结构框图与工作原理 我们使用的51 单片机GPIO 分为P0、P1......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>