C 该函数如何在不写入“变送器寄存器”的情况下执行“写入”操作?

C 该函数如何在不写入“变送器寄存器”的情况下执行“写入”操作?,c,linux,linux-kernel,uart,rtai,C,Linux,Linux Kernel,Uart,Rtai,下面是rt_imx_uart.c的代码: 我理解此功能是在用户空间程序想要写入设备时使用的。然而,我不明白这个函数是怎么做到的,因为在程序中,我们从来没有写入发送器寄存器。使用的start_tx功能仅启用一个标志,仅此而已 PS:这是这个驱动程序的链接:看起来该函数将字节放入缓冲区并启用传输中断。中断服务程序可能会写入uart传输寄存器。谢谢您的回答。如果我可以问一下,传输中断是如何产生的?@IronBaby:可能是硬件在FIFO缓冲区有空间时产生的。 static ssize_t rt_imx

下面是rt_imx_uart.c的代码:

我理解此功能是在用户空间程序想要写入设备时使用的。然而,我不明白这个函数是怎么做到的,因为在程序中,我们从来没有写入发送器寄存器。使用的start_tx功能仅启用一个标志,仅此而已


PS:这是这个驱动程序的链接:

看起来该函数将字节放入缓冲区并启用传输中断。中断服务程序可能会写入uart传输寄存器。

谢谢您的回答。如果我可以问一下,传输中断是如何产生的?@IronBaby:可能是硬件在FIFO缓冲区有空间时产生的。
static ssize_t rt_imx_uart_write(struct rtdm_fd *fd, const void *buf,
                size_t nbyte)
{
    struct rt_imx_uart_ctx *ctx;
    rtdm_lockctx_t lock_ctx;
    size_t written = 0;
    int free;
    int block;
    int subblock;
    int out_pos;
    char *in_pos = (char *)buf;
    rtdm_toseq_t timeout_seq;
    ssize_t ret;

    if (nbyte == 0)
        return 0;

    if (rtdm_fd_is_user(fd) && !rtdm_read_user_ok(fd, buf, nbyte))
        return -EFAULT;

    ctx = rtdm_fd_to_private(fd);

    rtdm_toseq_init(&timeout_seq, ctx->config.rx_timeout);

    /* Make write operation atomic. */
    ret = rtdm_mutex_timedlock(&ctx->out_lock, ctx->config.rx_timeout,
                   &timeout_seq);
    if (ret)
        return ret;

    while (nbyte > 0) {
        rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);

        free = OUT_BUFFER_SIZE - ctx->out_npend;

        if (free > 0) {
            block = subblock = (nbyte <= free) ? nbyte : free;
            out_pos = ctx->out_tail;

            rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);

            /* Do we have to wrap around the buffer end? */
            if (out_pos + subblock > OUT_BUFFER_SIZE) {
                /* Treat the block between head and buffer
                 * end separately.
                 */
                subblock = OUT_BUFFER_SIZE - out_pos;

                if (rtdm_fd_is_user(fd)) {
                    if (rtdm_copy_from_user
                        (fd,
                         &ctx->out_buf[out_pos],
                         in_pos, subblock) != 0) {
                        ret = -EFAULT;
                        break;
                    }
                } else
                    memcpy(&ctx->out_buf[out_pos], in_pos,
                           subblock);

                written += subblock;
                in_pos += subblock;

                subblock = block - subblock;
                out_pos = 0;
            }

            if (rtdm_fd_is_user(fd)) {
                if (rtdm_copy_from_user
                    (fd, &ctx->out_buf[out_pos],
                     in_pos, subblock) != 0) {
                    ret = -EFAULT;
                    break;
                }
            } else
                memcpy(&ctx->out_buf[out_pos], in_pos, block);

            written += subblock;
            in_pos += subblock;
            nbyte -= block;

            rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);

            ctx->out_tail =
                (ctx->out_tail + block) & (OUT_BUFFER_SIZE - 1);
            ctx->out_npend += block;

            ctx->ier_status |= IER_TX;
            rt_imx_uart_start_tx(ctx);

            rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);
            continue;
        }

        rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);

        ret = rtdm_event_timedwait(&ctx->out_event,
                       ctx->config.tx_timeout,
                       &timeout_seq);
        if (ret < 0) {
            if (ret == -EIDRM) {
                /* Device has been closed -
                 * return immediately.
                 */
                ret = -EBADF;
            }
            break;
        }
    }

    rtdm_mutex_unlock(&ctx->out_lock);

    if ((written > 0) && ((ret == 0) || (ret == -EAGAIN) ||
                  (ret == -ETIMEDOUT)))
        ret = written;

    return ret;
}