向linux内核中加载PWM(蜂鸣器)的两种方法

来源:互联网 发布:python opencv 切割 编辑:程序博客网 时间:2024/06/06 00:59

pwm_test蜂鸣器驱动的添加

添加有两种方式

Pwm驱动程序:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/delay.h>

#include <linux/poll.h>

#include <linux/interrupt.h>

#include <linux/gpio.h>

 

#include <asm/irq.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include <mach/regs-gpio.h>

#include <mach/hardware.h>

#include <plat/regs-timer.h>

#include <mach/regs-irq.h>

#include <asm/mach/time.h>

#include <linux/clk.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <linux/miscdevice.h>

 

#define DEVICE_NAME     "pwm"

 

#define PWM_IOCTL_SET_FREQ             1

#define PWM_IOCTL_STOP                     0

 

static struct semaphore lock;

 

/* freq:  pclk/50/16/65536 ~ pclk/50/16

  * if pclk = 50MHz, freq is 1Hz to 62500Hz

  * human ear : 20Hz~ 20000Hz

  */

static void PWM_Set_Freq( unsigned long freq )

{

       unsigned long tcon;

       unsigned long tcnt;

       unsigned long tcfg1;

       unsigned long tcfg0;

 

       struct clk *clk_p;

       unsigned long pclk;

 

       //set GPB0 as tout0, pwm output

       s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);

 

       tcon = __raw_readl(S3C2410_TCON);

       tcfg1 = __raw_readl(S3C2410_TCFG1);

       tcfg0 = __raw_readl(S3C2410_TCFG0);

 

       //prescaler = 50

       tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;

       tcfg0 |= (50 - 1);

 

       //mux = 1/16

       tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;

       tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;

 

       __raw_writel(tcfg1, S3C2410_TCFG1);

       __raw_writel(tcfg0, S3C2410_TCFG0);

 

       clk_p = clk_get(NULL, "pclk");

       pclk  = clk_get_rate(clk_p);

       tcnt  = (pclk/50/16)/freq;

      

       __raw_writel(tcnt, S3C2410_TCNTB(0));

       __raw_writel(tcnt/2, S3C2410_TCMPB(0));

                           

       tcon &= ~0x1f;

       tcon |= 0xb;           //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0

       __raw_writel(tcon, S3C2410_TCON);

      

       tcon &= ~2;                 //clear manual update bit

       __raw_writel(tcon, S3C2410_TCON);

}

 

static void PWM_Stop(void)

{

       s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);

       s3c2410_gpio_setpin(S3C2410_GPB(0), 0);

}

 

static int s3c24xx_pwm_open(struct inode *inode, struct file *file)

{

       if (!down_trylock(&lock))

              return 0;

       else

              return -EBUSY;

}

 

 

static int s3c24xx_pwm_close(struct inode *inode, struct file *file)

{

       PWM_Stop();

       up(&lock);

    return 0;

}

 

 

static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

       //printk("ioctl pwm: %x %lx\n", cmd, arg);

       switch (cmd) {

       case PWM_IOCTL_SET_FREQ:

              if (arg == 0)

                     return -EINVAL;

              PWM_Set_Freq(arg);

              break;

 

       case PWM_IOCTL_STOP:

              PWM_Stop();

              break;

       }

       return 0;

}

static struct file_operations dev_fops = {

    .owner   =   THIS_MODULE,

    .open    =   s3c24xx_pwm_open,

    .release =   s3c24xx_pwm_close,

    .ioctl   =   s3c24xx_pwm_ioctl,

};

 

static struct miscdevice misc = {

       .minor = MISC_DYNAMIC_MINOR,

       .name = DEVICE_NAME,

       .fops = &dev_fops,

};

 

static int __init dev_init(void)

{

       int ret;

 

       init_MUTEX(&lock);

       ret = misc_register(&misc);

 

       printk (DEVICE_NAME"\tinitialized\n");

           return ret;

}

 

static void __exit dev_exit(void)

{

       misc_deregister(&misc);

}

 

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("FriendlyARM Inc.");

MODULE_DESCRIPTION("S3C2410/S3C2440 PWM Driver");

1.       直接添加在内核中

     mini2440_pwm.c 驱动程序拷贝到字符设备驱动下

cp mini2440_pwm.c /usr/local/kernels/linux-2.6.32.2/drivers/char/

     /usr/local/kernels/linux-2.6.32.2/drivers/char/下修改配置文件Kconfig

加入

config PWM

tristate "This is PWM Driver"

default y

---help---

pwm!pwm!

     /usr/local/kernels/linux-2.6.32.2/drivers/char/Makefile

加入

obj-$(CONFIG_PWM)   +=mini2440_pwm.o

     make menuconfig 中选中pwm选项

Dvice drivers----à

               Charcter drivers-----à

                                    [*]This is PWM Driver

     make zImage

     linux-2.6.32.2/ARCH/arm/boot/zImage拷贝到板子上去

     在终端中运行  pwm_test 即可听到蜂鸣器发出声音

2.       以模块的方式添加

     前三步骤和直接加载到内核的一样

     make menuconfig 中选中pwm选项

Dvice drivers----à

               Charcter drivers-----à

                                    [M]This is PWM Driver

     先将Driver文件夹中有Makefile文件   执行make

     mini2440_pwm.ko 移动 mv mini2440_pwm.ko lib/modules/

     加载至内核   insmod  mini2440_pwm.ko

     lsmod 可以查看已经加载过的驱动

     再回到应用程序中  make一下
执行pwm_test