Brief Introduction
Buzzer as a simple audible device in the circuit is a commonly used components, its control is relatively simple, with a simple drive circuit, through the CPU I/O pin level changes can control its sound or not. In the advanced control can use the PWM wave to the buzzer to tune, here only demonstrates whether the buzzer is audible, in the tiny4412 Development Board buzzer Drive circuit is as follows:
Connected with the buzzer pin through the gradual search, you can see its pin and CPU GPD0 pin connection, analysis buzzer driver circuit can come to the conclusion that the CPU I/O output high level transistor conduction, buzzer power will beep, CPU I/O output low level transistor cut-off, The buzzer does not get power and does not beep.
the drive model used
Because the driver only involves simple I/O port level changes, the drive is relatively simple. This drive is written out using a miscellaneous device-driven model, and miscellaneous device drivers can automatically create device files, which is much easier than the other two drive types.
The following is a list of miscellaneous device-driven templates written earlier (no necessary security checks, only approximate frames), and the buzzer driver will be changed in the following example:
#include <linux/kernel.h> #include <linux/module.h> #include <linux/miscdevice.h> #include < linux/fs.h> #include <linux/export.h> #define MISC_MINOR 255//Open function static int misc_open (struct inode *node, Stru
CT file *fp) {printk ("This dev is open\r\n");
return 0;
}//close function static int misc_close (struct inode *node, struct file *fp) {printk ("This dev is close\r\n");
return 0; ///Read function ssize_t misc_read (struct file *fp, char __user *buf, size_t size, loff_t *loff) {printk ("This dev is read\r\n
");
return 0; //write function ssize_t misc_write (struct file *fp, const char __user *buf, size_t size, loff_t *loff) {printk ("This dev is WR
Ite\r\n ");
return 0; } struct file_operations fops={owner=this_module, Open=misc_open,. Read=misc_read, Write=misc_write,. releas
E=misc_close,};
struct Miscdevice mymisc={minor=misc_minor, name= "Mymisc",. Fops=&fops,}; Driver initialization static int __init misc_init (void) {if misc_register (&myMisc)) {PRINTK ("This module is Insmod fail\r\n");
return-1;
} PRINTK ("This module is success\r\n");
return 0;
}//driver uninstall static void __exit misc_exit (void) {PRINTK ("This module is exit\r\n");}
Module_init (Misc_init);
Module_exit (Misc_exit); Module_license ("GPL");
Calling function InterpretationIoremap
Function prototype: void* ioremap (unsigned long phys_addr,unsigned long size)
Role: Map the actual physical address to the address snap-in
Parameters: Phys_addr Actual physical address, size map address
Return value: Returns the address of the physical address in the address snap-in, which is equivalent to operating the actual physical address Iounmap
Function prototypes: void Iounmap (volatile void *addr)
Role: Canceling address mapping
Parameters: Addr Address Management Unit assigned address
return value: None
Why do I need address mapping
CPU and Single-chip microcomputer, SCM Almost all the resources are concentrated in a piece, less peripherals, storage space is not general address are solidified in the SCM internal, in the corresponding address to operate, only to directly operate the corresponding address can be. But the CPU is different, the CPU is complex, the register is more, and the storage unit is all external, belongs to the expansion component. General memory is larger. Due to the considerable flexibility of CPU expansion, it is not possible for the CPU to be designed to solidify all possible address spaces within the CPU (addressing area occupies volume, consumes cost, only to maximize the design, in case the design address unit too small cause application limited influence market share). Sometimes the peripheral address format is not uniform, and compatibility issues need to be considered. So the CPU designer rejects the actual method of reserving physical addresses, and the use of MMU address management, only to open up a small space, when the need to use an address only to get MMU internal, MMU automatically assign a piece of address and the actual address corresponding to the operation of the address is equivalent to the actual physical address of the operation. View the manual to configure the appropriate registers
GPD0 feature configuration registers, address for 0x11400000+0x000000a0=0x114000a0, every four bits control one pin, 0 input, 1 output, etc., where we use the output function, the corresponding bit (Gpdcon[1]) configured to 1 The
GPD0 Data Register, the output of the corresponding bit value 0/1, you can output high-low level, pin configuration for input, read the corresponding pins can get IO status, address for 0x11400000+0x000000a4= 0X114000A4
Sample code driver Code
#include <linux/kernel.h> #include <linux/module.h> #include <linux/miscdevice.h> #include < linux/fs.h> #include <linux/export.h> #include <linux/device.h> #include <asm/io.h> #include < asm/uaccess.h> #define GPD0CON_ADDR 0x114000a0 #define GPD0DAT_ADDR 0x114000a4 static volatile unsigned long *gpd0c
On=null;
Static volatile unsigned long *gpd0dat=null;
#define GPD0CON *gpd0con #define GPD0DAT *gpd0dat//Open function static int misc_open (struct inode *node, struct file *fp) {
PRINTK ("This dev is open\r\n");
return 0;
}//close function static int misc_close (struct inode *node, struct file *fp) {printk ("This dev is close\r\n");
return 0;
///Read function ssize_t misc_read (struct file *fp, char __user *buf, size_t size, loff_t *loff) {Gpd0con |= (0x1<<0);
Gpd0dat &= 0x0;
Gpd0dat |= (0x1<<0);
PRINTK ("This dev is read\r\n");
return 0; //write function ssize_t misc_write (struct file *fp, const char __user *buf, size_tSize, loff_t *loff) {Gpd0dat &= ~ (0x1<<0);
PRINTK ("This dev is write\r\n");
return 0; } struct file_operations fops={owner=this_module, Open=misc_open,. Read=misc_read, Write=misc_write,. releas
E=misc_close,};
struct Miscdevice mymisc={minor=255, name= "Mymisc",. Fops=&fops,}; Driver initialization static int __init misc_init (void) {if (Misc_register (&mymisc)) {PRINTK ("This module is Insmod fail\
r\n ");
return-1;
} PRINTK ("This module is success\r\n");
Gpd0con=ioremap (gpd0con_addr,4);
Gpd0dat=ioremap (gpd0dat_addr,4);
return 0;
}//driver uninstall static void __exit misc_exit (void) {Iounmap (gpd0dat);
Iounmap (Gpd0con);
PRINTK ("This module is exit\r\n");
} module_init (Misc_init);
Module_exit (Misc_exit); Module_license ("GPL");
App Code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h >
#include <sys/stat.h>
#include <fcntl.h>
int main (int argc,char *argv[])
{
int Fd,i;
Char buf[8];
Fd=open (ARGV[1],O_RDWR);
for (i=0;i<3;i++)
{
read (fd,buf,0);
Sleep (1);
Write (fd,buf,0);
Sleep (1);
}
Close (FD);
return 0;
}
Makefile
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int argc,char *argv[])
{
int fd,i;
Char buf[8];
Fd=open (ARGV[1],O_RDWR);
for (i=0;i<3;i++)
{
read (fd,buf,0);
Sleep (1);
Write (fd,buf,0);
Sleep (1);
}
Close (FD);
return 0;
}
Validate
Install drive Module
[Root@zc/zhangchao] #ls
Makefile misc.c misc.mod.c misc.o
modules.order module.symvers Misc.ko misc.mod.o misc_app.c
[Root@zc/zhangchao] #insmod Misc.ko
[ 25.585000] This Module is success
[Root@zc/zhangchao] #ls/dev/mymisc-l
crw-rw---- 1 root 47 1 12:34/dev/mymisc
[root@zc/zhangchao]#
running the app
[Root@zc/zhangchao] #ls
Makefile app Misc.ko misc.mod.o misc_app.c
module.symvers misc.c misc.mod.c misc.o modules.order
[Root@zc/zhangchao]#./app/dev/mymisc
[ 194.775000] This dev are open
[ 194.775000] This dev is read
[ 195.775000] This dev is write
[ 196.775000] This dev are read
[ 197.775000] This dev be write
[ 198.775000] This dev is read
[ 199.775000] This dev are write
[ 200.775000] This dev be close
[root@zc/zhangchao]#