ARM-Linux s3c2440 之UART分析(二)
軟件篇(linux-2.6.30.4):
本文引用地址:http://www.ex-cimer.com/article/201611/318132.htmLinux系統(tǒng)的串口驅(qū)動(dòng)與一般字符設(shè)備并一樣,它采用層次化的架構(gòu),從而看做是一個(gè)串行系統(tǒng)來實(shí)現(xiàn)。
(1)關(guān)注UART或其他底層串行硬件特征的底層驅(qū)動(dòng)程序。
(2)和底層驅(qū)動(dòng)程序接口的TTY驅(qū)動(dòng)程序。
(3)加工用于和TTY驅(qū)動(dòng)程序交換數(shù)據(jù)的線路規(guī)程。
下圖描述了串行系統(tǒng)間的層次結(jié)構(gòu)關(guān)系(s3c2440串口實(shí)現(xiàn)例),可以概括為:用戶應(yīng)用層 --> 線路規(guī)劃層 -->TTY層 -->底層驅(qū)動(dòng)層 -->物理硬件層
線路規(guī)程和TTY驅(qū)動(dòng)程序是與硬件平臺無關(guān)的,Linux源碼中已經(jīng)提供了實(shí)現(xiàn),所以對于具體的平臺,我們只需實(shí)現(xiàn)底層驅(qū)動(dòng)程序即可,這也是我們最關(guān)心的。在s3c2440a中,主要由dirivers/serial/下的s3c2440.c和samsung.c實(shí)現(xiàn)。
Uart驅(qū)動(dòng)程序主要圍繞三個(gè)關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)展開(include/linux/serial_core.h中定義):
UART特定的驅(qū)動(dòng)程序結(jié)構(gòu)定義:struct uart_driver s3c24xx_uart_drv;
UART端口結(jié)構(gòu)定義: struct uart_port s3c24xx_serial_ops;
UART相關(guān)操作函數(shù)結(jié)構(gòu)定義: struct uart_ops s3c24xx_serial_ops;
基于以上三個(gè)結(jié)構(gòu)體,來看看s3c2440是如何掛接到Linux中串口構(gòu)架的:
S3c2440串口相關(guān)操作函數(shù)定義在s3c24xx_serial_ops中,這個(gè)是一個(gè)structuart_ops結(jié)構(gòu)
- staticstructuart_opss3c24xx_serial_ops={
- .pm=s3c24xx_serial_pm,//電源管理函數(shù)
- .tx_empty=s3c24xx_serial_tx_empty,//檢車發(fā)送FIFO緩沖區(qū)是否空
- .get_mctrl=s3c24xx_serial_get_mctrl,//是否串口流控
- .set_mctrl=s3c24xx_serial_set_mctrl,//是否設(shè)置串口流控cts
- .stop_tx=s3c24xx_serial_stop_tx,//停止發(fā)送
- .start_tx=s3c24xx_serial_start_tx,//啟動(dòng)發(fā)送
- .stop_rx=s3c24xx_serial_stop_rx,//停止接收
- .enable_ms=s3c24xx_serial_enable_ms,//空函數(shù)
- .break_ctl=s3c24xx_serial_break_ctl,//發(fā)送break信號
- .startup=s3c24xx_serial_startup,//串口發(fā)送/接收,以及中斷申請初始配置函數(shù)
- .shutdown=s3c24xx_serial_shutdown,//關(guān)閉串口
- .set_termios=s3c24xx_serial_set_termios,//串口clk,波特率,數(shù)據(jù)位等參數(shù)設(shè)置
- .type=s3c24xx_serial_type,//CPU類型關(guān)于串口
- .release_port=s3c24xx_serial_release_port,//釋放串口
- .request_port=s3c24xx_serial_request_port,//申請串口
- .config_port=s3c24xx_serial_config_port,//串口的一些配置信息info
- .verify_port=s3c24xx_serial_verify_port,//串口檢測
- };
驅(qū)動(dòng)程序結(jié)構(gòu)定義:
- staticstructuart_drivers3c24xx_uart_drv={
- .owner=THIS_MODULE,
- .dev_name="s3c2440_serial",//具體設(shè)備名稱
- .nr=CONFIG_SERIAL_SAMSUNG_UARTS,//定義有幾個(gè)端口
- .cons=S3C24XX_SERIAL_CONSOLE,//console接口
- .driver_name=S3C24XX_SERIAL_NAME,//串口名:ttySAC
- .major=S3C24XX_SERIAL_MAJOR,//主設(shè)備號
- .minor=S3C24XX_SERIAL_MINOR,//次設(shè)備號
- };
端口配置結(jié)構(gòu)定義,其中包括了一個(gè)structuart_ports結(jié)構(gòu):
- structs3c24xx_uart_port{
- unsignedcharrx_claimed;
- unsignedchartx_claimed;
- unsignedintpm_level;
- unsignedlongbaudclk_rate;
- unsignedintrx_irq;
- unsignedinttx_irq;
- structs3c24xx_uart_info*info;
- structs3c24xx_uart_clksrc*clksrc;
- structclk*clk;
- structclk*baudclk;
- structuart_portport;
- #ifdefCONFIG_CPU_FREQ
- structnotifier_blockfreq_transition;
- #endif
- };
- staticstructs3c24xx_uart_ports3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS]={
- [0]={//串口0
- .port={
- .lock=__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
- .iotype=UPIO_MEM,//
- .irq=IRQ_S3CUART_RX0,//中斷號
- .uartclk=0,//時(shí)鐘值
- .fifosize=16,//定義FIFO緩存區(qū)大小
- .ops=&s3c24xx_serial_ops,//串口相關(guān)操作函數(shù)
- .flags=UPF_BOOT_AUTOCONF,
- .line=0,//線路1
- }
- },
- [1]={//串口1
- .port={
- .lock=__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
- .iotype=UPIO_MEM,
- .irq=IRQ_S3CUART_RX1,
- .uartclk=0,
- .fifosize=16,
- .ops=&s3c24xx_serial_ops,
- .flags=UPF_BOOT_AUTOCONF,
- .line=1,
- }
- },
- #ifCONFIG_SERIAL_SAMSUNG_UARTS>2
- [2]={//串口2
- .port={
- .lock=__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
- .iotype=UPIO_MEM,
- .irq=IRQ_S3CUART_RX2,
- .uartclk=0,
- .fifosize=16,
- .ops=&s3c24xx_serial_ops,
- .flags=UPF_BOOT_AUTOCONF,
- .line=2,
- }
- },
- #endif
- };
綜上所述,s3c2440主要是實(shí)現(xiàn)這三個(gè)數(shù)據(jù)結(jié)構(gòu):
s3c24xx_serial_ops, s3c24xx_uart_drv, s3c24xx_uart_ports3c24xx_serial_ports
下篇將進(jìn)一步結(jié)合源碼探討ARM-Linuxs3c2440 的實(shí)現(xiàn)。
評論