无网不进  
软硬件开发

昨天把DM8168的Timer设置给摸了一遍,为写PWM的底层驱动做好了准备,现在就要进入主题了。

dm8168_pwm.c:

 

[javascript] view plain copy
 
  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/uaccess.h> /* copy_to_user,copy_from_user */  
  5. #include <linux/miscdevice.h>  
  6. #include <linux/device.h>  
  7. #include <asm/io.h>  
  8.   
  9. static struct class  *pwm_class;  
  10.   
  11. volatile unsigned long *CLK_CTL;  
  12. volatile unsigned long *TCLR;  
  13. volatile unsigned long *TCRR;  
  14. volatile unsigned long *TLDR;  
  15. volatile unsigned long *TMAR;  
  16.   
  17. int pwm_open (struct inode *inode,struct file *filp)  
  18.   
  19. {  
  20.     *CLK_CTL = 0x00000002;  
  21.     *TCLR    = 0;  
  22.     *TLDR    = 0xffffffe0;  
  23.     *TMAR    = 0xfffffff0;  
  24.     *TCRR    = 0xffffffe0;  
  25.     return 0;  
  26. }  
  27.   
  28. ssize_t pwm_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)  
  29. {  
  30.     return 0;  
  31. }  
  32.   
  33. ssize_t pwm_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)  
  34. {  
  35.     char duty_buf[2];  
  36.     int ret;  
  37.     ret = copy_from_user(duty_buf,buf,count);         
  38.     *TMAR    = 0xffffffe0 + (unsigned char)(duty_buf[0]*30/100);  //分辨率略低,仅为demo  
  39.     *TCLR    = 0x1843;  
  40.     return count;  
  41. }  
  42.   
  43. struct file_operations pwm_fops =  
  44. {  
  45.     .owner   = THIS_MODULE,  
  46.     .open    = pwm_open,  
  47.     .read    = pwm_read,  
  48.     .write   = pwm_write,  
  49. } ;  
  50.   
  51. int major;  
  52. int pwm_init (void)  
  53. {     
  54.       
  55.     major = register_chrdev(0,"DM8168_PWM",&pwm_fops);  
  56.     pwm_class = class_create(THIS_MODULE, "DM8168_PWM");  
  57.     device_create(pwm_class,NULL,MKDEV(major,0),NULL,"pwm");  
  58.   
  59.     CLK_CTL = (volatile unsigned long *)ioremap(0x4818157C,4);  
  60.     TCLR    = (volatile unsigned long *)ioremap(0x48044038,4);  
  61.     TCRR    = (volatile unsigned long *)ioremap(0x4804403C,4);  
  62.     TLDR    = (volatile unsigned long *)ioremap(0x48044040,4);  
  63.     TMAR    = (volatile unsigned long *)ioremap(0x4804404C,4);  
  64.     printk ("pwm is ready\n");  
  65.     return 0;  
  66. }  
  67.   
  68. void pwm_exit (void)  
  69. {  
  70.     unregister_chrdev(major,"DM8168_PWM");  
  71.     device_destroy(pwm_class,MKDEV(major,0));  
  72.     class_destroy(pwm_class);  
  73.   
  74.     iounmap(CLK_CTL);  
  75.     iounmap(TCLR);  
  76.     iounmap(TCRR);  
  77.     iounmap(TLDR);  
  78.     iounmap(TMAR);  
  79.     printk ("module exit\n");  
  80.     return ;  
  81. }  
  82.   
  83. MODULE_LICENSE("GPL");  
  84. module_init(pwm_init);  
  85. module_exit(pwm_exit);  


Makefile:

 

 

[javascript] view plain copy
 
  1. obj-m:= dm8168_pwm.o  
  2.   
  3. CROSSCOMPILE := /opt/codesourcery/arm-2009q1/bin/arm-none-linux-gnueabi-  
  4.   
  5. CC  := $(CROSSCOMPILE)gcc   
  6.   
  7. KDIR:=/home/***/ti-ezsdk_dm816x-evm_5_03_01_15/board-support/linux-2.6.37-psp04.00.01.13.patch2  
  8.   
  9. PWD :=$(shell pwd)  
  10.   
  11. default:  
  12.     $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-  
  13. clean:  
  14.     rm -rf *.ko *.o .*cmd *.mod.c .tmp_versions   

 

 

测试程序 pwm_test.c:

 

[javascript] view plain copy
 
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <fcntl.h>  
  4. #include <string.h>  
  5.   
  6. int pow_10(char m)  
  7. {  
  8.     int j;  
  9.     int res=1;  
  10.     for(j=0;j<m;j++)  
  11.     {  
  12.         res = res * 10;  
  13.     }     
  14.     return res;  
  15. }  
  16.   
  17. int main(int argc, char *argv[])  
  18. {  
  19.     int  fd;  
  20.     char *buf;  
  21.     char i;  
  22.     int  val=0;  
  23.   
  24.     fd=open("/dev/pwm",O_RDWR);  
  25.     if(fd<0)  
  26.     {  
  27.         printf("open device failed !\n");  
  28.         exit(1);  
  29.     }  
  30.     else  
  31.     {  
  32.         printf("open success ! duty_cycle : %s\n",argv[1]);  
  33.         buf=argv[1];  
  34.         buf+=strlen(argv[1])-1;  
  35.     }  
  36.   
  37.     for(i=0;i<strlen(argv[1]);i++)  
  38.     {  
  39.         val += pow_10(i)*(*buf-0x30);  
  40.         buf --;   
  41.     }  
  42.     write(fd,&val,1);  
  43.     close(fd);  
  44.     return 0;  
  45. }  


测试 :

 

模块编译后加载:insmod dm8168_pwm.ko

交叉编译测试程序:arm-none-linux-gnueabi-gcc -o pwm_test pwm_test.c

运行:./pwm_test 50

输出为50%的PWM波形,测试成功。

posted on 2018-01-10 13:48  无网不进  阅读(152)  评论(0)    收藏  举报