BSP版本 : BSP18.0
问题描述 :
使用 UART1 进行串口通信 ,在UART1 向 PC 端不停发送数据 ,PC端也不停向 UART1 发送数据过程中 ,出现 UART1 接收数据丢失现象并报错
① uart_wr.c 编译后放到 TF 卡 ,运行此应用不停的向 PC 端发送数据
root@s32v234evb:~# ./uart_wr_app 65536123413413241341341324134123412341324134
② PC 端通过串口工具 ,以 10ms 的速度不停的向 S32V UART1 发送数据
③ 下面是 UART0 打印的报错信息 :[ 105.011611] ------------[ cut here ]------------
[ 105.016314] WARNING: CPU: 1 PID: 0 at drivers/tty/serial/fsl_linflexuart.c:206 linflex_copy_rx_to_tty+0x80/0xf4()…………………………………………………………………………………….
[ 105.226783] bf20: 00085074 ffffffc0 770ebf50 ffffffc0
[ 105.232314] [] el1_irq+0x68/0xe4
[ 105.237562] [] cpu_startup_entry+0x138/0x298
[ 105.243951] [] secondary_start_kernel+0x144/0x168
[ 105.250814] ---[ end trace 0d731b2be85a1fbf ]---
[ 105.255873] fsl-linflexuart 400bc000.serial: RxData copy to tty layer failed
问题分析 :
① 分析 LOG 信息找到报错函数 ,
通过 LOG 信息 ,找到了出错函数的位置为 :
drivers/tty/serial/fsl_linflexuart.c
static void linflex_copy_rx_to_tty(struct linflex_port *sport,
struct tty_port *tty, int count)
{
int copied;
sport->port.icount.rx += count;
if (!tty) {
dev_err(sport->port.dev, "No tty port\n");
return;
}
dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
copied = tty_insert_flip_string(tty,((unsigned char *)(sport->dma_rx_buf_virt)), count);
if (copied != count) {
WARN_ON(1);
dev_err(sport->port.dev, "RxData copy to tty layer failed\n");
}
}
② 报错原因分析 :
if (copied != count) ,需要拷贝的数量和已经拷贝的数量不相等 ,从这个信息 看出 ,数据有丢失现象
③ 问题追踪 :
由于复制的数量不对 ,我们对tty_insert_flip_string 这个函数进行追踪分析 :
数据丢失问题解决 :
通过程序追踪 ,我们分析出问题与内存的分配和释放有关系 :
static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
{
struct llist_node *free;
struct tty_buffer *p;
/* Round the buffer size out */
size = __ALIGN_MASK(size, TTYB_ALIGN_MASK);
if (size <= MIN_TTYB_SIZE) {
free = llist_del_first(&port->buf.free);
if (free) {
p = llist_entry(free, struct tty_buffer, free);
goto found;
}
}
if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if (p == NULL)
return NULL;
found:
tty_buffer_reset(p, size);
atomic_add(size, &port->buf.mem_used);
return p;
}
① 插入 LOG 发现 port->buf.free 开始是有空间的 ,随着数据不断的写入 ,打印 port->buf.free 的地址为 0 ,返回值 free 也为 0 ,goto found 没有执行 ,此时没有新的地址空间增加 ,UART1 因接收空间不足 ,发生数据丢失的现象
② 当检测到使用的空间大于限制空间后 ,通过tty_buffer_flush 函数对使用空间进行清
if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit)
{
tty_buffer_flush(port->tty, NULL);
return NULL;
}
通过以上修改 ,经过一个晚上的测试 ,未发现有数据丢失的现象发生
评论