linux UART串口驅動開發(fā)文檔
順帶介紹開關中斷接口:
static void w83697uart_start_tx(struct uart_port *port, unsigned int tty_start)
static void w83697uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
函數(shù): static void w83697uart_int(int irq, void *dev_id, struct pt_regs *regs)
描述: 中斷處理函數(shù),為3個使用系統(tǒng)外部中斷的的串口的中斷入口,其中必須處理的中斷狀態(tài)分為如下幾種, 注意必須在處理中斷時根據(jù)手冊中的說明來清除中斷,通常是讀或寫某些寄存器即可。
接收中斷.
傳送中斷.
FIFO超時中斷.
其它不具體處理的中斷,必須讀相應寄存器清中斷.
函數(shù): static void w83697uart_int2(int irq, void *dev_id, struct pt_regs *regs)
描述: 中斷處理函數(shù),為另外幾個使用串口使用的GPIO中斷入口,GPIO中斷共享同一個系統(tǒng)中斷向量, 必須根據(jù)GPIO的中斷狀態(tài)寄存器的相應位來判斷對應的中斷是屬哪一個串口的,從而進行相應的處理,其實這個判斷也是無所謂的,因為中斷產生時傳進來的參數(shù)已經含有了相應串口的參數(shù), 在判斷完中斷產生的GPIO口后立即調用w83697uart_int2 完成具體的中斷處理.
函數(shù): static int w83697uart_startup(struct uart_port *port)
描述: 串口開啟后的初始化函數(shù),主要完成初始化配置,以及安裝中斷處理了函數(shù),初始化配置包括打開中斷使能標志。
函數(shù): static void w83697uart_shutdown(struct uart_port *port)
描述: 串口關閉函數(shù),清除配置,半閉中斷.
函數(shù): static void w83697uart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
描述: 配置函數(shù),經由上次調用下來,主要配制串口的波特率比,以及各種容錯處理,在串口打開初始化時會被調用,在必變串口波特率/校驗方式/停止位/傳送位數(shù)等參數(shù)時會被調用.
5. 串口驅動與上層的接口關聯(lián)
文件: linux-2.4.21/drivers/serial/core.c
這一層接口是串口驅動中的共用部分代碼, 核心結構為struct uart_driver. 這一層上承TTY終端,下啟串口底層,串口底層主要處理了與串口硬件相關的部分,并向上提供uart中間層向下的接口. Uart coar向下與底層驅動的接口,通過一個static struct uart_ops amba_pops結構完成? 這個結構直接賦值給串口struct uart_amba_port amba_ports 的.ops成員,最后將串口的port加入到uart_driver當中完成關聯(lián), 通過uart_add_one_port加入.
static int __init w83697uart_init(void)
{
int ret, i;
ret = uart_register_driver(amba_reg);
if (ret == 0) {
for (i = 0; i UART_NR; i++)
uart_add_one_port(amba_reg, amba_ports[i].port);
}
return ret;
}
二. Linux的中斷機制及中斷共享機制.
前面講到了有6個串口,除了w83697中的前三個串使用的是獨立的系統(tǒng)外部中斷之外,其它的在個串口是共享一個系統(tǒng)中斷向量的,現(xiàn)在我們來看看多個中斷是如何掛在一個系統(tǒng)中斷向量表當中的,共享中斷到底是什么樣的一種機制?
進行分析代碼可知,linux下的中斷采用的是中斷向量的方式,每一個中斷對應一個中斷描述數(shù)組當中的一項, 結構為struct irqdesc,其當中對應一成員結構為struct irqactionr 的成員action, 這個即表示此中斷向量對應的中斷處理動作,這里引用從網上下載的一幅圖講明中斷向量表與中斷動作之間的關系:
struct irqaction {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
unsigned long mask;
const char *name;
void *dev_id;
struct irqaction *next;
};
從上面的結構體與圖當中,我們就可以很清楚的看到,一個中斷向量表可以對應一個irqaction,也可能對應多個由鏈表鏈在一起的一個鏈表irqaction, 這當中主要在安裝中斷的時候通過中斷的標志位來決定:
安裝中斷處理,不可共享:
retval = request_irq(port->irq, w83697uart_int, 0, w83697_uart3, port);
安裝中斷處理,可共享:
retval = request_irq(port->irq, w83697uart_int2, SA_SHIRQ, w83977_uart5, port);
由上即可知,安裝共享中斷時,只須指定安裝的中斷標志位flag為SA_SHIRQ, 進入分析安裝中斷的處理可知,在安裝時,會檢測已經安裝的中斷是否支持共享中斷,如果不支持,則新的中斷安裝動作失敗;如果已經安裝的中斷支持共享中斷,則還必須檢測將要安裝的新中斷是否支持中斷共享,如果不支持則安裝還是會失敗,如果支持則將此新的中斷處理鏈接到此中斷向量對應的中斷動作處理鏈表當中.
在產生中斷時,共享中斷向量中對應的中斷處理程序鏈表中的每一個都會被調用,依據(jù)鏈表的次序來,這樣處理雖然會有影響到效率,但是一般情況下中斷傳到用戶的中斷處理服務程序中時,由用戶根據(jù)硬件的狀態(tài)來決定是否處理中斷,所以能常情況下都是立即就返回了,效率的影響不會是大的問題.
三. Linux的軟中斷機制.
前面已經簡單講過了LINUX下的硬中斷處理機制,其實硬中斷的處理都由LINUX底層代碼具體完成了,使用者一般在處理硬中斷時是相當簡單的,只須要用request_irq()簡單的掛上中斷即可,這里我們進一步介紹一下LINUX下的軟中斷機制,軟中斷機制相比起硬中斷機制稍微復雜一些,而且在LINUX內核本身應用非常的廣, 它作為一種軟性的異步執(zhí)行機制,只有深入理解了它才能靈活的運用.
之所以提到內核的softirq機制,主要是因為在串口中斷也使用了這些機制,理解了這些機制就能更加明白串口驅動一些問題, 現(xiàn)在先提出幾個問題如下:
前面提供到中斷接收后數(shù)據(jù),先放到flip緩沖區(qū)當中,這樣讓人很容易進一步想知道,中斷處理的緩沖區(qū)的數(shù)據(jù),用戶進程讀取串口時如何讀到的?很明顯中斷處于內核空間,用戶讀取串口輸入進程是在用戶空間,中斷緩沖區(qū)中的數(shù)據(jù)如何被處理到終端緩沖區(qū)中,供用戶讀取的?
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關文章:linux教程
評論