linux 串口write,Linux串口驱动分析write

/*和read的分析过程一样, 我们首先分析tty_write*/

/*最重要的就是do_tty_write函数。 前面都是一些合法性判断*/

static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)

{

struct inode *inode = file->f_path.dentry->d_inode;

struct tty_struct *tty = file_tty(file);

struct tty_ldisc *ld;

ssize_t ret;

if (tty_paranoia_check(tty, inode, "tty_write"))

return -EIO;

if (!tty || !tty->ops->write ||

(test_bit(TTY_IO_ERROR, &tty->flags)))

return -EIO;

/* Short term debug to catch buggy drivers */

if (tty->ops->write_room == NULL)

printk(KERN_ERR "tty driver %s lacks a write_room method.\n",

tty->driver->name);

ld = tty_ldisc_ref_wait(tty);

if (!ld->ops->write)

ret = -EIO;

else

/*调用tty_ldisc_N_TTY中的write函数*/

ret = do_tty_write(ld->ops->write, tty, file, buf, count);

tty_ldisc_deref(ld);

return ret;

}

/*调用uart_ops中的write函数*/

static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)

{

c = tty->ops->write(tty, b, nr);

}

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) {

WARN_ON(1);

return -EL3HLT;

}

/*取出所对应的port和循环缓冲buf*/

port = state->uart_port;

circ = &state->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);

/*调正循环缓冲head的位置*/

circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);

/*挪动buf当前的指针位置*/

buf += c;

count -= c;

ret += c;

}

spin_unlock_irqrestore(&port->lock, flags);

uart_start(tty);

return ret;

}

/*判断循环缓冲是否为空等。 然后调用注册驱动时的ops。 也就是s3c24xx_serial_ops*/

static void __uart_start(struct tty_struct *tty)

{

struct uart_state *state = tty->driver_data;

struct uart_port *port = state->uart_port;

if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&

!tty->stopped && !tty->hw_stopped)

port->ops->start_tx(port);

}

/*判断端口是否使能,如果没使能则使能端口。 然后使能tx中断

* 使能tx中断,则当有数据来时,则会触发tx中断,调用中断函数

*/

static void s3c24xx_serial_start_tx(struct uart_port *port)

{

struct s3c24xx_uart_port *ourport = to_ourport(port);

static int a =1;//temp

if (port->line == 3) {

//printk("485_start_tx\n");

if(a){

s3c_gpio_cfgpin(S3C64XX_GPK(5), S3C_GPIO_SFN(1));

a=0;

}

gpio_set_value(S3C64XX_GPK(5), 1);

}

if (!tx_enabled(port)) {

if (port->flags & UPF_CONS_FLOW)

s3c24xx_serial_rx_disable(port);

enable_irq(ourport->tx_irq);

tx_enabled(port) = 1;

}

}

/*tx中断触发函数*/

static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)

{

struct s3c24xx_uart_port *ourport = id;

struct uart_port *port = &ourport->port;

struct circ_buf *xmit = &port->state->xmit;

int count = 256;

/*判断x_char是否存在,如果存在则写进UTXH寄存器。清空x_char*/

if (port->x_char) {

wr_regb(port, S3C2410_UTXH, port->x_char);

port->icount.tx++;

port->x_char = 0;

goto out;

}

/* if there isn't anything more to transmit, or the uart is now

* stopped, disable the uart and exit

*/

/*判断循环缓冲是否为空,或者tx是否为停止状态。 如果是则停止发送*/

if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {

s3c24xx_serial_stop_tx(port);

goto out;

}

/* try and drain the buffer... */

/*当循环缓冲buff不为空,而且count是大于0的。则进入while循环*/

while (!uart_circ_empty(xmit) && count-- > 0) {

/*首先读取UFSTAT寄存器,然后判断tx_fifo是否为0.是则退出*/

if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)

break;

/*然后将循环buff中的数据读出到UTXH寄存器。然后设置tail的指针位置*/

wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);

xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);

port->icount.tx++;

}

/*判断循环缓冲中的数据是否小于WAKEUP_CHARS, 小于则启动接受*/

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

uart_write_wakeup(port);

/*如果循环buff为空,则停止发送,退出*/

if (uart_circ_empty(xmit))

s3c24xx_serial_stop_tx(port);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值