mini2440驱动分析之pwm

1. pwm驱动也是作为杂项设备注册的,同样为了防止并发造成的竞态,有个信号量保护。模块的初始化函数

static int __init dev_init(void)   {       int ret;          init_MUTEX(&lock);       ret = misc_register(&misc);          printk (DEVICE_NAME"\tinitialized\n");           return ret;   }  

这个函数就是初始化了一个信号量,然后调用misc_register注册到杂项设备

 

2. 这个pwm驱动的基本功能体现在ioctl方法上

static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)   {       //printk("ioctl pwm: %x %lx\n", cmd, arg);       switch (cmd) {       case PWM_IOCTL_SET_FREQ:           if (arg == 0)               return -EINVAL;           PWM_Set_Freq(arg);           break;             case PWM_IOCTL_STOP:           PWM_Stop();           break;       }       return 0;   }  

可以看出,只提供两个选项,一个是设置频率(调用PWM_Set_Freq函数),一个是停止。其他的功能都没有,这充分体现驱动程序中 “提供机制而不是提供策略”的思想,驱动程序中只提供基本的功能实现,其他复杂的功能由应用程序提供。


3. PWM_Set_Freq(arg)函数分析

 

static void PWM_Set_Freq( unsigned long freq )   {       unsigned long tcon;       unsigned long tcnt;       unsigned long tcfg1;       unsigned long tcfg0;             struct clk *clk_p;       unsigned long pclk;             //set GPB0 as tout0, pwm output       s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);             tcon = __raw_readl(S3C2410_TCON);       tcfg1 = __raw_readl(S3C2410_TCFG1);       tcfg0 = __raw_readl(S3C2410_TCFG0);             //prescaler = 50       tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;       tcfg0 |= (50 - 1);              //mux = 1/16       tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;       tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;             __raw_writel(tcfg1, S3C2410_TCFG1);       __raw_writel(tcfg0, S3C2410_TCFG0);             clk_p = clk_get(NULL, "pclk");       pclk  = clk_get_rate(clk_p);       tcnt  = (pclk/50/16)/freq;              __raw_writel(tcnt, S3C2410_TCNTB(0));       __raw_writel(tcnt/2, S3C2410_TCMPB(0));                          tcon &= ~0x1f;       tcon |= 0xb;        //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0       __raw_writel(tcon, S3C2410_TCON);              tcon &= ~2;         //clear manual update bit       __raw_writel(tcon, S3C2410_TCON);   }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzpfy.html