S32V UART1 数据拷贝到 TTY LAYER 失败

使用的芯片 :S32V234
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;

}

通过以上修改 ,经过一个晚上的测试 ,未发现有数据丢失的现象发生

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论