This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/AM3352:USB 大容量数据包接收损耗

Guru**** 2549920 points
Other Parts Discussed in Thread: AM3352

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/601651/linux-am3352-usb-bulk-in-packet-receive-loss

器件型号:AM3352

工具/软件:Linux

你(们)好,先生  

我们将 AM3352与 SDK 6.0 (内核3.2)配合使用、并集成了以下链接中的所有 USB 补丁  

     processors.wiki.ti.com/index.php/Sitara_Linux_MUSB_Issues

我们将 AM3352与 PC 相连、并将 AM3352设置为外设模式。

并使用 PC 进行数据批量传输。 (USB 处于 DMA 模式)。

如果 PC 发送   的数据不是64字节的倍数、则效果良好。  

如果 PC 使用   64字节数据 有效载荷的倍数进行批量数据传输、AM335x 将无法接收数据。

PC 似乎不发送 ZLP 数据包。

TI 是否有任何建议?

BTW、    如果 PC 发送多个64字节有效载荷而不在末尾发送 ZLP、USB CPPI41-DMA 的行为是什么  

谢谢

BR

Yimin

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    SDK 6.0已停产、TI 不再支持。 请移至新版本的 Processor SDK: www.ti.com/.../PROCESSOR-SDK-AM335X
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    是否确定 PC 未发送 ZLP? 顺便说一下、在 USB2.0中、512字节是批量模式下的最大数据包。 AM335x 是否被枚举为 USB1.1、因为对于 USB2.0、最大数据包大小为512字节而不是64字节。 只有在最大数据包大小(USB2.0为512)的倍数内,才会有 ZLP 吗? PC 不可能错过发送 ZLP。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="yimin bai34"]

    如果 PC 使用   64字节数据 有效载荷的倍数进行批量数据传输、AM335x 将无法接收数据。

    PC 似乎不发送 ZLP 数据包。

    [/报价]

    这是高速连接吗? 如果是、当 USB 数据包大小是64字节的倍数但不是512字节时失败、则不是 ZLP 问题、因为对于高速、任何大小不是512字节的数据包都是短数据包、因此不需要 ZLP。

    [引用 user="yimin bai34"]

    TI 是否有任何建议?

    [/报价]

    尝试禁用 CPPI41 DMA 以查看问题是否仍然发生。 或 Biser 注释后移至最新的 Processor SDK 内核。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好,先生

    由于某些原因、我们将 USB 设置为全速。 数据包大小为64字节
    2.如果我们从 PC 发送64字节到 AM335x、然后立即发送短数据包(非零数据包)、AM335x 可以接收64字节数据。
    3.我们使用 PC 软件(NI VESA),而规格 USBTMC 说明它不会发送 ZLP 数据包。
    PS:主机在传输的数据数量与数据数量完全相同时、必须考虑已完成批量输出数据传输(例外)
    (所有消息数据字节和对齐字节)如果最后一个数据有效载荷为 wMaxPackSize、则主机不应发送
    零长度数据包。
    那么、如何在 AM335x 站点中处理这种情况而不接收 ZLP 数据包呢? CPPI41-DMA 的行为是什么?

    BTW、我们将 USB 设置为 PIO 模式、并通过修改一些小工具驱动程序代码来忽略错误消息。 AM335x 可以接收
    64字节数据的倍数。 但等待可能需要大约1秒钟。
    如果我们从 PC 发送海量数据、系统将崩溃。

    BR
    Yimin
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Yimin、

    我不熟悉 NI VESA 或 USBTMC、但根据您刚才介绍的内容、这可能是 ZLP 问题。

    如果 USB 传输大小是 wMaxPacketSize 的倍数、USB 器件和主机要知道传输是否完成、双方的应用必须就以下事项达成一致。
    -如果接收器在传输前不知道传输大小,则发送器_has _发送 ZLP;否则,接收器侧的 USB 驱动程序无法知道传输何时完成。
    -如果接收器在传输前确实知道传输大小,则发送器不发送 ZLP,但接收器应用程序必须使用已知的传输大小对 URB 进行编程,以便 USB 驱动程序知道预期的数据大小。

    我想您在 AM335x 上拥有用户空间应用、请确保它遵循上述协议。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 TI

    如何在函数"USB_process_rx_BD"中获取主存储器数据? (cppi41_dma.c)

    我想获取批量输出数据包内容、以确定数据长度、从而解决 PC 无 ZLP 问题

    我可以通过 USB FIFO 获取批量输出数据、但这会导致其他问题  

    如何通过主存储器获取批量数据?????

     

    if (rx_ch->channel.actual_len=64){
    for (i=0;i<2;i++){
    data[i]=readl (rx_ch->end_pt->ep_out.hw_ep->fifo);

    printk ("data[%d]=%08x\r\n"、i、data[i]);

    TMC_Bulkout_len=data[1]+12;

    我使用以下方法来获取数据为0或数据不正确

    for (i=0;i<512;i++){
    data[i]=cpi_readl (rx_ch->queue_obj.base_addr+(i*4));
    printk ("data[%d]=%08x\r\n"、i、data[i]);

    for (i=0;i<512;i++){
    data[i]=cpi_readl (rx_ch->dma_ch_obj.base_addr+(i*4));
    printk ("data[%d]=%08x\r\n"、i、data[i]);

     

     

     

    静态空 USB_process_rx_BD (struct cppi41 * cpi、
    结构 USB_pkt_desc *货币_pd)

    静态 u8 read_debug=0;
    静态 U16 TMC_Bulkout_len=0;
    U8 en_BD_intr = cpi->en_BD_intr;
    struct cppi41_channel * rx_ch;
    U8 ch_num、ep_num;
    struct musb *musb = cpi->musb;
    u32长度= 0、orig_Buf_len;
    U8 sched_tbl_ctrl = cpi->cpi_info->sched_tbl_ctrl;
    u32数据[512];
    u32 *u32ptr;
    U16 I;

    /*从接收到的数据包描述符中提取数据*/
    长度= CURR_PD->hw_desc.desc_info & CPPI41_PKT_LEN_MASK;
    ch_num = CURR_PD->ch_num;
    EP_num = CURR_PD->EP_num;

    /* cppi41 DMA 将在何时将接收到的字节长度设置为1
    *接收到零长度数据包、通过修复此虚拟字节
    *将接收到的空等长度设置为零
    *
    /////printk ("jjjjjjRx 完整:DMA 通道(%d) ep%d len %d\n"、ch_num、ep_num、length);


    if (CURR_PD->HW_desc.pkt_info & CPPI41_ZLP){
    长度= 0;
    /////printk ("ZLP\r\n");

    RX_ch =&cpi->rx_cpi_ch[ch_num];
    dev_dbg (musb->控制器,"Rx 完成:DMA 通道(%d) ep%d len %d\n",
    ch_num、ep_num、length);

    RX_ch->channel.actual_len += length;


    if (CURR_PD->EOP){
    CURR_PD->EOP = 0;

    printk ("Curr_PD->EOP\r\n");
    /*禁用 Rx DMA schedular */
    if (sched_tbl_ctrl && is_peripheral_active (cppi->musb)&&
    !cpi->cpi_info->rx_inf_mode)
    cppi41_schedtbl_remove_dma_ch (0、0、
    cpi->cpi_info->ep_dma_ch[ch_num]、0);

    /*
    *将 Rx PD 返回到软件列表--
    *这受临界区保护
    *
    USB_PUT_FREE_PD (cppi、CURR_PD);

    ORIG_Buf_len = CURR_PD->HW_desc.orig_Buf_len;
    if (en_BD_intr)
    ORIG_Buf_len &=~CPPI41_PKT_INTR_FLAG;

    dev_dbg (musb->控制器,
    "Cure_pd=%p、len=%d、origlen=%d、rxch (alen/len)=%d/%d\n"、
    CURR_PD、长度、orig_Buf_len、
    rx_ch->channel.actual_len、rx_ch->length);

    #if 0  
    printk ("length =%d Rx_ch->channel.actual_len=%d Rx_ch->length=%d orig_Buf_len=%d Rx_ch->Curr_offset=%d\n"、length、Rx_ch->ch.actual_len、Rx_ch->length、org_Buf_offset->CURR_rx_len/simum_r_rth->)

    #endif

    if (Rx_ch->channel.actual_len/*832/>=RX_ch->length/*2060*/||
    length/*60或64*/< orig_Buf_len/*64*/){

    #if defined (CONFIG_SOC_OMAPTI81XX)|| Defined (CONFIG_SOC_OMAPAM33XX)
    struct musb_hw_EP * EP;
    U8 ISOC、NEW_SEG = 0;

    /*早期 Rx 完成的权变措施
    *用于 ti81xx 的通用 RNDIS 模式下的 cppi41 DMA
    *
    if (is_host_enabled (cppi->musb)&&!rx_ch->channel.completed){
    u32 pkt_size = rx_ch->pkt_size;
    ep = cpi->musb->端点+ EP_num;
    isOC = musb_readb (EP->regs、MUSB_RXTYPE);
    ISOC =(ISOC >> 4)& 0x1;

    如果(!ISOC
    &&(Rx_ch->DMA_mode = USB_general_RNDIS_MODE)
    &&(rx_ch->channel.actual_len < rx_ch->length)
    &&!(Rx_ch->transfer_mode)
    &&!(Rx_ch->channel.actual_len % pkt_size ))
    NEW_SEG = 1;

    if (next _seg){
    RX_ch->CURR_OFFSET = RX_ch-> CHANNEL。actual_len;
    cppi41_next rx_segment (rx_ch);
    }否则
    #endif

    RX_ch->channel.status = MUSB_DMA_STATUS_FREE;
    RX_ch->channel.completed = 1;

    if (rx_ch->inf_mode){
    cppi41_rx_ch_set_maxbufcnt (
    &Rx_ch->DMA_ch_obj、0);
    RX_ch->INF_MODE = 0;

    /* Rx 完成例程回调*/
    musb_dma_completion (cppi->musb、ep_num、0);
    #if 1.  
    MUSB 写入(rx_ch->end_pt->regs、MUSB_RXCSR、MUSB_RXCS_FLUSHFIFO /*| MUSB_RXCSR_CLRDATOG*/);
    printk ("jj musb_dma_completion\r\n");

    #endif

    }否则{
    如果((rx_ch->length - rx_ch->CURR_OFFSET)>0){


    #if 1.  
    /// printk ("xxx rx_ch->length=%d rx_ch->CURR_OFFSET=%d rx_ch->channel.actual_len=%d\r\n"、rx_ch->length、rx_ch->CURR_OFFSET、rx_ch->ch.actual_len);

    if (rx_ch->channel.actual_len=64){
    for (i=0;i<2;i++){
    data[i]=readl (rx_ch->end_pt->ep_out.hw_ep->fifo);

    printk ("data[%d]=%08x\r\n"、i、data[i]);

    TMC_Bulkout_len=data[1]+12;


    #if 1.
    printk ("rx_ch->start_addr + rx_ch->CURR_OFFSET=%08x\r\n"、rx_ch->start_addr + rx_ch->CURR_OFFSET);
    for (i=0;i<2;i++){
    data[i]=cpi_readl (rx_ch->start_addr + rx_ch->CURR_OFFSET);
    printk ("Xdata[%d]=%08x\r\n"、i、data[i]);

    #endif


    #if 0


    for (i=0;i<512;i++){
    data[i]=cpi_readl (rx_ch->queue_obj.base_addr+(i*4));
    printk ("data[%d]=%08x\r\n"、i、data[i]);

    for (i=0;i<512;i++){
    data[i]=cpi_readl (rx_ch->dma_ch_obj.base_addr+(i*4));
    printk ("data[%d]=%08x\r\n"、i、data[i]);


    #endif
    #if 0
    printk ("---------------------------------------- \r\n");
    u32ptr = CURR_PD->HW_desc.buf_ptr;
    printk ("u32ptr =%p\r\n"、u32ptr);

    u32 io_BASE;
    io_BASE =(volatile u32 *) ioremap (CURR_PD->HW_desc.buf_ptr、64);

    DATA[0]=*((volatile u32 *)(io_BASE));
    printk ("data[0]=%08x\r\n"、data[0]);

    #endif


    //printk ("rx_ch->end_pt.epnum=%d rx_ch->end_pt->fifo=%p data[0] data[1]=%08x\r\n"、rx_ch->end_pt->epnum、rx_ch -> end_pt->fifo、data[0]、data[0]、数据[1];

    if (rx_ch->channel.actual_len>TMC_bulkout_len)

    RX_ch->channel.status = MUSB_DMA_STATUS_FREE;
    RX_ch->channel.completed = 1;

    if (rx_ch->inf_mode){
    cppi41_rx_ch_set_maxbufcnt (&rx_ch->dma_ch_obj、0);
    RX_ch->INF_MODE = 0;

    /* Rx 完成例程回调*/
    musb_dma_completion (cppi->musb、ep_num、0);
    printk ("kkk musb_dma_completion rx_ch->channel.actual_len=%d >TMC_bulkout_len=%d \r\n"、Rx_ch->channel.actual_len、TMC_Bulkout_len);
    MUSB 写入(rx_ch->end_pt->regs、MUSB_RXCSR、MUSB_RXCS_FLUSHFIFO /*| MUSB_RXCSR_CLRDATOG*/);

    否则{
    cppi41_next rx_segment (rx_ch);


    其他
    cppi41_next rx_segment (rx_ch);

    #endif