昨天把DM8168的Timer设置给摸了一遍,为写PWM的底层驱动做好了准备,现在就要进入主题了。
dm8168_pwm.c:
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h> /* copy_to_user,copy_from_user */
- #include <linux/miscdevice.h>
- #include <linux/device.h>
- #include <asm/io.h>
- static struct class *pwm_class;
- volatile unsigned long *CLK_CTL;
- volatile unsigned long *TCLR;
- volatile unsigned long *TCRR;
- volatile unsigned long *TLDR;
- volatile unsigned long *TMAR;
- int pwm_open (struct inode *inode,struct file *filp)
- {
- *CLK_CTL = 0x00000002;
- *TCLR = 0;
- *TLDR = 0xffffffe0;
- *TMAR = 0xfffffff0;
- *TCRR = 0xffffffe0;
- return 0;
- }
- ssize_t pwm_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
- {
- return 0;
- }
- ssize_t pwm_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
- {
- char duty_buf[2];
- int ret;
- ret = copy_from_user(duty_buf,buf,count);
- *TMAR = 0xffffffe0 + (unsigned char)(duty_buf[0]*30/100); //分辨率略低,仅为demo
- *TCLR = 0x1843;
- return count;
- }
- struct file_operations pwm_fops =
- {
- .owner = THIS_MODULE,
- .open = pwm_open,
- .read = pwm_read,
- .write = pwm_write,
- } ;
- int major;
- int pwm_init (void)
- {
- major = register_chrdev(0,"DM8168_PWM",&pwm_fops);
- pwm_class = class_create(THIS_MODULE, "DM8168_PWM");
- device_create(pwm_class,NULL,MKDEV(major,0),NULL,"pwm");
- CLK_CTL = (volatile unsigned long *)ioremap(0x4818157C,4);
- TCLR = (volatile unsigned long *)ioremap(0x48044038,4);
- TCRR = (volatile unsigned long *)ioremap(0x4804403C,4);
- TLDR = (volatile unsigned long *)ioremap(0x48044040,4);
- TMAR = (volatile unsigned long *)ioremap(0x4804404C,4);
- printk ("pwm is ready\n");
- return 0;
- }
- void pwm_exit (void)
- {
- unregister_chrdev(major,"DM8168_PWM");
- device_destroy(pwm_class,MKDEV(major,0));
- class_destroy(pwm_class);
- iounmap(CLK_CTL);
- iounmap(TCLR);
- iounmap(TCRR);
- iounmap(TLDR);
- iounmap(TMAR);
- printk ("module exit\n");
- return ;
- }
- MODULE_LICENSE("GPL");
- module_init(pwm_init);
- module_exit(pwm_exit);
Makefile:
- obj-m:= dm8168_pwm.o
- CROSSCOMPILE := /opt/codesourcery/arm-2009q1/bin/arm-none-linux-gnueabi-
- CC := $(CROSSCOMPILE)gcc
- KDIR:=/home/***/ti-ezsdk_dm816x-evm_5_03_01_15/board-support/linux-2.6.37-psp04.00.01.13.patch2
- PWD :=$(shell pwd)
- default:
- $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
- clean:
- rm -rf *.ko *.o .*cmd *.mod.c .tmp_versions
测试程序 pwm_test.c:
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <string.h>
- int pow_10(char m)
- {
- int j;
- int res=1;
- for(j=0;j<m;j++)
- {
- res = res * 10;
- }
- return res;
- }
- int main(int argc, char *argv[])
- {
- int fd;
- char *buf;
- char i;
- int val=0;
- fd=open("/dev/pwm",O_RDWR);
- if(fd<0)
- {
- printf("open device failed !\n");
- exit(1);
- }
- else
- {
- printf("open success ! duty_cycle : %s\n",argv[1]);
- buf=argv[1];
- buf+=strlen(argv[1])-1;
- }
- for(i=0;i<strlen(argv[1]);i++)
- {
- val += pow_10(i)*(*buf-0x30);
- buf --;
- }
- write(fd,&val,1);
- close(fd);
- return 0;
- }
测试 :
模块编译后加载:insmod dm8168_pwm.ko
交叉编译测试程序:arm-none-linux-gnueabi-gcc -o pwm_test pwm_test.c
运行:./pwm_test 50
输出为50%的PWM波形,测试成功。

浙公网安备 33010602011771号