linux驅動子系統--TTY
tty目錄下的8250指的是intel的8250系列串列埠晶片驅動目錄;8250系列包括8250,16450,16450A等。
【struct uart_port解析】
flag串列埠屬性標誌,以下是解釋
#define UPF_FOURPORT 4埠串列埠卡,8250系列
#define UPF_SAK 當串列埠接收到break訊號時終止在當前虛擬終端上執行的所有程序(包括X視窗)。這個組合鍵被稱為“安全訪問鍵“(SAK). <Alt><SysRq><k>
#define UPF_SPD_MASK 波特率掩碼
#define UPF_SPD_HI 當設定波特率的引數非法時,預設其為57600
#define UPF_SPD_VHI 當設定波特率的引數非法時,預設其為115200
#define UPF_SPD_CUST 當期望波特率為38400時,如果UPF_SPD_HI和UPF_SPD_VHI同時被指定,則波特率除數由port->custom_divisor指定,這個用不到
#define UPF_SPD_SHI 當設定波特率的引數非法時,預設其為230400
#define UPF_SPD_WARP 當設定波特率的引數非法時,預設其為460800
#define UPF_SKIP_TEST 調過檢測串列埠是否存在,當前只有8250系列驅動在用
#define UPF_AUTO_IRQ 串列埠中斷號由port->ops->config_port()自動探測
#define UPF_HARDPPS_CD 支援硬體秒脈衝檢測
#define UPF_LOW_LATENCY 串列埠接收到資料後是否立即傳遞到line discipline處理
#define UPF_BUGGY_UART 古怪的串列埠???一般不用
#define UPF_NO_TXEN_TEST 不進行傳輸使能檢測
#define UPF_MAGIC_MULTIPLIER 波特率除數計算時不通過uart_get_divisor()來獲得,而是直接指定
#define UPF_CONS_FLOW 具有流控功能
#define UPF_SHARE_IRQ 與其他裝置共享中斷號,未用到
#define UPF_EXAR_EFR 串列埠為8250系列XR17D15x晶片,它的Extended Features Register位置和普通8250系列不一樣
#define UPF_BUG_THRE 8250系列串列埠,存在THRE的bug
#define UPF_FIXED_TYPE 串列埠型別是固定的,否則由port->ops->config_port()來探測
#define UPF_BOOT_AUTOCONF 是否在串列埠註冊時自動配置(呼叫port->ops->config_port())
#define UPF_FIXED_PORT 串列埠型別屬性註冊後就不可以改變
#define UPF_DEAD 置位表示串列埠已通過uart_remove_one_port()移除,uart_add_one_port()時該位清除
#define UPF_IOREMAP 串列埠訪問資源需要進行IOREMAP操作
#define UPF_CHANGE_MASK 串列埠屬性型別變更時flag標誌需變更的位元位掩碼
#define UPF_USR_MASK 使用者可以修改的位元位掩碼
mctrl 當前串列埠控制狀態,主要由串列埠驅動核心在使用,他的標誌位如下
TIOCM_LE ???
TIOCM_DTR 終端裝置已準備好
TIOCM_RTS 終端裝置請求傳送資料
TIOCM_ST
TIOCM_SR
TIOCM_CTS 允許終端裝置傳送資料過來
TIOCM_CAR / TIOCM_CD 線路上已檢測到載波
TIOCM_RNG / TIOCM_RI 通知終端裝置,modem已被呼叫
TIOCM_DSR modem已準備好
TIOCM_OUT1 / TIOCM_OUT2 這個啥用???
TIOCM_LOOP modem處於迴環模式
timeout 關斷串列埠時等待資料傳送完成的時間
type 串列埠型別,serial_core.h中定義,比如PORT_ATMEL系列為49
ops 實現硬體操作的驅動方法,寫串列埠驅動大部分程式碼在此處
custom_divisor 計算波特率除數時如果指定的波特率非法則直接使用custom_divisor, 具體參見uart_get_divisor()
line 串列埠序號,跟列印資訊,裝置號等相關
mapbase ioremap對映的地址引數,實體地址
membase ioremap之後的虛擬地址,所有對串列埠資源的訪問都是用改地址,使用readw()/writew()
iobase 直接IO指令訪問時傳遞的地址引數,intel X86系列有此功能,但是ARM架構都是通過記憶體對映訪問
serial_in 傳統的串列埠資源訪問方法,呼叫serial_port_in()訪問,驅動可以自己使用
serial_out 傳統的串列埠資源訪問方法,呼叫serial_port_out()訪問,驅動可以自己使用
set_termios 設定串列埠的屬性,現在只有8250系列晶片還在使用,該功能現在由struct uart_ops的set_termios實現
handle_irq 串列埠中斷處理函式,現在只有8250系列晶片還在使用,在該函式外面再包一層註冊中斷函式,多此一舉,所以最好的方法是不用此方法。
pm 8250系列晶片獨享,其他驅動在struct uart_ops的pm方法裡實現
irq 中斷號,既可以指定,也可以動態探測得到,取決於系統架構
irqflags 中斷函式的標誌位,註冊中斷時使用
uartclk 串列埠輸入時鐘頻率
fifosize fifo大小,一般串列埠都帶有fifo吧。。
x_char 儲存需要傳送的XON/XOFF字元時,一般上層呼叫port->ops->send_xchar,如果沒提供該方法則呼叫port->ops->start_tx(),這樣一來就基本上是在中斷函式中查詢是否需要傳送XON/XOFF字元
regshift 暫存器序號之間的地址偏移,一般設為4,但是這個用處不大
iotype 串列埠資源的類別,有UPIO_PORT、UPIO_HUB6、UPIO_MEM、UPIO_MEM32、UPIO_AU、UPIO_TSI, UPIO_PORT和UPIO_HUB6都是IO訪問型,UPIO_MEM、UPIO_MEM32是需要記憶體對映的,後三個坑爹吧,應該也是記憶體對映的,為啥要獨立出來???
unused1 確實沒用到,那麼驅動可以用來幹自己的小九九
read_status_mask 串列埠工作狀態讀取掩碼,掩碼外的狀態不處理,因此顯然這個成員是驅動用的
ignore_status_mask uart_insert_char()讀取資料時需要忽略哪些狀態位
state 指向struct uart_state,uart_state用於彙總上下層的資料結構
icount 串列埠統計計數,驅動要用到的
cons 當串列埠需要作為Printk系統列印控制檯時用到
sysrq 執行sysrq操作時的timeout時間,串列埠驅動核心自己使用,當前確定為5s,底層驅動不要賦值
dev 裝置驅動模型表示
hub6 8250系列6埠串列埠卡,指定其埠序號
suspended 串列埠是否處於休眠狀態,驅動別去碰他
irq_wake 串列埠是否處於中斷待喚醒狀態,沒怎麼用
unused 這個驅動可以用,但是不推薦
private_data 驅動特定的資料結構,貌似大家都沒用
lock 自旋鎖,驅動和串列埠核心都用,注意互斥訪問
struct uart_ops驅動操作方法:
tx_empty 傳輸緩衝區是否為空
set_mctrl 設定串列埠控制狀態
get_mctrl 獲取串列埠控制狀態
stop_tx 停止傳輸資料
start_tx 啟動傳輸資料
send_xchar 傳送XON/XOFF字元
stop_rx 停止接收資料
enable_ms 允許modem狀態中斷
break_ctl break訊號控制
startup 啟動串列埠所需的軟體資源,比如定時器、中斷註冊等
shutdown 關斷串列埠,與startup相反
flush_buffer 清空傳輸緩衝區
set_termios 設定串列埠工作模式
set_ldisc 進行線路規程相關設定
pm 電源管理操作
set_wake ???
type 查詢串列埠類別,返回字串
release_port 釋放串列埠註冊的軟體資源
request_port 申請串列埠使用的軟體資源
config_port 埠配置
verify_port 驗證使用者層的設定是否正確
ioctl 使用者ioctl操作,一般底層驅動不需要實現了,因為uart層已經實現了大部分的命令
poll_put_char 以查詢方式傳送資料
poll_get_char 以查詢方式接收資料
uart介面API
uart_add_one_port
1、通過struct uart_state和struct tty_port掛接;
2、配置埠硬體port->ops->config_port、port->ops->set_mctrl;
3、向裝置驅動核心註冊;
uart_register_driver
1、建立並初始化struct uart_driver的上層代表struct tty_driver;
2、註冊裝置號(後續使用者操作時根據裝置號就能找到對應的驅動);
3、連結到tty驅動的單鏈表中;
struct ktermios的標誌位說明
struct ktermios {
tcflag_t c_iflag; /*input mode flags */
tcflag_t c_oflag; /*output mode flags */
tcflag_t c_cflag; /*control mode flags */
tcflag_t c_lflag; /*local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
}
c_iflag:輸入模式標誌,控制終端輸入方式,具體引數如表1所示。
表1 c_iflag引數表
鍵值 |
說明 |
IGNBRK |
忽略BREAK鍵輸入 |
BRKINT |
如果設定了IGNBRK,BREAK鍵輸入將被忽略 |
IGNPAR |
忽略奇偶校驗錯誤 |
PARMRK |
標識奇偶校驗錯誤 |
INPCK |
允許輸入奇偶校驗 |
ISTRIP |
去除字元的第8個位元 |
INLCR |
將輸入的NL(換行)轉換成CR(回車) |
IGNCR |
忽略輸入的回車 |
ICRNL |
將輸入的回車轉化成換行(如果IGNCR未設定的情況下) |
IUCLC |
將輸入的大寫字元轉換成小寫字元(非POSIX) |
IXON |
允許輸入時對XON/XOFF流進行控制 |
IXANY |
輸入任何字元將重啟停止的輸出 |
IXOFF |
允許輸入時對XON/XOFF流進行控制 |
IMAXBEL |
當輸入佇列滿的時候開始響鈴 |
c_oflag:輸出模式標誌,控制終端輸出方式,具體引數如表2所示。
表2 c_oflag引數
鍵值 |
說明 |
OPOST |
處理後輸出 |
OLCUC |
將輸入的小寫字元轉換成大寫字元(非POSIX) |
ONLCR |
將輸入的NL(換行)轉換成CR(回車)及NL(換行) |
OCRNL |
將輸入的CR(回車)轉換成NL(換行) |
ONOCR |
第一行不輸出回車符 |
ONLRET |
不輸出回車符 |
OFILL |
傳送填充字元以延遲終端輸出 |
OFDEL |
以ASCII碼的DEL作為填充字元,如果未設定該引數,填充字元為NUL |
NLDLY |
換行輸出延時,可以取NL0(不延遲)或NL1(延遲0.1s) |
CRDLY |
回車延遲,取值範圍為:CR0、CR1、CR2和 CR3 |
TABDLY |
水平製表符輸出延遲,取值範圍為:TAB0、TAB1、TAB2和TAB3 |
BSDLY |
空格輸出延遲,可以取BS0或BS1 |
VTDLY |
垂直製表符輸出延遲,可以取VT0或VT1 |
FFDLY |
換頁延遲,可以取FF0或FF1 |
c_cflag:控制模式標誌,指定終端硬體控制資訊,具體引數如表3所示。
表3 c_cflag引數
鍵值 |
說明 |
CBAUD |
波特率(4+1位)(非POSIX) |
CBAUDEX |
附加波特率(1位)(非POSIX) |
CSIZE |
字元長度,取值範圍為CS5、CS6、CS7或CS8 |
CSTOPB |
設定兩個停止位 |
CREAD |
使用接收器 |
PARENB |
使能校驗 |
PARODD |
置1使用奇校驗,置0使用偶校驗 |
HUPCL |
關閉裝置時掛起 |
CLOCAL |
忽略調變解調器線路狀態 |
CRTSCTS |
使用RTS/CTS流控制 |
CMSPAR |
使用MARK/SPACE校驗方式 |
c_lflag:本地模式標誌,控制終端編輯功能,具體引數如表4所示。
表4 c_lflag引數
鍵值 |
說明 |
ISIG |
當輸入INTR、QUIT、SUSP或DSUSP時,產生相應的訊號 |
ICANON |
使用標準輸入模式 |
XCASE |
在ICANON和XCASE同時設定的情況下,終端只使用大寫。 |
ECHO |
顯示輸入字元 |
ECHOE |
如果ICANON同時設定,ERASE將刪除輸入的字元 |
ECHOK |
如果ICANON同時設定,KILL將刪除當前行 |
ECHONL |
如果ICANON同時設定,即使ECHO沒有設定依然顯示換行符 |
ECHOPRT |
如果ECHO和ICANON同時設定,將刪除打印出的字元(非POSIX) |
TOSTOP |
向後臺輸出傳送SIGTTOU訊號 |
c_cc[NCCS]:控制字元,用於儲存終端驅動程式中的特殊字元,如輸入結束符等。c_cc中定義瞭如表5所示的控制字元。
表5 c_cc支援的控制字元
巨集 |
說明 |
巨集 |
說明 |
VINTR |
Interrupt字元 |
VEOL |
附加的End-of-file字元 |
VQUIT |
Quit字元 |
VTIME |
非規範模式讀取時的超時時間 |
VERASE |
Erase字元 |
VSTOP |
Stop字元 |
VKILL |
Kill字元 |
VSTART |
Start字元 |
VEOF |
End-of-file字元 |
VSUSP |
Suspend字元 |
VMIN |
非規範模式讀取時的最小字元數 |