怎么优化自己网站,北京移动端网站价格,云服务器建站,研发一个app费用编写驱动的第一步仍是看原理图#xff1a; 可以看到#xff0c;该蜂鸣器由 GPD0_0 来控制 #xff0c;查手册可知该I/O口由Time0 来控制#xff0c;找到相应的寄存器#xff1a; a -- I/O口寄存器及地址 GPD0CON 0x114000a0 b -- Time0 寄存器及地址 基地址为#xff1a… 编写驱动的第一步仍是看原理图 可以看到该蜂鸣器由 GPD0_0 来控制 查手册可知该I/O口由Time0 来控制找到相应的寄存器 a -- I/O口寄存器及地址 GPD0CON 0x114000a0 b -- Time0 寄存器及地址 基地址为TIMER_BASE 0x139D0000 这些物理寄存器地址都是相邻的我们这里用偏移量来表示 寄存器名 地址偏移量 所需配置 TCFG0 0x0000 [7-0] 0XFF TCFG1 0x0004 [3-0] 0X2 TCON 0x0008 [3-0] 0X2 0X9 0X0 TCNTB0 0x000C 500 TCMPB0 0x0010 250 前面已经知道驱动是无法直接操纵物理地址的所以这里仍需物理地址向虚拟地址的转换用到 ioremap() 函数、writel()函数、readl()函数 1、地址映射操作 [cpp] view plaincopy unsigned int *gpd0con; void *timer_base;span stylewhite-space:pre /span//之所以是void类型偏移量为4时只是移动4个字节方便理解 gpd0con ioremap(GPD0CON,4); timer_base ioremap(TIMER_BASE , 0x14); 2、Time0初始化操作这里使用的已经是虚拟地址 这里现将数据从寄存器中读出修改后再写回寄存器具体寄存器操作可以移步Exynos4412裸机开发——PWM定时器: [cpp] view plaincopy writel((readl(gpd0con)~(0xf0)) | (0x20),gpd0con); writel ((readl(timer_base TCFG0 )~(0xff0)) | (0xff 0),timer_base TCFG0); writel ((readl(timer_base TCFG1 )~(0xf0)) | (0x2 0),timer_base TCFG1 ); 3、装载数据配置占空比 [cpp] view plaincopy writel(500, timer_base TCNTB0 ); writel(250, timer_base TCMPB0 ); writel ((readl(timer_base TCON )~(0xf0)) | (0x2 0),timer_base TCON ); 4、相关控制函数 [cpp] view plaincopy void beep_on(void) { writel ((readl(timer_base TCON )~(0xf0)) | (0x9 0),timer_base TCON ); } void beep_off(void) { writel ((readl(timer_base TCON )~(0xf0)) | (0x0 0),timer_base TCON ); } 下面是驱动程序这里我们用到了 write() read() ioctl() 函数具体解析移步 驱动程序:beep.c [cpp] view plaincopy #include linux/module.h #include linux/fs.h #include linux/cdev.h #include linux/device.h #include asm/io.h #include asm/uaccess.h static int major 250; static int minor0; static dev_t devno; static struct class *cls; static struct device *test_device; #define GPD0CON 0x114000a0 #define TIMER_BASE 0x139D0000 #define TCFG0 0x0000 #define TCFG1 0x0004 #define TCON 0x0008 #define TCNTB0 0x000C #define TCMPB0 0x0010 static unsigned int *gpd0con; static void *timer_base; #define MAGIC_NUMBER k #define BEEP_ON _IO(MAGIC_NUMBER ,0) #define BEEP_OFF _IO(MAGIC_NUMBER ,1) #define BEEP_FREQ _IO(MAGIC_NUMBER ,2) static void fs4412_beep_init(void) { gpd0con ioremap(GPD0CON,4); timer_base ioremap(TIMER_BASE,0x14); writel ((readl(gpd0con)~(0xf0)) | (0x20),gpd0con); writel ((readl(timer_base TCFG0 )~(0xff0)) | (0xff 0),timer_base TCFG0); writel ((readl(timer_base TCFG1 )~(0xf0)) | (0x2 0),timer_base TCFG1 ); writel (500, timer_base TCNTB0 ); writel (250, timer_base TCMPB0 ); writel ((readl(timer_base TCON )~(0xf0)) | (0x2 0),timer_base TCON ); } void fs4412_beep_on(void) { writel ((readl(timer_base TCON )~(0xf0)) | (0x9 0),timer_base TCON ); } void fs4412_beep_off(void) { writel ((readl(timer_base TCON )~(0xf0)) | (0x0 0),timer_base TCON ); } static int beep_open (struct inode *inode, struct file *filep) { // fs4412_beep_on(); return 0; } static int beep_release(struct inode *inode, struct file *filep) { fs4412_beep_off(); return 0; } #define BEPP_IN_FREQ 100000 static void beep_freq(unsigned long arg) { writel(BEPP_IN_FREQ/arg, timer_base TCNTB0 ); writel(BEPP_IN_FREQ/(2*arg), timer_base TCMPB0 ); } static long beep_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { switch(cmd) { case BEEP_ON: fs4412_beep_on(); break; case BEEP_OFF: fs4412_beep_off(); break; case BEEP_FREQ: beep_freq( arg ); break; default : return -EINVAL; } } static struct file_operations beep_ops { .open beep_open, .release beep_release, .unlocked_ioctl beep_ioctl, }; static int beep_init(void) { int ret; devno MKDEV(major,minor); ret register_chrdev(major,beep,beep_ops); cls class_create(THIS_MODULE, myclass); if(IS_ERR(cls)) { unregister_chrdev(major,beep); return -EBUSY; } test_device device_create(cls,NULL,devno,NULL,beep);//mknod /dev/hello if(IS_ERR(test_device)) { class_destroy(cls); unregister_chrdev(major,beep); return -EBUSY; } fs4412_beep_init(); return 0; } void fs4412_beep_unmap(void) { iounmap(gpd0con); iounmap(timer_base); } static void beep_exit(void) { fs4412_beep_unmap(); device_destroy(cls,devno); class_destroy(cls); unregister_chrdev(major,beep); printk(beep_exit \n); } MODULE_LICENSE(GPL); module_init(beep_init); module_exit(beep_exit); makefile: [cpp] view plaincopy ifneq ($(KERNELRELEASE),) obj-m:beep.o $(info 2nd) else #KDIR : /lib/modules/$(shell uname -r)/build KDIR : /home/fs/linux/linux-3.14-fs4412 PWD:$(shell pwd) all: $(info 1st) make -C $(KDIR) M$(PWD) modules arm-none-linux-gnueabi-gcc test.c -o beeptest sudo cp beep.ko beeptest /tftpboot clean: rm -f *.ko *.o *.symvers *.mod.c *.mod.o *.order endif 下面是是个简单的测试程序test.c仅实现蜂鸣器响6秒的功能[cpp] view plaincopy #include sys/types.h #include sys/stat.h #include fcntl.h #include stdio.h #include sys/ioctl.h #define MAGIC_NUMBER k #define BEEP_ON _IO(MAGIC_NUMBER ,0) #define BEEP_OFF _IO(MAGIC_NUMBER ,1) #define BEEP_FREQ _IO(MAGIC_NUMBER ,2) main() { int fd; fd open(/dev/beep,O_RDWR); if(fd0) { perror(open fail \n); return ; } ioctl(fd,BEEP_ON); sleep(6); ioctl(fd,BEEP_OFF); close(fd); } 这是个音乐播放测试程序慎听分别为《大长今》、《世上只有妈妈好》、《渔船》这个单独编译一下 [cpp] view plaincopy /* * main.c : test demo driver */ #include stdio.h #include stdlib.h #include unistd.h #include fcntl.h #include string.h #include sys/types.h #include sys/stat.h #include sys/ioctl.h #include pwm_music.h /*ioctl 鍛戒护*/ #define magic_number k #define BEEP_ON _IO(magic_number,0) #define BEEP_OFF _IO(magic_number,1) #define SET_FRE _IO(magic_number,2) int main(void) { int i 0; int n 2; int dev_fd; int div; dev_fd open(/dev/beep,O_RDWR | O_NONBLOCK); if ( dev_fd -1 ) { perror(open); exit(1); } for(i 0;isizeof(GreatlyLongNow)/sizeof(Note);i ) { div (GreatlyLongNow[i].pitch); ioctl(dev_fd, SET_FRE, div); ioctl(dev_fd, BEEP_ON); usleep(GreatlyLongNow[i].dimation * 100); ioctl(dev_fd, BEEP_OFF); } for(i 0;isizeof(MumIsTheBestInTheWorld)/sizeof(Note);i ) { div (MumIsTheBestInTheWorld[i].pitch); ioctl(dev_fd, SET_FRE, div); ioctl(dev_fd, BEEP_ON); usleep(MumIsTheBestInTheWorld[i].dimation * 100); ioctl(dev_fd, BEEP_OFF); } for(i 0;isizeof(FishBoat)/sizeof(Note);i ) { div (FishBoat[i].pitch); ioctl(dev_fd, SET_FRE, div); ioctl(dev_fd, BEEP_ON); usleep(FishBoat[i].dimation * 100); ioctl(dev_fd, BEEP_OFF); } return 0; } 附所用头文件 [cpp] view plaincopy #ifndef __PWM_MUSIC_H #define __PWM_MUSIC_H #define BIG_D #define PCLK (202800000/4) typedef struct { int pitch; int dimation; }Note; // 1 2 3 4 5 6 7 // C D E F G A B //261.6256 293.6648 329.6276 349.2282 391.9954 440 493.8833 //C澶ц皟 #ifdef BIG_C #define DO 262 #define RE 294 #define MI 330 #define FA 349 #define SOL 392 #define LA 440 #define SI 494 #define TIME 6000 #endif //D澶ц皟 #ifdef BIG_D #define DO 293 #define RE 330 #define MI 370 #define FA 349 #define SOL 440 #define LA 494 #define SI 554 #define TIME 6000 #endif Note MumIsTheBestInTheWorld[]{ //6. //_5 //3 //5 {LA,TIMETIME/2}, {SOL,TIME/2},{MI,TIME},{SOL,TIME}, //1^ //6_ //_5 //6- {DO*2,TIME},{LA,TIME/2},{SOL,TIME/2} ,{LA,2*TIME}, // 3 //5_ //_6 //5 {MI,TIME},{SOL,TIME/2},{LA,TIME/2},{SOL,TIME}, // 3 //1_ //_6, {MI,TIME},{DO,TIME/2},{LA/2,TIME/2}, //5_ //_3 //2- //2. {SOL,TIME/2},{MI,TIME/2},{RE,TIME*2},{RE,TIMETIME/2}, //_3 //5 //5_ //_6 {MI,TIME/2},{SOL,TIME},{SOL,TIME/2},{LA,TIME/2}, // 3 //2 //1- //5. {MI,TIME},{RE,TIME},{DO,TIME*2},{SOL,TIMETIME/2}, //_3 //2_ //_1 //6,_ {MI,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME/2}, //_1 //5,-- {DO,TIME/2},{SOL/2,TIME*3} }; Note GreatlyLongNow[]{ // 2 3 3 3. _2 1 {RE,TIME}, {MI,TIME},{MI,TIME},{MI,TIMETIME/2},{RE,TIME/2},{DO,TIME}, //6, 1 2 1-- 2 3 3 {LA/2,TIME},{DO,TIME},{RE,TIME},{DO,TIME*3},{RE,TIME},{MI,TIME},{MI,TIME}, //3. _5 3 3 2 3 {MI,TIMETIME/2},{SOL,TIME/2},{MI,TIME},{MI,TIME},{RE,TIME},{MI,TIME}, //3-- 5 6 6 6. _5 {MI,TIME*3},{SOL,TIME},{LA,TIME},{LA,TIME},{LA,TIMETIME/2},{SOL,TIME/2}, // 3 3 5 6 5--- 2 3 {MI,TIME},{MI,TIME},{SOL,TIME},{LA,TIME},{SOL,TIME*3},{RE,TIME},{MI,TIME}, // 3 2. _3 3 2 3 {MI,TIME},{RE,TIMETIME/2},{MI,TIME/2},{MI,TIME},{RE,TIME},{MI,TIME}, //6, 1_ _6, 6,- {LA/2,TIME},{DO,TIME/2},{LA/2,TIME/2},{LA/2,TIME*2}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, // 2 3 1 2. _3 5 {RE,TIME},{MI,TIME},{DO,TIME},{RE,TIMETIME/2},{MI,TIME/2},{SOL,TIME}, //6_ _6 6_ _5 3 {LA,TIME/2},{LA,TIME/2},{LA,TIME/2},{SOL,TIME/2},{MI,TIME}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, //6, 5,. _6, 6,-- {LA/2,TIME},{SOL/2,TIMETIME/2},{LA/2,TIME/2},{LA/2,TIME*3}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, // 2 3 1 2. _3 5 {RE,TIME},{MI,TIME},{DO,TIME},{RE,TIMETIME/2},{MI,TIME/2},{SOL,TIME}, //6_ _6 6_ _5 3 {LA,TIME/2},{LA,TIME/2},{LA,TIME/2},{SOL,TIME/2},{MI,TIME}, //2_ _2 2_ _1 6, {RE,TIME/2},{RE,TIME/2},{RE,TIME/2},{DO,TIME/2},{LA/2,TIME}, //6, 5,. _6, 6,-- {LA/2,TIME},{SOL/2,TIMETIME/2},{LA/2,TIME/2},{LA/2,TIME*3} }; Note FishBoat[]{ //3. _5 6._ 1^ 6_ {MI,TIMETIME/2},{SOL,TIME/2},{LA,TIME/2TIME/4},{DO*2,TIME/4},{LA,TIME/2}, //_5 3 -. 2 1. _3 2._ {SOL,TIME/2},{MI,TIME*3},{RE,TIME},{DO,TIMETIME/2},{MI,TIME/2},{RE,TIME/2TIME/4}, //3 2_ _1 2-- 3. _5 {MI,TIME/4},{RE,TIME/2},{DO,TIME/2},{RE,TIME*4},{MI,TIMETIME/2},{SOL,TIME/2}, // 2 1 6._ 1^ 6_ _5 {RE,TIME},{DO,TIME},{LA,TIME/2TIME/4},{DO*2,TIME/4},{LA,TIME/2},{SOL,TIME/2}, //6- 5,. _6, 1._ 3 {LA,TIME*2},{SOL/2,TIMETIME/2},{LA/2,TIME/2},{DO,TIME/2TIME/4},{MI,TIME/4}, //2_ _1 5,-- {RE,TIME/2},{DO,TIME/2},{SOL/2,TIME*4}, //3. _5 6._ 1^ 6_ {MI,TIMETIME/2},{SOL,TIME/2},{LA,TIME/2TIME/4},{DO*2,TIME/4},{LA,TIME/2}, //_5 3-. 5_ _6 1^_ _6 {SOL,TIME/2},{MI,TIME*3},{SOL,TIME/2},{LA,TIME/2},{DO*2,TIMETIME/2},{LA,TIME/2}, //5._ 6 5_ _3 2-- {SOL,TIME/2TIME/4},{LA,TIME/4},{SOL,TIME/2},{MI,TIME/2},{RE,TIME*4}, //3. _5 2._ 3 2_ _1 {MI,TIMETIME/2},{SOL,TIME/2},{RE,TIME/2TIME/4},{MI,TIME/4},{RE,TIME/2},{DO,TIME/2}, //6._ 1^ 6_ _5 6- 1. {LA,TIME/2TIME/4},{DO*2,TIME/4},{LA,TIME/2},{SOL,TIME/2},{LA,TIME*2},{DO,TIMETIME/2}, //_2 3_ _5 2_ _3 1-- {RE,TIME/2},{MI,TIME/2},{SOL,TIME/2},{RE,TIME/2},{MI,TIME/2},{DO,TIME*4} }; #endif 编译好程序后 # insmod beep.ko #mknod /dev/beep c 250 0 #./music