说明:以下由两部分组成,定时器驱动、定时器应用程序构成;


1.驱动程序;


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/mm.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach/time.h>
#include <mach/map.h>
#include <mach/regs-irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <mach/regs-irq.h>
#include <plat/regs-timer.h>

#define DEVICE_NAME "CL_beep"

#define BEEP_MAJOR 233

static int CL_beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long temp;
unsigned long gpbcon;
unsigned long tcfg0;
unsigned long tcfg1;
unsigned long tcntb;
unsigned long tcmpb;
unsigned long tcon;
struct clk *clk_p;
unsigned long pclk;

printk("Kernel info: cmd=%d....\n", cmd);
if (cmd <= 0) {
temp = __raw_readl(S3C2410_GPBCON);
temp &= ~3;
temp |= 1; /*管脚功能定义为-输出*/
__raw_writel(temp, S3C2410_GPBCON);
temp = __raw_readl(S3C2410_GPBDAT);
temp &= ~1;
__raw_writel(temp, S3C2410_GPBDAT);
} else {
gpbcon = __raw_readl(S3C2410_GPBCON);
gpbcon &= ~3;
gpbcon |= 2; /*管脚功能定义为-定时器*/
__raw_writel(gpbcon, S3C2410_GPBCON);


/*定时器输入时钟频率=PCLK/(预分频值+1)/(分频值)
=PCLK/(15+1)/(1/8) */
tcfg0 = __raw_readl(S3C2410_TCFG0);
tcfg0 &= ~0xff;
tcfg0 |= 15; /*定时器预分频值为15*/
__raw_writel(tcfg0, S3C2410_TCFG0);

tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg1 &= ~0xf;
tcfg1 |= 2; /*定时器分频值为2,即1/8分频*/
__raw_writel(tcfg1, S3C2410_TCFG1);

clk_p = clk_get(NULL, "pclk");
pclk = clk_get_rate(clk_p);
printk("Kernel info: pclk=%d\n", pclk);

if (arg == 0)
arg = 1;
tcntb = (pclk/128)/arg; /*定时器计数缓冲寄存器*/
__raw_writel(tcntb, S3C2410_TCNTB(0));
printk("Kernel info: tcntb=%d\n", tcntb);

tcmpb = tcntb>>1; /*定时器比较缓冲寄存器*/
__raw_writel(tcmpb, S3C2410_TCMPB(0));
printk("Kernel info: tcmpb=%d\n", tcmpb);

tcon = __raw_readl(S3C2410_TCON);
tcon &= ~0x1f;
tcon |= 0x0b;
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~2; /*这里比较特殊,此为必须在下次写操作时清零!*/
__raw_writel(tcon, S3C2410_TCON);
}

return 0;
}

static struct file_operations CL_beep_fops = {
.owner = THIS_MODULE,
.ioctl = CL_beep_ioctl,
};


static struct class *beep_class;

static int __init CL_beep_init(void)
{
int ret;

/*注册字符设备驱动程序*/
ret = register_chrdev(BEEP_MAJOR, DEVICE_NAME, &CL_beep_fops);
if (ret) {
printk(DEVICE_NAME" can`t register major number.\n");
return ret;
}

/*注册一个类,使mdev可以在/dev目录下创建设备节点*/
beep_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(beep_class)) {
printk("Err: create class failed.\n");
return -1;
}

/*创建一个设备节点,节点名为DEVICE_NAME*/
device_create(beep_class, NULL, MKDEV(BEEP_MAJOR, 0), NULL, DEVICE_NAME);

printk(DEVICE_NAME" initialized.\n");

return 0;
}


static void __exit CL_beep_exit(void)
{
unregister_chrdev(BEEP_MAJOR, DEVICE_NAME);

printk(DEVICE_NAME" exit!\n");
}

module_init(CL_beep_init);
module_exit(CL_beep_exit);

MODULE_AUTHOR("Cl learning...");
MODULE_DESCRIPTION("[2016-02-22] Cl Time0 for PWM test");
MODULE_LICENSE("GPL");



2.应用程序;


#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>

#define DEVICE_NAME "/dev/CL_beep"

int main(int argc, char *argv[])
{

int fd;
int i;
int cmd = 1;
unsigned long temp = 0;

fd = open(DEVICE_NAME, O_RDWR);
if (fd < 0){
perror("open fail:");
exit(1);
}

while(1){
scanf("%d", &temp);
printf("temp = %d\n", temp);
ioctl(fd, cmd, temp);
if (temp == 0)
break;
}

close(fd);

return 0;
}