Yesterday, I tried setting the Timer of DM8168 to prepare the underlying driver for writing PWM. Now I am going to enter the topic.
Dm8168_pwm.c:
# Include
# Include
# Include
# Include
/* Copy_to_user, copy_from_user */# include
# Include
# Include 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 = 0xffffe0; * 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); // the resolution is slightly lower, only 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 = forward (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 (0x48038538,4); TCRR = (volatile unsigned long *) ioremap (0x4803663c, 4); TLDR = (volatile unsigned long *) ioremap (0x48044040,4); TMAR = (volatile unsigned long *) ioremap (0x4801_4c, 4); printk ("pwm is ready \ n"); return 0 ;} void pwm_exit (void) {callback (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.oCROSSCOMPILE := /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.patch2PWD :=$(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
Test Program pwm_test.c:
# Include
# Include
# Include
# Include
Int pow_10 (char m) {int j; int res = 1; for (j = 0; j
Test:
Load the module after compilation: insmod dm8168_pwm.ko
Cross-compilation test program: arm-none-linux-gnueabi-gcc-o pwm_test pwm_test.c
Run:./pwm_test 50
The 50% PWM waveform is output and the test is successful.