mini2440驱动分析之pwm


1. pwm驱动也是作为杂项设备注册的,同样为了防止并发造成的竞态,有个信号量保护。模块的初始化函数
  1. static int __init dev_init(void)  
  2. {  
  3.     int ret;  
  4.   
  5.     init_MUTEX(&lock);  
  6.     ret = misc_register(&misc);  
  7.   
  8.     printk (DEVICE_NAME"\tinitialized\n");  
  9.         return ret;  
  10. }  
这个函数就是初始化了一个信号量,然后调用misc_register注册到杂项设备   2. 这个pwm驱动的基本功能体现在ioctl方法上
  1. static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
  2. {  
  3.     //printk("ioctl pwm: %x %lx\n", cmd, arg);  
  4.     switch (cmd) {  
  5.     case PWM_IOCTL_SET_FREQ:  
  6.         if (arg == 0)  
  7.             return -EINVAL;  
  8.         PWM_Set_Freq(arg);  
  9.         break;  
  10.   
  11.   
  12.     case PWM_IOCTL_STOP:  
  13.         PWM_Stop();  
  14.         break;  
  15.     }  
  16.     return 0;  
  17. }  
可以看出,只提供两个选项,一个是设置频率(调用PWM_Set_Freq函数),一个是停止。其他的功能都没有,这充分体现驱动程序中 “提供机制而不是提供策略”的思想,驱动程序中只提供基本的功能实现,其他复杂的功能由应用程序提供。
3. PWM_Set_Freq(arg)函数分析  
  1. static void PWM_Set_Freq( unsigned long freq )  
  2. {  
  3.     unsigned long tcon;  
  4.     unsigned long tcnt;  
  5.     unsigned long tcfg1;  
  6.     unsigned long tcfg0;  
  7.   
  8.   
  9.     struct clk *clk_p;  
  10.     unsigned long pclk;  
  11.   
  12.   
  13.     //set GPB0 as tout0, pwm output  
  14.     s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);  
  15.   
  16.   
  17.     tcon = __raw_readl(S3C2410_TCON);  
  18.     tcfg1 = __raw_readl(S3C2410_TCFG1);  
  19.     tcfg0 = __raw_readl(S3C2410_TCFG0);  
  20.   
  21.   
  22.     //prescaler = 50  
  23.     tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;  
  24.     tcfg0 |= (50 - 1);   
  25.   
  26.   
  27.     //mux = 1/16  
  28.     tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;  
  29.     tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;  
  30.   
  31.   
  32.     __raw_writel(tcfg1, S3C2410_TCFG1);  
  33.     __raw_writel(tcfg0, S3C2410_TCFG0);  
  34.   
  35.   
  36.     clk_p = clk_get(NULL, "pclk");  
  37.     pclk  = clk_get_rate(clk_p);  
  38.     tcnt  = (pclk/50/16)/freq;  
  39.       
  40.     __raw_writel(tcnt, S3C2410_TCNTB(0));  
  41.     __raw_writel(tcnt/2, S3C2410_TCMPB(0));  
  42.                   
  43.     tcon &= ~0x1f;  
  44.     tcon |= 0xb;        //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0  
  45.     __raw_writel(tcon, S3C2410_TCON);  
  46.       
  47.     tcon &= ~2;         //clear manual update bit  
  48.     __raw_writel(tcon, S3C2410_TCON);  
  49. }  
主要是对操作pwm的寄存器进行设置,跟裸机的设置一样,但是可以看出,驱动程序中设置寄存器都是采用读修改写的方式进行的。 像S3C2410_TCON S3C2410_TCFG1_MUX0_MASK 都是在regs-timer.h中定义的,直接使用就可以了。

相关内容