S3C2440 Linux UART 串口驅動-----1


Linux系統的串口驅動與一般字符設備並一樣,它采用層次化的架構,從而看做是一個串行系統來實現。

(1)      關注UART或其他底層串行硬件特征的底層驅動程序。

(2)      和底層驅動程序接口的TTY驅動程序。

(3)      加工用於和TTY驅動程序交換數據的線路規程。

下圖描述了串行系統間的層次結構關系(s3c2440串口實現例),可以概括為:用戶應用層 --> 線路規划層 --> TTY層 --> 底層驅動層 --> 物理硬件層

 

線路規程和TTY驅動程序是與硬件平台無關的,Linux源碼中已經提供了實現,所以對於具體的平台,我們只需實現底層驅動程序即可,這也是我們最關心的。在s3c2440a中,主要由dirivers/serial/下的s3c2440.c和samsung.c實現。

Uart驅動程序主要圍繞三個關鍵的數據結構展開(include/linux/serial_core.h中定義):

UART特定的驅動程序結構定義:struct uart_driver s3c24xx_uart_drv;

UART端口結構定義: struct uart_port s3c24xx_serial_ops;

UART相關操作函數結構定義: struct uart_ops s3c24xx_serial_ops;

基於以上三個結構體,來看看s3c2440是如何掛接到Linux中串口構架的:

S3c2440串口相關操作函數定義在s3c24xx_serial_ops中,這個是一個struct uart_ops結構,這個結構體在dirivers/serial/samsung.c中

[cpp] view plaincopy
  1. static struct uart_ops s3c24xx_serial_ops ={  
  2.       .pm         =s3c24xx_serial_pm,   //電源管理函數  
  3.       .tx_empty       = s3c24xx_serial_tx_empty, //檢車發送FIFO緩沖區是否空  
  4.       .get_mctrl       = s3c24xx_serial_get_mctrl, //是否串口流控  
  5.       .set_mctrl       = s3c24xx_serial_set_mctrl, //是否設置串口流控cts  
  6.        .stop_tx   =s3c24xx_serial_stop_tx,  //停止發送  
  7.        .start_tx   =s3c24xx_serial_start_tx,  //啟動發送  
  8.        .stop_rx   =s3c24xx_serial_stop_rx,   //停止接收  
  9.       .enable_ms     = s3c24xx_serial_enable_ms, //空函數  
  10.       .break_ctl       = s3c24xx_serial_break_ctl,   //發送break信號  
  11.        .startup    =s3c24xx_serial_startup,   //串口發送/接收,以及中斷申請初始配置函數  
  12.       .shutdown       = s3c24xx_serial_shutdown,  //關閉串口  
  13.       .set_termios    = s3c24xx_serial_set_termios,//串口clk,波特率,數據位等參數設置  
  14.       .type             = s3c24xx_serial_type,  // CPU類型關於串口  
  15.        .release_port   =s3c24xx_serial_release_port,  //釋放串口  
  16.        .request_port   =s3c24xx_serial_request_port, //申請串口  
  17.       .config_port    = s3c24xx_serial_config_port,  //串口的一些配置信息info  
  18.       .verify_port    = s3c24xx_serial_verify_port,  //串口檢測  
  19. };  

驅動程序結構定義:

[cpp] view plaincopy
  1. static struct uart_driver s3c24xx_uart_drv= {  
  2.       .owner           =THIS_MODULE,  
  3.       .dev_name      = "s3c2440_serial",  //具體設備名稱  
  4.       .nr          =CONFIG_SERIAL_SAMSUNG_UARTS,  //定義有幾個端口  
  5.       .cons             = S3C24XX_SERIAL_CONSOLE,  //console接口  
  6.        .driver_name  =S3C24XX_SERIAL_NAME,  //串口名:ttySAC  
  7.       .major            =S3C24XX_SERIAL_MAJOR,  //主設備號  
  8.       .minor            =S3C24XX_SERIAL_MINOR,   //次設備號  
  9. };  

端口配置結構定義,其中包括了一個structuart_ports結構:

[cpp] view plaincopy
  1. struct s3c24xx_uart_port {  
  2.       unsigned char               rx_claimed;  
  3.       unsigned char               tx_claimed;  
  4.       unsigned int                 pm_level;  
  5.       unsigned long              baudclk_rate;  
  6.    
  7.       unsigned int                 rx_irq;  
  8.       unsigned int                 tx_irq;  
  9.    
  10.       struct s3c24xx_uart_info       *info;  
  11.       struct s3c24xx_uart_clksrc     *clksrc;  
  12.       struct clk              *clk;  
  13.       struct clk              *baudclk;  
  14.       struct uart_port            port;  
  15.    
  16. #ifdef CONFIG_CPU_FREQ  
  17.       struct notifier_block            freq_transition;  
  18. #endif  
  19. };  
  20. static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {  
  21.        [0]= {  //串口0  
  22.              .port= {  
  23.                     .lock             =__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),  
  24.                     .iotype           =UPIO_MEM,  //  
  25.                     .irq         =IRQ_S3CUART_RX0,   //中斷號  
  26.                     .uartclk   = 0,   //時鍾值  
  27.                     .fifosize   = 16,   //定義FIFO緩存區大小  
  28.                     .ops        = &s3c24xx_serial_ops, //串口相關操作函數  
  29.                     .flags            = UPF_BOOT_AUTOCONF,  
  30.                     .line        = 0, //線路1  
  31.              }  
  32.        },  
  33.        [1]= {//串口1  
  34.              .port= {  
  35.                     .lock             =__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),  
  36.                     .iotype           = UPIO_MEM,  
  37.                     .irq         = IRQ_S3CUART_RX1,  
  38.                     .uartclk   = 0,  
  39.                     .fifosize   = 16,  
  40.                     .ops        = &s3c24xx_serial_ops,  
  41.                     .flags            = UPF_BOOT_AUTOCONF,  
  42.                     .line        = 1,  
  43.              }  
  44.        },  
  45. #if CONFIG_SERIAL_SAMSUNG_UARTS > 2  
  46.    
  47.        [2]= {//串口2  
  48.              .port= {  
  49.                     .lock             =__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),  
  50.                     .iotype           = UPIO_MEM,  
  51.                     .irq         = IRQ_S3CUART_RX2,  
  52.                     .uartclk   = 0,  
  53.                     .fifosize   = 16,  
  54.                     .ops        =&s3c24xx_serial_ops,  
  55.                     .flags            = UPF_BOOT_AUTOCONF,  
  56.                     .line        = 2,  
  57.              }  
  58.        },  
  59. #endif  
  60. };  

綜上所述,s3c2440主要是實現這三個數據結構: 

s3c24xx_serial_ops,  s3c24xx_uart_drv,  s3c24xx_uart_ports3c24xx_serial_ports

下篇將進一步結合源碼探討ARM-Linuxs3c2440 的實現。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com