这是来自的代码rt_imx_uart.c
:
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;
}
我了解此功能是在用户空间程序想要写入设备时使用的。但是我不明白这个函数是如何做到的,因为我们在程序中没有任何地方写入发送器寄存器。使用的 start_tx 函数仅启用一个标志,仅此而已。
PS:这里是这个驱动的链接:链接到驱动