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: some problems with the am3352 and ch340G

Part Number: AM3352

Tool/software: Linux

hi all:

I have some problems with the am3352 and ch340G,a USB to serial port chip。

        Am3352 has used kernel versions of 4.4.113 and 4.1.6 respectively, and USB serial interface chips are driven by ch340G manufacturer's official network, such as accessories.

       The test method is as follows. Two serial ports of devices A and B are connected to each other. First, A sends 2K data with counting flag to B. When B receives the data, it checks the integrity of the data and counts correctly. After checking correctly, all the data received by B will be sent back to A. After receiving, A will check whether the received data is the data sent by itself. Then send the next frame.

       Normally, the sending and receiving data are OK.

      The error is as follows: when sending a certain frame of data, you can not send 2K data completely, and the data must be a multiple of 32 bytes.

       Tracking the driver of ch340G, we found that his main process is: when sending data, call the write function, which will submit a URB to the USB subsystem, including 32 bytes of data. When the data is sent, the USB subsystem calls the driven completion function and continues to send the next 32 bytes of data in the completion function until all the data is sent. When an error occurs, the driver's completion function is not called when a 32-byte data is sent in the middle, resulting in the subsequent data being unable to continue to be sent. But the specific reasons were not found.

       This phenomenon does not necessarily occur for a few minutes or one or two hours.

        Testing the driver of the CH341 brought by the kernel will also lead to abnormal transmission.

        On the hardware, there is no abnormal data sending and receiving when the circuit related to the serial port of the USB is flown out to connect to other CPU chips.

       Can someone help me?  Thank you very much!

CH341SER_LINUX.ZIP

  • Hi,

    Have you tried to disable MUSB CPPI DMA to see if the issue still happens? Kernel config has an option to disable CPPI DMA.
  • Hi, I haven’t heard back from you, I’m assuming you were able to resolve your issue. If not, just post a reply below (or create a new thread if the thread has locked due to time-out). thanks.
  • This resolved my issue,thank you very much
  • That issue is resolved, but I have another issue.The CPU has two USB buses. When the DMA of the two buses is turned off, the DMA of the two buses is turned off. Can I turn off the DMA of only one buses and turn on the DMA of the other buses?

  • Hi,

    The Linux kernel MUSB driver doesn't support controlling DMA separately. But I will check the driver to see if I can provide a workaround.

    Which musb controller do you want its DMA off, USB0 or USB1?
  • Hi,

    Please keep musb cppi enable in kernel config, and use the following kernel patch to enable/disable cppi dma for a particular musb port. The patch below disable cppi for musb0, enable cppi for musb1. Please modify the code accordingly if you want a different configuration.

    diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
    index b7d56272f9d1..d32f4e165cf3 100644
    --- a/drivers/usb/musb/musb_core.c
    +++ b/drivers/usb/musb/musb_core.c
    @@ -2159,6 +2159,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
            int                     status;
            struct musb             *musb;
            struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
    +       int                     id;
     
            /* The driver might handle more features than the board; OK.
             * Fail when the board needs a feature that's not enabled.
    @@ -2302,6 +2303,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
            if (status < 0)
                    goto err_usb_phy_init;
     
    +       id = to_platform_device(musb->controller)->id;
    +       if (id == 0)
    +               use_dma = 0;
    +       else
    +               use_dma = 1;
    +
            if (use_dma && dev->dma_mask) {
                    musb->dma_controller =
                            musb_dma_controller_create(musb, musb->mregs);
    
  • ok, let me have a try, thank you very much!
  • The function of switch DMA works, but there are still some problems.
    USB1 connects ch34G, turn off the DMA function. USB0 connects LTE module, which turns on the DMA function. In this configuration,
    The data send and receive of USB1 is correct. but in USB0, I failed to configure LTE module with AT command. After I restored the configuration of usb, it was successful to configure LTE module with AT command.
    I don't understand why that happens, can you help me?
    the kernel configuration of usb dma is:

    2962 #
    2963 # Platform Glue Layer
    2964 #
    2965 # CONFIG_USB_MUSB_TUSB6010 is not set
    2966 # CONFIG_USB_MUSB_OMAP2PLUS is not set
    2967 # CONFIG_USB_MUSB_AM35X is not set
    2968 CONFIG_USB_MUSB_DSPS=y
    2969 CONFIG_USB_MUSB_AM335X_CHILD=y
    2970
    2971 #
    2972 # MUSB DMA mode
    2973 #
    2974 # CONFIG_MUSB_PIO_ONLY is not set
    2975 CONFIG_USB_TI_CPPI41_DMA=y
    2976 # CONFIG_USB_DWC3 is not set
    2977 # CONFIG_USB_DWC2 is not set
    2978 # CONFIG_USB_CHIPIDEA is not set
    2979 # CONFIG_USB_ISP1760 is not set
    2980
    2981 #
    2982 # USB port drivers
    2983 #
    2984 CONFIG_USB_SERIAL=y

    the kernel code is :

    @@ -1983,7 +1983,7 @@ musb_init_controller(struct device *dev,
            int                     status;
            struct musb             *musb;
            struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
    -
    +       int id;
            /* The driver might handle more features than the board; OK.
             * Fail when the board needs a feature that's not enabled.
             */
    @@ -2122,7 +2122,14 @@ musb_init_controller(struct device *dev,
            }
     
            pm_runtime_get_sync(musb->controller);
    -
    +
    +#ifndef CONFIG_MUSB_PIO_ONLY
    +       id = to_platform_device(musb->controller)->id;
    +       if (id == 1)
    +               use_dma = 0;
    +       else
    +               use_dma = 1;
    +#endif
            if (use_dma && dev->dma_mask) {
                    musb->dma_controller =
                            musb_dma_controller_create(musb, musb->mregs);

    config.rar



  • Hi,

    user5321888 said:
    but in USB0, I failed to configure LTE module with AT command. After I restored the configuration of usb, it was successful to configure LTE module with AT command.

    I assume the LTE module config issue doesn't happen if disabled CPPI in kernel config?

    If so, it seems the patch above doesn't completely disable the DMA. Please apply the additional patch below and let me know how it works.

    diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
    index b59ce9ad14ce..68ad64d4dbd6 100644
    --- a/drivers/usb/musb/musb_host.c
    +++ b/drivers/usb/musb/musb_host.c
    @@ -719,6 +719,20 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
     
            /* candidate for DMA? */
            dma_controller = musb->dma_controller;
    +       if (!dma_controller) {
    +               use_dma = 0;
    +
    +               csr = musb_readw(epio, MUSB_TXCSR);
    +               csr &= ~MUSB_TXCSR_DMAENAB;
    +               musb_writew(epio, MUSB_TXCSR, csr);
    +               hw_ep->tx_channel = NULL;
    +
    +               csr = musb_readw(epio, MUSB_RXCSR);
    +               csr &= ~MUSB_RXCSR_DMAENAB;
    +               musb_writew(epio, MUSB_RXCSR, csr);
    +               hw_ep->rx_channel = NULL;
    +       }
    +
            if (use_dma && is_dma_capable() && epnum && dma_controller) {
                    dma_channel = is_out ? hw_ep->tx_channel : hw_ep->rx_channel;
                    if (!dma_channel) {
    
    
  • I used the above two patches and turned on the DMA option in the kernel configuration option, but failed to configure LTE module using the AT command. But if I comment out the first patch,

    //#ifndef CONFIG_MUSB_PIO_ONLY
    //	id = to_platform_device(musb->controller)->id;
    //	if (id == 1)
    //		use_dma = 0;
    //	else
    //		use_dma = 1;
    //#endif

    and then the rest remains unchanged, the AT command is successful, but the DMA function is globally enabled. So the required functions have not been implemented.

  • Hi,

    It seems the patches don't disable cppi dma completely, but I am unable to reproduce the failure in my setup (of cause, I don't have a modem to test with).

    I would need your help to collect some debug log to understand the problem. Can you run kernel v4.14 from Processor SDK v5.x on your board? I can provide you the detailed instructions to enable ftrace in kernel build and collect debug logs. The older versions of the kernel doesn't have ftrace debug support in musb drivers, so we have to use v4.14+ to debug the problem.

  • my kernel version is v4.4.113, can I use this version to debug the problem?

  • Hi,

    As I mentioned the older kernel doesn't have ftrace debug support in musb drivers, I would need ftrace feature to generate usb register access log to see the difference in cppi disabled/enabled cases. So can you use the SDK v5.x kernel on you board to help debug the issue? Once I found the root cause, I can create the fix for v4.4 kernel.