Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155170
  • 博文数量: 72
  • 博客积分: 3680
  • 博客等级: 中校
  • 技术积分: 1051
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-22 13:51
文章分类
文章存档

2010年(72)

我的朋友

分类: LINUX

2010-09-24 09:01:23

1.发送和接收

发送:循环buffer à发送fifoà发送移位寄存器

接收:接收移位寄存器à接收fifo àFlip_buf

 

发送的过程是:把数据写到发送fifo中,fifo把收到的数据传给发送移位寄存器(自动的,driver控制),然后每个时钟脉冲往串口线上写一bit数据。

接收的过程是:接收移位寄存器收到数据,发送给接收fifo,接收fifo事先设置好了触发门限,当里面的数据量超过门限时就会触发一个中断,调用驱动中的中断处理函数,把数据写到flip_buf中。

 

2.寄存器

                   UART Line Control Register


 

 

Word Length :数据位长度

Number of Stop Bit :停止位数

Parity Mode :奇偶校验位类型

Infra-Red Mode UART/红外模式选择(当以UART模式工作时,需设为0”

 

 

                                               UART Control Register

Receive Mode:选择接收模式。如果是采用DMA模式的话,还需要指定说使用的DMA信道。

Transmit Mode :同上。

Send Break Signal :选择是否在传1帧资料中途发送Break信号。

Loopback Mode :选择是否将UART置于Loopback测试模式。

Rx Error Status Interrupt Enable :选择是否使能当发生接收异常时,是否产生接收错误中断。

Rx Time Out Enable :是否使能接收超时中断。

Rx Interrupt Type :选择接收中断类型。

选择0Pulse(脉冲式/边沿式中断。非FIFO模式时,一旦接收缓冲区中有数据,即产生一个中断;为FIFO模式时,一旦当FIFO中的资料达到一定的触发水平后,即产生一个中断)

选择1Level(电平模式中断。非FIFO模式时,只要接收缓冲区中有数据,即产生中断;为FIFO模式时,只有FIFO中的资料达到触发水平后,即产生中断)

Tx Interrupt Type :类同于Rx Interrupt Type

 

 

 

 

                                  UART FIFO Conrtol Register

 

FIFO Enable FIFO使能选择。
Rx FIFO Reset
:选择当复位接收FIFO时是否自动清除FIFO中的内容。
Tx FIFO Reset
:选择当复位发送FIFO时是否自动清除FIFO中的内容。
Rx FIFO Trigger Level
:选择接收FIFO的触发水平。
Tx FIFO Trigger Level
:选择发送FIFO的触发水平。

 

                 UART TX/RX Status Register

 

Receive buffer data ready :当接收缓冲寄存器从UART接收端口接收到有效资料时将自动置1”。反之为“0则表示缓冲器中没有资料。

Transmit buffer empty :当发送缓冲寄存器中为空,自动置1”;反之表明缓冲器中正有资料等待发送。

Transmitter empty :当发送缓冲器中已经没有有效资料时,自动置1”;反之表明尚有资料未发送。

                    UART FIFO Status Register

 

Rx FIFO Count :接收FIFO中当前存放的字节数。

Tx FIFO Count :发送FIFO中当前存放的字节数。

Rx FIFO Full :“1“表明接收FIFO已满。

Tx FIFO Full :“1“表明发送FIFO已满。

 

 3.函数介绍

模块初始化函数:

static int __init s3c2410uart_init(void)

{

return uart_register_driver(&s3c2410_reg);

}

使用uart_register_driver注册串口驱动。

 

static struct uart_driver s3c2410_reg = {

      owner:           THIS_MODULE,

      normal_major:   SERIAL_S3C2410_MAJOR,

      normal_name:   "ttyS%d",

      callout_name:    "cua%d",

      normal_driver:   &normal,

      callout_major:    CALLOUT_S3C2410_MAJOR,

      callout_driver:    &callout,

      table:       s3c2410_table,

      termios:   s3c2410_termios,

      termios_locked: s3c2410_termios_locked,

      minor:      MINOR_START,

      nr:       UART_NR,

      port:        s3c2410_ports,

      cons:       S3C2410_CONSOLE,

};

 

static struct uart_port   s3c2410_ports[UART_NR] = {

  {

      iobase:          (unsigned long)(UART0_CTL_BASE),

      iotype:           SERIAL_IO_PORT,

      irq:      IRQ_RXD0,

      uartclk:    130252800,

      fifosize:    16,

      ops:         &s3c2410_pops,

      type:        PORT_S3C2410,

      flags:       ASYNC_BOOT_AUTOCONF,

  },

。。。。。。     。。。。。。。      。。。。。。。

};

 

static struct uart_ops s3c2410_pops = {

         tx_empty:         s3c2410uart_tx_empty,

set_mctrl:    s3c2410uart_set_mctrl,

      get_mctrl:    s3c2410uart_get_mctrl,

      stop_tx:       s3c2410uart_stop_tx,

      start_tx:       s3c2410uart_start_tx,

      stop_rx:       s3c2410uart_stop_rx,

      enable_ms: s3c2410uart_enable_ms,

      break_ctl:    s3c2410uart_break_ctl,

      startup:        s3c2410uart_startup,

      shutdown:        s3c2410uart_shutdown,

      change_speed:     s3c2410uart_change_speed,

      type:        s3c2410uart_type,

      config_port:      s3c2410uart_config_port,

      release_port:    s3c2410uart_release_port,

      request_port:   s3c2410uart_request_port,

};

3.1 阻止发送函数uart_stop_tx

static void s3c2410uart_stop_tx(struct uart_port *port, u_int from_tty)

{

disable_irq(TX_IRQ(port));

}

停止发送的功能,其内部的函数disable_irq是停止中断的功能 ,发送数据是通过中断来完成的,关闭中断也就关闭了发送。

 

3.2 发送使能函数uart_start_tx

static void s3c2410uart_start_tx(struct uart_port *port, u_int nonempty,

u_int from_tty)

{

enable_irq(TX_IRQ(port));

}

与上面的过程类似,就是一个相反的过程

 

3.3 阻止接收函数uart_stop_rx

static void s3c2410uart_stop_rx(struct uart_port *port)

{

disable_irq(RX_IRQ(port));

}

 

 

 

 

3.4 发送缓冲空判断函数uart_tx_empty

static u_int s3c2410uart_tx_empty(struct uart_port *port)

{

return (UART_UTRSTAT(port) & UTRSTAT_TR_EMP ? 0 : TIOCSER_TEMT);

}

 

如果发送缓冲为空则返回0,否则返回1

 

3.5 获取控制信息函数uart_get_mctrl

static u_int s3c2410uart_get_mctrl(struct uart_port *port)

{

return (TIOCM_CTS | TIOCM_DSR | TIOCM_CAR);

}

获得控制信息, TIOCM_CTS ,TIOCM_DSR TIOCM_CAR,这几个宏代表串口的控制信息, 分别是clear to send,data set readydata carrier detect(详见Serial Programming Guide for POSIX Operating Systems)

 

3.6 接收中断函数uart_rx_interrupt

static void s3c2410uart_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

struct uart_info *info = dev_id;

struct tty_struct *tty = info->tty;

unsigned int status, ch, max_count = 256;

struct uart_port *port = info->port;

 

status = UART_UTRSTAT(port);

while ((status & UTRSTAT_RX_RDY) && max_count--)

{

if (tty->flip.count >= TTY_FLIPBUF_SIZE)

{

tty->flip.tqueue.routine((void *) tty);

 

if (tty->flip.count >= TTY_FLIPBUF_SIZE) {

printk(KERN_WARNING "TTY_DONT_FLIP set\n");

return;

}

}

ch = UART_URXH(port);

*tty->flip.char_buf_ptr = ch;

*tty->flip.flag_buf_ptr = TTY_NORMAL;

port->icount.rx++;

tty->flip.flag_buf_ptr++;

tty->flip.char_buf_ptr++;

tty->flip.count++;

 

status = UART_UTRSTAT(port);

}

tty_flip_buffer_push(tty);

return;

}

 

功能:主要是是while大循环,首先看循环判断条件status & UTRSTAT_RX_RDY,前面有status = UART_UTRSTAT(port),2410datasheet, status & UTRSTAT_RX_RDY这个位是判断接收buffer内是否还有有效数据?按道理一次中断只是把接收的fifobuffer中的数据放到flipbuffer中去,接收的fifo的中断门限是4-12字节,进行一次接收往往要中断好多次,这样中断开销比较大,所以在while的循环条件中判断一下是否还有接收的有效数据,如果有,就继续在中断程序中继续接收,当然,永远都在接收中断中(如果一直有数据要接收)也不合适,所以while循环还有计数,最多循环256次。

在循环中,首先是要判断一下接收数据用的flip-buffer是不是已经满了, if (tty->flip.count >= TTY_FLIPBUF_SIZE)如果满了,就要跳到另一个buffer上去, tty->flip.tqueue.routine((void *) tty)是用来实现跳到另一个buffer上的功能,然后把收到的数据写到flip-buffer,相应的状态,统计数据都要改,接着再来while 循环,循环结束后就要调用tty_flip_buffer_push(tty)来让用户把存在缓冲里的数据取走,接收一次都要把缓存清空。

 

阅读(1639) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~