嵌入式linux驅動開發流程

轉載自http://blog.163.com/qwz_007@126/blog/static/3701811920141895541695/,感謝原做者
嵌入式linux驅動開發流程
嵌入式系統中,操做系統是經過各類驅動程序來駕馭硬件設備的。設備驅動程序是操做系統內核和硬件設備之間的接口,它爲應用程序屏蔽了硬件的細節,這樣在應用程序看來,硬件設備只是一個設備文件,能夠像操做普通文件同樣對硬件設備進行操做。設備驅動程序是內核的一部分,完成如下功能:
◇ 驅動程序的註冊和註銷。
◇ 設備的打開和釋放。
◇ 設備的讀寫操做。
◇ 設備的控制操做。
◇ 設備的中斷和輪詢處理。
Linux主要將設備分爲三類:字符設備、塊設備和網絡設備。字符設備是指發送和接收數據以字符的形式進行,沒有緩衝區的設備;塊設備是指發送和接收數據以整個數據緩衝區的形式進行的設備;網絡設備是指網絡設備訪問的BSD socket 接口。下面以字符設備爲例,寫出其驅動編寫框架:
1、 編寫驅動程序初始化函數
  驅動程序的初始化在函數xxx_init()中完成,包括對硬件初始化、中斷函數、向內核註冊驅動程序等。
  首先理解硬件結構,搞清楚其功能,接口寄存器以及CPU怎麼訪問控制這些寄存器等。
  其次向內核註冊驅動程序。設備驅動程序能夠直接編譯進內核,在系統啓動的時候初始化,也能夠在須要的時候以模塊的方式動態加載到內核中去。每一個字符設備或是塊設備都是經過register_chrdev()函數註冊,調用該函數後就能夠向系統申請主設備號,操做成功,設備名就會出如今/proc/devices裏。
  此外,在關閉設備時,須要先解除原先設備的註冊,須要有清除函數,在xxx_exit()中經過unregister_chrdev()函數在實現,此後設備就會從/proc/devices裏消失。
  當驅動程序被編譯成模塊時,使用insmod加載模塊,模塊的初始化函數xxx_init()被調用,向內核註冊驅動程序;使用rmmod卸載模塊,模塊的清除函數xxx_exit()被調用。
2、 構造file_operations結構中要用到的各個成員函數
  Linux操做系統將全部的設備都當作文件,以操做文件的方式訪問設備。應用程序不能直接操做硬件,使用統一的接口函數調用硬件驅動程序,這組接口被成爲系統調用。每一個系統調用中都有一個與之對應的函數(open、release、read、write、ioctl等),在字符驅動程序中,這些函數集合在一個file_operations類型的數據結構中。以一個鍵盤驅動程序爲例:
struct file_operations Key7279_fops =  
{
.open = Key7279_Open,  
.ioctl = Key7279_Ioctl,  
.release = Key7279_Close,
.read = Key7279_Read,
};
一、 設備的打開和釋放
  打開設備是由open()函數來完成,在大部分設備驅動中open完成以下工做:
  ◇ 遞增計數器
  ◇ 檢查特定設備的特殊狀況
  ◇ 初始化設備
  ◇ 識別次設備號
  釋放設備由release()函數來完成。當一個進程釋放設備時,其它進程還能繼續使用該設備,只是該進程暫時中止對該設備的的使用,而當一個進程關閉設備時,其它進程必須從新打開此設備才能使用。Release完成以下工做:
◇ 遞減計數
◇ 在最後一次釋放設備操做時關閉設備
二、 設備的讀寫操做
  讀寫設備的主要任務就是把內核空間的數據複製到用戶空間,或者是從用戶空間複製到內核空間,也就是將內核空間緩衝區裏的數據複製到用戶空間的緩衝區中或者相反。字符設備使用各自的read()函數和write()函數來進行數據讀寫。
三、 設備的控制操做
大部分設備除了讀寫能力,還可進行超出簡單的數據傳輸以外的操做,因此設備驅動也必須具有進行各類硬件控制操做的能力. 這些操做經常經過 ioctl 方法來支持。與讀寫操做不一樣,ioctl()的用法與具體設備密切相關。以鍵盤Key7279_Ioctl爲例:
static int Key7279_Ioctl(struct inode *inode,struct file *file,unsigned int cmd, unsigned long arg)
{
switch(cmd)  
  {
  case Key7279_GETKEY:
return key7279_getkey();
  default:
  printk("Unkown Keyboard Command ID.\n");
  }
  return 0;
}
  cmd的取值及含義都與具體的設備有關,除了ioctl(),設備驅動程序還可能有其餘控制函數,好比llseek()等。
  當應用程序使用open、release等函數打開某個設備時,設備驅動程序的file_operations結構中的相應成員就會被調用。
3、設備的中斷和輪詢處理
  對於不支持中斷的設備,讀寫時須要輪詢設備狀態,以及是否須要繼續進行數據傳輸。例如,打印機。若是設備支持中斷,則可按照中斷方式進行。
模塊在使用中斷前要先請求一箇中斷通道(或者 IRQ中斷請求),並在使用後釋放它。經過request_irq()函數來註冊中斷,free_irq()函數來釋放。
4、驅動程序的測試
  對驅動程序的調試能夠經過打印的方式來進行,就是經過在驅動程序中添加printk()打印函數,來跟蹤驅動程序的執行過程,以此來判斷問題。
  以上是我根據本身的學習總結的,可能寫的比較簡單,對於比較複雜的驅動函數,會添加更多的函數,可是大致的框架就是這樣了。