linux serial构架分析及驱动开发(6)

转载 2012年03月23日 18:48:40
  这一节分析串口核心中对写操作的处理,从用户空间调用write系统调用开始,首先执行tty_write函数,在该函数中执行do_tty_write,将用户空间的数据复制到tty->write_buf中,然后调用线路规程中的写函数即write_chain,最后write_chain调用uart_write或uart_flush_chars,再调用专用port->ops中的数据将数据发射出去,具体的操作过程看下面的源码。

 

//uart_write现将待写入的数据写入到环形缓存state->info->xmit中,然后调用uart_start发射数据

static int uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
 struct uart_state *state = tty->driver_data;
 struct uart_port *port;
 struct circ_buf *circ;
 unsigned long flags;
 int c, ret = 0;

 /*
  * This means you called this function _after_ the port was
  * closed.  No cookie for you.
  */
 if (!state || !state->info) {
  WARN_ON(1);
  return -EL3HLT;
 }

 port = state->port;
 circ = &state->info->xmit;

 if (!circ->buf)
  return 0;

 spin_lock_irqsave(&port->lock, flags);
 while (1) {

 //对环形缓存中空间的判断
  c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
  if (count < c)
   c = count;
  if (c <= 0) //数据写完或者没有空间时退出循环
   break;
  memcpy(circ->buf + circ->head, buf, c);
  circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
  buf += c;
  count -= c;
  ret += c;
 }
 spin_unlock_irqrestore(&port->lock, flags);

 uart_start(tty); //完成数据发射
 return ret;
}

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//环形缓存中有数据而没有停止串口时,调用串口port->ops->start_tx发射数据,而uart_flush_chars直接调用uart_start

//把环形缓存中的数据发射出去

static void uart_start(struct tty_struct *tty)
{
 struct uart_state *state = tty->driver_data;
 struct uart_port *port = state->port;
 unsigned long flags;

 spin_lock_irqsave(&port->lock, flags);
 __uart_start(tty);
 spin_unlock_irqrestore(&port->lock, flags);
}

static void __uart_start(struct tty_struct *tty)
{
 struct uart_state *state = tty->driver_data;
 struct uart_port *port = state->port;

 if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
     !tty->stopped && !tty->hw_stopped)
  port->ops->start_tx(port);
}

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//uart_put_char 是将一个字符复制到用户空间,和uart_write的作用相同但是只针对一个字符且没有发射处理

static int uart_put_char(struct tty_struct *tty, unsigned char ch)
{
 struct uart_state *state = tty->driver_data;

 return __uart_put_char(state->port, &state->info->xmit, ch);
}

 

static inline int
__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
{
 unsigned long flags;
 int ret = 0;

 if (!circ->buf)
  return 0;

 spin_lock_irqsave(&port->lock, flags);
 if (uart_circ_chars_free(circ) != 0) { //检测环形缓存有无空间
  circ->buf[circ->head] = c;
  circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
  ret = 1;
 }
 spin_unlock_irqrestore(&port->lock, flags);
 return ret;
}

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//uart_write_room检测环形缓存中是否存在空间,并返回可用的空间数量

 

static int uart_write_room(struct tty_struct *tty)
{
 struct uart_state *state = tty->driver_data;
 unsigned long flags;
 int ret;

 spin_lock_irqsave(&state->port->lock, flags);
 ret = uart_circ_chars_free(&state->info->xmit);
 spin_unlock_irqrestore(&state->port->lock, flags);
 return ret;
}

 

 在前面的tty核心分析中我们就介绍过tty_read函数是从tty->read_buf中将数据读到用户空间的,而tty->read_buf中的数据来源于struct tty_bufhead管理的数据缓存。struct tty_bufhead管理的各个缓存中的数据来源于在中断中调用 tty_insert_flip_char 类函数将接受到的数据保存其中,所以对串口驱动而言没有什么特别的完全继承tty的操作方式。


相关文章推荐

linux serial构架分析及驱动开发(3)

这一节我们将介绍一个serial驱动的实例,后面各节中也将以这个例子来分析串口各种操作的实际情景(例子是at91sam9260板子的串口驱动)。    该驱动将串口看作平台(platform)...

linux serial构架分析及驱动开发(5)

uart_close主要在tty_release和do_tty_hundup中调用,做与uart_pen相反的操作,具体源码如下: /*  * In 2.4.5, calls to this wi...

linux serial构架分析及驱动开发(5)

//原文地址:http://blog.csdn.net/sirzjp/article/details/6170596 uart_close主要在tty_release和do_tty_hundu...

linux serial构架分析及驱动开发(4)

转载:http://blog.csdn.net/sirzjp/article/details/6169984 在uart_register_driver函数中有这样的一个函数:tty_s...

linux serial构架分析及驱动开发(2)

上节介绍了serial驱动核心提供的重要数据结构,这一节将介绍serial核心提供给驱动开发的核心函数uart_register_driver向内核注册serial驱动(具体操作就是向内核注册一个tt...

linux serial构架分析及驱动开发(3)

原文地址:http://blog.csdn.net/sirzjp/article/details/6164694 这一节我们将介绍一个serial驱动的实例,后面各节中也将以这个例子来分析串...

linux serial构架分析及驱动开发(4)

原文地址:http://blog.csdn.net/sirzjp/article/details/6169984 在uart_register_driver函数中有这样的一个函数:t...

linux serial构架分析及驱动开发(3)

转载: 这一节我们将介绍一个serial驱动的实例,后面各节中也将以这个例子来分析串口各种操作的实际情景(例子是at91sam9260板子的串口驱动)。    该驱动将串口看作平...

linux serial构架分析及驱动开发(2)

转载:http://blog.csdn.net/sirzjp/article/details/6163429

linux serial构架分析及驱动开发(1)

前面介绍了tty核心分析及tty驱动开发的方法,tty设备包括串口、终端、伪终端三大类,其中终端和伪终端驱动内核都帮我们实现好了,很少需要改动。因此我们主要介绍串口驱动的开发及其在内核中的构架(其核心...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)