×
单片机 > 单片机程序设计 > 详情

ARMLinux s3c2440 之UART分析二

发布时间:2020-06-20 发布时间:
|
软件篇(linux-2.6.30.4):

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中,这个是一个structuart_ops结构

 

static struct uart_ops s3c24xx_serial_ops ={
      .pm         =s3c24xx_serial_pm,   //电源管理函数
      .tx_empty       = s3c24xx_serial_tx_empty, //检车发送FIFO缓冲区是否空
      .get_mctrl       = s3c24xx_serial_get_mctrl, //是否串口流控
      .set_mctrl       = s3c24xx_serial_set_mctrl, //是否设置串口流控cts
       .stop_tx   =s3c24xx_serial_stop_tx,  //停止发送
       .start_tx   =s3c24xx_serial_start_tx,  //启动发送
       .stop_rx   =s3c24xx_serial_stop_rx,   //停止接收
      .enable_ms     = s3c24xx_serial_enable_ms, //空函数
      .break_ctl       = s3c24xx_serial_break_ctl,   //发送break信号
       .startup    =s3c24xx_serial_startup,   //串口发送/接收,以及中断申请初始配置函数
      .shutdown       = s3c24xx_serial_shutdown,  //关闭串口
      .set_termios    = s3c24xx_serial_set_termios,//串口clk,波特率,数据位等参数设置
      .type             = s3c24xx_serial_type,  // CPU类型关于串口
       .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,  //串口检测
};

 

 

驱动程序结构定义:

 

static struct uart_driver s3c24xx_uart_drv= {
      .owner           =THIS_MODULE,
      .dev_name      = "s3c2440_serial",  //具体设备名称
      .nr          =CONFIG_SERIAL_SAMSUNG_UARTS,  //定义有几个端口
      .cons             = S3C24XX_SERIAL_CONSOLE,  //console接口
       .driver_name  =S3C24XX_SERIAL_NAME,  //串口名:ttySAC
      .major            =S3C24XX_SERIAL_MAJOR,  //主设备号
      .minor            =S3C24XX_SERIAL_MINOR,   //次设备号
};

 

 

端口配置结构定义,其中包括了一个structuart_ports结构:

 

struct s3c24xx_uart_port {
      unsignedchar               rx_claimed;
      unsignedchar               tx_claimed;
      unsignedint                 pm_level;
      unsignedlong              baudclk_rate;
 
      unsignedint                 rx_irq;
      unsignedint                 tx_irq;
 
      structs3c24xx_uart_info       *info;
      structs3c24xx_uart_clksrc     *clksrc;
      structclk              *clk;
      structclk              *baudclk;
      structuart_port            port;
 
#ifdef CONFIG_CPU_FREQ
      structnotifier_block            freq_transition;
#endif
};
static structs3c24xx_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,   //时钟值
                    .fifosize   = 16,   //定义FIFO缓存区大小
                    .ops        = &s3c24xx_serial_ops, //串口相关操作函数
                    .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,
             }
       },
#if CONFIG_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主要是实现这三个数据结构: 

s3c24xx_serial_ops,  s3c24xx_uart_drv,  s3c24xx_uart_ports3c24xx_serial_ports

下篇将进一步结合源码探讨ARM-Linuxs3c2440 的实现。

关键字:ARM  Linux  s3c2440  UART

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容