Interpretation of S3C2440 core buzzer driver

Publisher:WhisperingWavesLatest update time:2024-08-21 Source: cnblogsKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

First, we will introduce the locations of some required header files


linux-2.6.32. Important kernel file directory:

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 buzzer core driver

Display kernel driver


#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 transfer function, and generate parameter directory and parameter file in the module directory

/*

MODULE_AUTHOR (declares who wrote the module),

MODULE_DESCRIPION (a human-readable description of what the module does),

MODULE_VERSION (a code revision number; see the comments in for the convention used to create the version string),

MODULE_ALIAS (another name by which the module is known), and MODULE_DEVICE_TABLE (to tell userspace which devices the module supports).

MODULE_LICENSE(“GPL”);

The specific licenses recognized by the kernel are "GPL" (any version of the GNU General Public License applies), "GPL v2" (only version 2 of the GPL applies), "GPL and additional rights", "Dual BSD/GPL", "Dual MPL/GPL", and "Proprietary". Unless your module is explicitly marked as being under a free license recognized by the kernel, it is assumed to be proprietary.

*/

MODULE_AUTHOR("All");

MODULE_LICENSE("Dual BSD/GPL");


#define BEEP_MAGIC 'b'

#define BEEP_START_CMD _IO (BEEP_MAGIC, 1) //Use the _IO function provided by the kernel function library, and refer to the reference for details

#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;

}

//Generally, functions like read and write do not write anything, but open sometimes puts an initialization function


/*

Use the s3c2410_gpio_cfgpin function to initialize the port and set it as output. Use s3c2410_gpio_setpin to set the port output high and low voltages. Set the output voltage you need according to the development manual. s3c2410_gpio_pullup controls the pull-up resistor.

*/

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);

}


/*Function call, using ioctl to select the kernel function to call through different cmd numbers*/

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);

//Register the device, or should I say initialize it

dev->owner = THIS_MODULE;

dev->ops = fops;

err = cdev_add(dev, devno, 1);

//Failed to add device to kernel, after linux-2.6, two functions are used to register and add

if (err)

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

}


/*

file_operations structure

Linux uses the file_operations structure to access the driver's functions. The name of each member of this structure corresponds to a function call.

When the user process performs operations such as read/write on the device file, the system call finds the corresponding device driver through the major device number of the device file, then reads the corresponding function pointer of this data structure, and then transfers control to the function. This is the basic principle of how Linux device drivers work.

struct module *owner

The first file_operations member is not an operation at all, it is a pointer to the module that owns the structure. This member is used to prevent the module from being unloaded while its operations are still being used. Almost all of the time, it is simply initialized to THIS_MODULE, a macro defined in . This macro is quite complex and is usually initialized to THIS_MODULE when doing simple learning operations.

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 function is mainly used to obtain the device number for kernel identification*/

static int beep_init(void)

{

int result;

dev_t dev = MKDEV(beep_major, 0);

//Format conversion, beep_major is the major device number, which is passed when calling the driver, and the default is 0

char dev_name[]="beep";


/* Figure out our device number. */

if (beep_major)

result = register_chrdev_region(dev, 1, dev_name);

//Manually assign the registered device number. If the device number has not been assigned before, beep_major is 0, so the dynamic allocation device number is called for registration. However, after the kernel assigns beep_major to 0, this function will be called. In other words, the function is used only when the major device number is known.

else {

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

beep_major = MAJOR(dev);

//Dynamically assign registered device numbers and update primary device numbers. For details, see 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);

//Unregister the device and delete a cdev

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

//Release the device number occupied by the logout

printk("beep device uninstalledn");

}



module_init(beep_init);

module_exit(beep_cleanup);

//Driver loading system parameter transfer

EXPORT_SYMBOL(beep_major);



Loading the driver module


insmod beep_dev.ko


Create the beep device file under dev and bind it to our beep_dev driver


mknod /dev/beep c 251 0


Original command format: mknod /dev/node_name c major minor


Only when the beep file is created can the user access it through operations such as open or call the kernel driver function.


2. 2440 buzzer user function

The second is the application layer function outside the buzzer core


#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;

}



The relationship is roughly as follows:

image-20230613190752929


Keywords:S3C2440 Reference address:Interpretation of S3C2440 core buzzer driver

Previous article:TQ2440--nandflash (K9F2G08U0A) driver writing
Next article:S3C2440 SPI driver framework

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号