linux虛擬串口控制器實現---適用於無開發板學習tty driver

在前面幾章,我們介紹了tty子系統的框架、數據結構、tty驅動的註冊與註銷等內容,本章我們藉助

之前學習的內容開發一個虛擬的串口控制器驅動,以便我們理解開發串口驅動的步驟及驅動開發實踐。

本次實現的虛擬串口主要是藉助tty_register_driver、tty_port_register_device實現,而不是藉助

uart_register_driver、uart_add_one_port,等我們後面介紹了uart子系統之後,再借助

uart_register_driver、uart_add_one_port實現一次虛擬串口。


本次虛擬串口實現的功能

  1. 虛擬串口的名稱為vttyM(如串口0,則為/dev/vttyM0);
  2. 應用程序可通過打開設備文件/dev/vttyM0,實現對串口vttyM0的讀寫操作;
  3. /dev/vttyM0支持loopback模式,即應用程序通過/dev/vttyM0打開串口後,向串口寫入數據後,vttyM0則會將寫入的數據作為接收數據,再刷新到串口中;
  4. 可通過sysfs,通過設置/sys/class/tty/vttyM0/vtty_loopback屬性,進行loopback模式的開啟與關閉(默認開啟loopback模式);
  5. 可通過sysfs文件系統,通過向/sys/class/tty/vttyM0/vtty_receive_buff中寫入數據,來模擬vttM0串口的數據接收,如echo "vtty test" >vtty_receive_buff,則表示串口接收到數據“vtty test”,此時若讀取/dev/vttyM0,則可以獲取到數據“vtty test”

本次虛擬串口實現涉及的知識點

  1. 藉助platform device接口,實現虛擬串口端口對應platfomr的創建(如實現vttyM0、vttyM1兩個串口,則創建對應的兩個platform device);
  2. 藉助platform driver接口,實現platform device對應的driver,在platform driver的probe接口中,調用tty_port_register_device完成tty端口及其對應字符設備的註冊
  3. 藉助sysfs_create_group,創建tty端口對應的sysfs屬性文件,實現loopback的控制以及模擬串口接收數據的模擬;
  4. 藉助tty_register_driver,完成虛擬tty 控制器驅動的註冊,並實現對應的接口

下面詳細說明實現步驟

Platform device的實現

在本次代碼實現中,主要實現了兩個虛擬串口,因此創建了兩個platform device,其中struct virtual_tty_port_platform_config定義了每一個端口的信息,此處主要定義了tty端口的index,而platform driver與platform dev匹配的條件即為plaform device的名稱"virtual_tty_port_dev"

linux虛擬串口控制器實現---適用於無開發板學習tty driver


Platform driver的實現

Platform driver的定義如下,該platform driver的名稱為"virtual_tty_port_dev",基於名稱匹配檢測,即可完成platform driver與platform device的匹配。

當platform driver與platform device匹配後,則調用其probe接口進行探測操作,而在virtual_tty_port_platform_probe接口中,主要實現如下功能:

  1. 創建 struct virtual_tty_port *port變量,作為本驅動的tty_port相關數據結構類型變量,為該tty端口創建一個fifo,用於存儲寫入到虛擬串口中的數據;
  2. 創建一個工作隊列,並設置工作隊列對應的callback為virtual_tty_flush_to_port,當線路規程的寫接口調用tty_driver的write_buff接口後,在write_buff接口中,將數據刷到tty port的fifo中,然後喚醒該工作隊列,由工作隊列的回調函數進行寫操作(因我們的虛擬串口不支持中斷,此處由工作隊列進行模擬)
  3. 調用tty_port_register_device,註冊該tty端口及其對應的字符設備;
  4. 調用sysfs_create_group,為該tty端口對應的device創建屬性文件,主要是/sys/class/tty/vttyM0/vtty_loopback、/sys/class/tty/vttyM0/vtty_receive_buff
linux虛擬串口控制器實現---適用於無開發板學習tty driver

通過platform driver 的probe,即完成tty端口的註冊,而tty端口的操作接口,主要定義瞭如下幾個:

當打開tty端口時,將該端口的loopback模式設置為true,即打開其loopback模式,這樣應用程序打開一個串口後,即可對該串口先進行寫操作,再進行讀操作了。而在關閉一個tty端口時,則關閉loopback模式,同時提供了tty端口內存的釋放接口,這個主要是藉助device的kref實現的。

linux虛擬串口控制器實現---適用於無開發板學習tty driver


Tty driver的註冊

Tty driver的代碼如下,其中tty端口的名稱前綴為vttyM,tty的類型為串口,該tty driver提供的操作接口包括open、close、write、hangup、write_room、install、remove、set_termios等。

具體功能說明如下:

  1. open接口主要是打開一個tty端口,主要就是對tty_port_open,而在該接口中,會初始化該tty端口的接收緩存、tty_port與struct tty_struct的關聯等等操作
  2. write接口用於向該tty端口寫數據,在本驅動中,即將數據緩存到kfifo中,然後調用schedule_work,由我們註冊工作隊列進行寫操作;
  3. hangup用於掛起一個tty端口,主要調用tty_port_hangup實現掛起操作;
  4. install主要建立tty_struct與tty_driver的關聯,內部主要調用tty_standard_install實現,同時設置tty_struct->driver_data指向該tty端口對應的struct virtual_tty_port ,實現將tty_struct與我們的端口相關的私有數據變量的關聯;
  5. remove用於移除tty_struct與tty_driver的關聯,此處則主要設置driver->ttys[tty->index] = NULL
  6. cleanup主要進行資源的釋放,此處主要是減少對struct virtual_tty_port 的引用計數;
  7. virtual_tty_set_termios則主要是設置字節寬度、波特率等信息,若是真實的串口,此處應該根據串口控制器的數據手冊進行設置。
linux虛擬串口控制器實現---適用於無開發板學習tty driver


設備屬性文件的實現

主要是在sysfs文件系統下創建device相關的屬性文件,此處主要是設置loopback模式以及模擬虛擬串口接收數據的功能,定義如下:

對於模擬接收數據的功能,主要是調用tty_insert_flip_char實現將數據寫入到tty端口中,並調用

tty_flip_buffer_push實現將數據刷到對應線路規程的buffer中,關閉數據讀寫的流程,可參考我上一篇文章,此處不再細說。

linux虛擬串口控制器實現---適用於無開發板學習tty driver

下面是測試截圖:

通過sysfs下設備屬性文件,模擬串口接收數據

linux虛擬串口控制器實現---適用於無開發板學習tty driver

然後在應用程序讀取串口接收的數據

linux虛擬串口控制器實現---適用於無開發板學習tty driver


完成以上功能後,基本上完成了一個虛擬的串口控制器以及虛擬串口讀寫的實現,該代碼可用來學習

串口驅動的使用,而在實際的串口中,主要是在寫函數與讀函數上有所不同,一般串口的讀寫均是通過中斷實現的,而且也可以進行流控、串口波特率設置等內容,完整的代碼後續會上傳到csdn上,後面我會把鏈接貼上。本篇的內容主要是實現一個模擬的串口控制器及串口的實現,熟悉了tty_driver、tty_port的註冊與註銷後,下一章學習uart子系統也會有所幫助。


分享到:


相關文章: