基于tiny210v2的linux-3.9.6内核驱动移植4:PWM移植

来源:互联网 发布:单片机与usb连接电路图 编辑:程序博客网 时间:2024/06/03 16:20

 对于做智能车的爱好者来说PWM可说是很重要的,那么如果要用arm开发板来控制pwm,首先还是要移植pwm驱动

       开发板:tiny210v2,S5PV210核心。

        环境:    ubuntu13.04 +arm-linux-gcc

        内核:    linux-3.9

        参考友善自带的linux-3.0.8内核代码

        转载请注明:

               blog.csdn.net/canyue102/article/details/9526551

一、硬件信息

         对于tiny210v2开发板上有一个PWM0对应一个峰鸣器,引脚为GPD0-0

二、驱动源码

         在linux-3.9.6/drivers/char文件夹下新建smdkv210_pwm.c

 

/* * linux/drivers/char/smdkv210_pwm.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/fb.h>#include <linux/backlight.h>#include <linux/err.h>#include <linux/pwm.h>#include <linux/slab.h>#include <linux/miscdevice.h>#include <linux/delay.h>#include <mach/gpio.h>#include <mach/regs-gpio.h>#include <plat/gpio-cfg.h>#define DEVICE_NAME"pwm"#define PWM_IOCTL_SET_FREQ1#define PWM_IOCTL_STOP0#define NS_IN_1HZ(1000000000UL)#define BUZZER_PWM_ID0#define BUZZER_PMW_GPIOS5PV210_GPD0(0)static struct pwm_device *pwm4buzzer;static struct semaphore lock;static void pwm_set_freq(unsigned long freq) {int period_ns = NS_IN_1HZ / freq;pwm_config(pwm4buzzer, period_ns / 2, period_ns);pwm_enable(pwm4buzzer);s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));}static void pwm_stop(void) {s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);pwm_config(pwm4buzzer, 0, NS_IN_1HZ / 100);pwm_disable(pwm4buzzer);}static int smdkv210_pwm_open(struct inode *inode, struct file *file) {if (!down_trylock(&lock))return 0;elsereturn -EBUSY;}static int smdkv210_pwm_close(struct inode *inode, struct file *file) {up(&lock);return 0;}static long smdkv210_pwm_ioctl(struct file *filep, unsigned int cmd,unsigned long arg){switch (cmd) {case PWM_IOCTL_SET_FREQ:if (arg == 0)return -EINVAL;pwm_set_freq(arg);break;case PWM_IOCTL_STOP:default:pwm_stop();break;}return 0;}static struct file_operations smdkv210_pwm_ops = {.owner= THIS_MODULE,.open= smdkv210_pwm_open,.release= smdkv210_pwm_close, .unlocked_ioctl= smdkv210_pwm_ioctl,};static struct miscdevice smdkv210_misc_dev = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &smdkv210_pwm_ops,};static int __init smdkv210_pwm_dev_init(void) {int ret;ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);if (ret) {printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);return ret;}gpio_set_value(BUZZER_PMW_GPIO, 0);s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);pwm4buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);if (IS_ERR(pwm4buzzer)) {printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);return -ENODEV;}pwm_stop();sema_init(&lock, 1);ret = misc_register(&smdkv210_misc_dev);printk(DEVICE_NAME "\tinitialized\n");return ret;}static void __exit smdkv210_pwm_dev_exit(void) {pwm_stop();misc_deregister(&smdkv210_misc_dev);gpio_free(BUZZER_PMW_GPIO);}module_init(smdkv210_pwm_dev_init);module_exit(smdkv210_pwm_dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");MODULE_DESCRIPTION("S5PV210 PWM Driver");

二、设置config文件

    在该目录下的Kconfig文件中添加:

config SMDKV210_BUZZER
    tristate "Buzzer driver for FriendlyARM TINY210 development boards"
    depends on MACH_SMDKV210
    default y
    help
      this is buzzer driver for FriendlyARM TINY210 development boards
三、修改Makefile

    在该目录下的Makefile文件中添加:

    obj-$(CONFIG_SMDKV210_BUZZER)    += smdkv210_pwm.o

四、make测试

    编译通过

五、测试程序

  

#include <stdio.h>#include <termios.h>#include <unistd.h>#include <stdlib.h>#define PWM_IOCTL_SET_FREQ#define PWM_IOCTL_STOP#define ESC_KEY120x1bstatic int getch(void){struct termios oldt,newt;int ch;if (!isatty(STDIN_FILENO)) {fprintf(stderr, "this problem should be run at a terminal\n");exit(1);}// save terminal settingif(tcgetattr(STDIN_FILENO, &oldt) < 0) {perror("save the terminal setting");exit(1);}// set terminal as neednewt = oldt;newt.c_lflag &= ~( ICANON | ECHO );if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {perror("set terminal");exit(1);}ch = getchar();// restore termial settingif(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {perror("restore the termial setting");exit(1);}return ch;}static int fd = -1;static void close_buzzer(void);static void open_buzzer(void){fd = open("/dev/pwm", 0);if (fd < 0) {perror("open pwm_buzzer device");exit(1);}// any function exit call will stop the buzzeratexit(close_buzzer);}static void close_buzzer(void){if (fd >= 0) {ioctl(fd, PWM_IOCTL_STOP);close(fd);fd = -1;}}static void set_buzzer_freq(int freq){// this IOCTL command is the key to set frequencyint ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);if(ret < 0) {perror("set the frequency of the buzzer");exit(1);}}static void stop_buzzer(void){int ret = ioctl(fd, PWM_IOCTL_STOP);if(ret < 0) {perror("stop the buzzer");exit(1);}}int main(int argc, char **argv){int freq = 1000 ;open_buzzer();printf( "\nBUZZER TEST ( PWM Control )\n" );printf( "Press +/- to increase/reduce the frequency of the BUZZER\n" ) ;printf( "Press 'ESC' key to Exit this program\n\n" );while( 1 ){int key;set_buzzer_freq(freq);printf( "\tFreq = %d\n", freq );key = getch();switch(key) {case '+':if( freq < 20000 )freq += 10;break;case '-':if( freq > 11 )freq -= 10 ;break;case ESC_KEY:case EOF:stop_buzzer();exit(0);default:break;}}}


       

             


原创粉丝点击