// >0 sets the value in down_counter (beeping frequency)
//-------------------------------------------------------------
static int xiaoyang_beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{
unsigned long temp;
if(cmd <= 0)
{
//set as gpb0,output
temp = __raw_readl(S3C2410_GPBCON); //GPBCON IO Control
temp &= ~3; //just select the GPBCON[1:0]bits for gpb0
temp |= 1; //set gpb[0] as output
__raw_writel(temp, S3C2410_GPBCON);
//set gpbdata[0](beep value) as 0
temp = __raw_readl(S3C2410_GPBDAT); //GPBDAT
temp &= ~1;
__raw_writel(temp, S3C2410_GPBDAT);
}
else
{
//set as TOUT0
temp = __raw_readl(S3C2410_GPBCON); //GPBCON
temp &= ~3;
temp |= 2; //using TOUT0(pwm timer)
__raw_writel(temp, S3C2410_GPBCON);
//using pwm timer TOUT0
temp = __raw_readl(S3C2410_TCFG0); //TCFG0
temp &= ~0xff; //select Timer0
temp |= 15; //FCLK/(15+1)/(devided value),prescaler value!
__raw_writel(temp, S3C2410_TCFG0);
temp = __raw_readl(S3C2410_TCFG1); //TCFG1
temp &= ~0xf; //select MUX0
temp |= 1; //1/4 diveder
__raw_writel(temp, S3C2410_TCFG1);
//--------------------------------------------------------------
// now set TCNTB and TCMPB,generate 1:1 diveded timer
//TCNTB register sets the initial value loaded into the down counter and decrements it in sequence
//TCMPB register is used to load the value to be compared with the down counter
// So when TCMPB = TCNTB/2 is set, it means 1:1 time division
//--------------------------------------------------------------
temp = (50000000/64)/cmd;//set timer count buffer rgister ,50MHZ/(16*4*cmd)
__raw_writel(temp, S3C2410_TCNTB(0));
temp >>= 1;
__raw_writel(temp, S3C2410_TCMPB(0));
//setup timer0
temp = __raw_readl(S3C2410_TCON); //TCON
temp &= ~0x1f;
temp |= 0xb;//disable deadzone,auto-reload,interval-off,update TCNTB and TCMPB,start timer0
__raw_writel(temp, S3C2410_TCON);
temp &= ~2;//set bit[0] as 0,clear manual update-setting bit
__raw_writel(temp, S3C2410_TCON);
}
return 0;
}
//--------------------------------------------------------------
// This structure is the core of the character device driver
// The open, read, write, ioctl and other functions called when the application operates the device file.
// The corresponding function specified in this structure will eventually be called
//--------------------------------------------------------------
static struct file_operations xiaoyang_beep_fops = {
.owner = THIS_MODULE,
.ioctl = xiaoyang_beep_ioctl,
};
static char __initdata banner[] = "TQ2440 Beep, 2010-xiaoyang yin";
static struct class *beep_class;
//--------------------------------------------------------------
// This function will be called when the "insmod xiaoyang_beep.ko" command is executed
//--------------------------------------------------------------
static int __init xiaoyang_beep_init(void)
{
int ret;
printk(banner);
//--------------------------------------------------------------
// Register character device driver
// The parameters are the main device number, device name, and file_operations structure;
// In this way, the major device number is associated with the specific file_operations structure,
// When operating a device file whose main device is BEEP_MAJOR, the relevant member function in xiaoyang_beep_fops will be called
// BEEP_MAJOR can be set to 0, indicating that the kernel automatically assigns the major device number
//--------------------------------------------------------------
ret = register_chrdev(BEEP_MAJOR, DEVICE_NAME, &xiaoyang_beep_fops);//Assign device number
if (ret < 0) {
printk(DEVICE_NAME " can't register major numbern");
return ret;
}
//Register a class so that mdev can create device nodes under the "/dev/" directory
beep_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(beep_class))
{
printk("Err: failed in xiaoyang-Beep class. n");
return -1;
}
//Create a device node named DEVICE_NAME
device_create(beep_class, NULL, MKDEV(BEEP_MAJOR, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME " initializedn");
return 0;
}
//--------------------------------------------------------------
// This function will be called when the "rmmod xiaoyang_beep.ko" command is executed
//--------------------------------------------------------------
static void __exit xiaoyang_beep_exit(void)
{
/* Uninstall the driver */
unregister_chrdev(BEEP_MAJOR, DEVICE_NAME);
device_destroy(beep_class, MKDEV(BEEP_MAJOR, 0)); //Delete the device node
class_destroy(beep_class); //Deregister class
}
//Specify the driver's initialization function and uninstallation function
module_init(xiaoyang_beep_init);
module_exit(xiaoyang_beep_exit);
/* Describe some information about the driver, not required */
MODULE_AUTHOR("software-hit"); //Driver author
MODULE_DESCRIPTION("TQ2440 Beep Driver"); //Description information
MODULE_LICENSE("GPL"); //Agreement to follow
Add it to the kernel, configure drivers/char/Kconfig and Makefile, copy config_EmbededSky_W35 in the root directory to .config and run: Make menuconfig to configure.
Beep can be added to the kernel as a module or as a mandatory part of the kernel. Then run
Make oldconfig
Make
After generating zImage and burning it to the development board, there will be a /dev/beep device.
If you want to compile it as a module, just run Make SUBDIR=drivers/char/modules to compile EmbededSky_Beep.ko, copy it to the development board and load it with insmod.
The following problems occurred during the compilation process:
drivers/char/EmbedSky_beep.c: In function 'xiaoyang_beep_init':
drivers/char/EmbedSky_beep.c:134: error: implicit declaration of function 'class_device_create'
drivers/char/EmbedSky_beep.c: In function 'xiaoyang_beep_exit':
drivers/char/EmbedSky_beep.c:148: error: implicit declaration of function 'class_device_destroy'
make[2]: *** [drivers/char/EmbedSky_beep.o] Error 1
make[1]: *** [drivers/char] Error 2
make: *** [drivers] Error 2
[xiaoyang@localhost linux-2.6.3
Solution:
This is mainly caused by interface changes between versions.
In Linux 2.6, there are some modifications in different versions to address the above problem. Before using, you should first check the function declaration in /.../include/linux/device.h. For example, if I use Linux 2.6.30, there is no class_device_create function, and you can directly use device_create. In previous versions such as Linux 2.6.15, you need to use the class_device_create function.
So don't use class_device_create but use device_create instead, and the same goes for the other interface.
Writing an application:
//----------------------------------------------------------
// xiaoyang@2011.4.21
// beep driver/module test
//----------------------------------------------------------
#include
#include
#include
#include
#include
#include
int main()
{
int fd;
int i = 0;
int m_pwm_val;
fd = open("/dev/xiaoyang-beep",O_RDWR);
if(fd < 0){
perror("open device xiaoyang-beep error!");
exit(1);
}
for(i = 0; i < 1000; i++){
scanf("%d",&m_pwm_val);
printf("your pwm_val is %dn",m_pwm_val);
ioctl(fd,m_pwm_val,4); //The last parameter is useless. ioctl: Linux interface uses a unified interface to operate the device
if(m_pwm_val == 0){
break;
}
}
close(fd);
return 0;
}
Makefile is as follows:
CROSS_COMPILE=arm-linux-
CC=$(CROSS_COMPILE)gcc
obj-m := hello.o
all:beep
beep:beep.c
$(CC) -o beep beep.c
$(CROSS_COMPILE)strip beep
clean:
rm -rf *.o beep
Screenshot of experimental results:
After entering the number, the beep sounds at different frequencies, which is too harsh.
Previous article:Linux driver learning (3)--synchronization, semaphores and spin locks
Next article:Linux driver learning (1) - environment and hello world program
Recommended ReadingLatest update time:2024-11-16 09:40
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- I don't quite agree with this statement.
- Schottky diode voltage drop test
- Oscilloscope is fun, it’s more than just waveform display!
- Feiling FETT507-C core board 4-way AHD camera implementation solution
- DSP ccs2 C5000 compiles SUBC instruction to implement division
- Push-button start system power supply circuit
- Tell us what you think about 996
- How to view NPU clock power configuration and information for Allwinner V853 chip?
- Detailed explanation of the method of remote control of oscilloscope mobile app
- USB PD fast charging communication principle