歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> S3C6410的PWM驅動實例

S3C6410的PWM驅動實例

日期:2017/3/1 10:26:45   编辑:Linux編程

我們使用PWM來控制蜂鳴器,主要是兩種功能,一是使能蜂鳴器,並設置其頻率;二是禁止蜂鳴器。這些操作均可通過ioctl來完成。所以在pwm的設備驅動中,主要也就是ioctl這個函數。

首先,我們要定義兩個命令,用在ioctl函數中的switch語句中,至於怎麼來定義這兩個命令呢?其實簡單的做法,我們可以將其定義為兩個不同的常量,能用在switch語句中即可,但是這樣會造成一定的問題。例如,其他的設備也有支持設個命令的,例如串口支持設置波特率等,很有可能在寫代碼時不小心,寫成了串口,結果調用的時候,驅動沒報錯,因為串口也支持這個命令,解決辦法就是不同的設備支持不同的命令號,及時目前有一部分驅動依舊是使用之前的那種簡單定義命令號的方式,但是我們要嚴格要求自己。

那怎麼樣才能使得自己定義的命令號不和內核已存在的命令號沖突呢?內核定義了幾個簡單的宏,使得我們使用這些宏來定義自己的命令號就肯定沒問題了。

在include/asm/ioctl.h文件裡,這些宏是:

  1. /* used to create numbers */
  2. #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
  3. #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
  4. #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
  5. #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
  6. #define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
  7. #define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
  8. #define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

其實主要使用的就是上面四個,可以看到這個宏定義中還有一個_IOC宏定義,我們來看看是啥:

  1. #define _IOC(dir,type,nr,size) \
  2. (((dir) << _IOC_DIRSHIFT) | \
  3. ((type) << _IOC_TYPESHIFT) | \
  4. ((nr) << _IOC_NRSHIFT) | \
  5. ((size) << _IOC_SIZESHIFT))<span style="font-size: 18px; ">

可以看到其實是對四個因素的結合,第一個是傳輸方向,第二個是幻數,第三個是序數,第四個是數據大小。

首先是傳輸方向,以應用為中心考察,如果數據從驅動傳輸到應用,那麼就是讀取操作,如果數據從應用傳輸到驅動,那就是寫入操作;

再者是幻數(IMAGENUMBER),這個是可以自己定義的,有8bits寬,整個驅動都使用這個數字;

然後就是序數,這個算得是幻數大類裡面的小類了,因為一個ioctl裡面一般不止一個命令,所以,這個主要是用來區別各個命令的,上面的幻數在各個命令你都是一樣的。

最後就是傳輸數據的大小,可以通過對參數使用sizeof運算符獲取。

下面來舉個例子,在我們的pwm驅動裡面有兩個命令,一個是啟動並設置頻:PWM_START,另外一個是PWM_STOP。在這個過程中不涉及數據的傳輸,所以使用上面的第一個宏_IO(type, nr)。

一個參數type是一個幻數,我們可以定義為3825:

#define PWM_MAGIC3825

然後是定義命令序列號,這裡有兩個命令,序號我分別選為0和1,因此整個可以這樣定義:

  1. #define PWM_START _IO(PWM_MAGIC, 0)
  2. #define PWM_STOP _IO(PWM_MAGIC, 1)

有了這兩個定義,我們就可以在switch中如下使用:

  1. switch(cmd)
  2. {
  3. case PWM_START:
  4. ...
  5. break;
  6. case PWM_STOP:
  7. ...
  8. break;
  9. default:
  10. ...
  11. }
Copyright © Linux教程網 All Rights Reserved