weixin_39548787
weixin_39548787
2020-12-02 20:38

rx channel works well but tx channel always timed out?

Hello, I only use the rx channel before and this driver works well. When I need to do bi-directional operation, it fails.

My block design is quite typical AXI-DMA usage, the S2MM (write channel) receives data from peripheral device, write to DDR, and then the MM2S (read channel) reads the data from DDR and send to another xilinx IP.

To implement this, I call the axidma_oneway_transfer() twice, the first call to rx data, and the second call to tx data. I have verified the buffer after rx done to make sure it works well, but the tx never finish, and report "DMA transmit transaction timed out".

I remember that I have tried the axidma_twoway_transfer() with a loop design before, and it works, so I am wondering why the tx fails with two axidma_oneway_transfer() calls?

该提问来源于开源项目:bperez77/xilinx_axidma

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

18条回答

  • weixin_39649490 weixin_39649490 5月前

    Hi Brandon!

    I am having also a timeout problem using the driver. I followed this issue and the issue #20 and I am not able to solve it. I am executing the axidma_benchmark with a loopback design in the PL.

    I have checked that the interrupts of the AXI DMA IP are the same that I have wrote in the device tree (see image) imagen

    I don´t know what could be or what could I try. Could you share the set up of your loopback in Vivado in order to check if I am doing right that part?

    Kind regards and thank you for all this work.

    Tom

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    Hi Tom, From my experience in issue #20, if you encounter timeout issue with a loopback design, the first step is to check your PL design and make sure all the input/output signals work well, e.g. there is actually data input and output happens. This issue #25 is another story that is different with loopback design, and the twoway_transfer in benchmark test won't work.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Could you post your device tree entries for the AXI DMA devices? That or what mentioned usually ends up being the issue.

    点赞 评论 复制链接分享
  • weixin_39649490 weixin_39649490 5月前

    Here they are:

    The entries for configure the DMA are placed in the pl.dtsi file:

    amba_pl: amba_pl { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; ranges ;

        axi_dma_0: axidma0 {
            compatible = "xlnx,axi-dma", "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a";
            reg = < 0x40400000 0x10000 >;
            xlnx,include-sg;
            #dma-cells = <1>;
                    clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
                    clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
                    interrupt-parent = <&intc>;
                    interrupts = <0 29 4 0 30 4>;
                    xlnx,addrwidth = <0x20>;
    
            dma-mm2s-channel {
            compatible = "xlnx,axi-dma-mm2s-channel";
            dma-channels = <1>;
            xlnx,datawidth = <64>;
            xlnx,device-id = <0x0>;
            clocks = <&clkc 15>;
            clock-names = "axis";
            interrupt-parent = <&intc>;
            interrupts = < 0 29 4 >;
            } ;
            dma-s2mm-channel {
            compatible = "xlnx,axi-dma-s2mm-channel";
            dma-channels = <1>;
            xlnx,datawidth = <64>;
            xlnx,device-id = <0x1>;
            clocks = <&clkc 15>;
            clock-names = "axis";
            interrupt-parent = <&intc>;
            interrupts = < 0 30 4 >;
            } ;
        } ;
    };
    

    And the entries for the driver are on system-conf.dtsi, at the same level than chosen label:

    axidma_chrdev: axidma_chrdev {
        compatible = "xlnx,axidma-chrdev";
        dmas = <&axi_dma_0 0 &axi_dma_0 1>;
        dma-names = "tx_channel", "rx_channel";
    };
    

    Thank you both for your help

    点赞 评论 复制链接分享
  • weixin_39649490 weixin_39649490 5月前

    Hi again!

    Finally my problem is solved. As said, the problem was in my PL configuration. The addres with of the DMA was not correctly set. Now is time to use the driver with my application!

    Thank you and for your help.

    Tom

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Ahh got it. Yeah that's very often the source of the issue. It's tricky because the device tree isn't automatically generated unless you're using PetaLinux, so it's easy to miss something like that.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Just so that I have it correct, you first initiate an RX transfer to a DRAM buffer, wait until the RX transaction completes, and then initiate a TX transfer from the same buffer?

    It's hard to say what the issue can be just based on the information that you provided. It's worth noting that this design is no longer really a loop, so you naturally won't be able to use axidma_twoway_transfer for this system.

    A timeout on a transfer typically means that the driver has never received an interrupt from the IP/device. This typically comes from one of three issues: 1. The IP is not sending a TLAST signal, so an interrupt is never triggered. 2. The interrupt property for the AXI DMA IP corresponding to the IP is incorrect, so it is using the wrong number for the interrupt. 3. The address width for the AXI DMA IP is not large enough to accomodate the data transfer. I believe it defaults to 14 bits, which would only allow for up to 16 KB transfers (max is 23 bits).

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    "Just so that I have it correct, you first initiate an RX transfer to a DRAM buffer, wait until the RX transaction completes, and then initiate a TX transfer from the same buffer?"

    -- exactly, I only create one buffer, it firstly receives data from RX transfer, then to do TX transfer from the same buffer. If it works, I will consider to do Ping-Pong operation, that The RX and TX won't wait each other.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Got it, those three things are the usual culprits for the error. If that doesn't work, post your device tree entries for AXI DMA. Also, are you able to give more info on your TX IP, and have you verified it?

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    You are right, it's the issue 1, no mm2s interrupt comes out. The block design is really complicated as I use 9 AXIDMA in total, so I do not upload it here to confuse us...I just found that sometimes the tx could work, it should be working because I have verified the block design with baremetal system for quite a few days, so looks like there are some mis-config in my linux application code and leads to signal pending, I am debugging this....

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Wow 9 AXIDMA? That's quite a few IPs. Even though you so no MM2S interrupt, it's still possible that the actual source of the issue is the second one. I can take a look at your device tree entries if you want a fresh pair of eyes on them.

    Otherwise, the only thing I could think of for why an IP would work in baremetal, but not Linux, is if relies on some AXI-Lite signals from the processor. Not sure if this is the case for your IP, but that could be another source of the issue.

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    Sure, here is the device tree.

    / * CAUTION: This file is automatically generated by Xilinx. * Version:
    * Today is: Thu Apr 20 03:07:51 2017
    /

    / { axidma_chrdev_1: axidma_chrdev_1 { compatible = "xlnx,axidma-chrdev-1"; dmas = <&axi_dma_0 0 &axi_dma_0 1>; dma-names = "tx_channel", "rx_channel"; }; axidma_chrdev_2: axidma_chrdev_2 { compatible = "xlnx,axidma-chrdev-2"; dmas = <&axi_dma_1 0 &axi_dma_1 1>; dma-names = "tx_channel", "rx_channel"; }; axidma_chrdev_3: axidma_chrdev_3 { compatible = "xlnx,axidma-chrdev-3"; dmas = <&axi_dma_2 0>; dma-names = "tx_channel"; }; axidma_chrdev_4: axidma_chrdev_4 { compatible = "xlnx,axidma-chrdev-4"; dmas = <&axi_dma_3 0>; dma-names = "tx_channel"; }; axidma_chrdev_5: axidma_chrdev_5 { compatible = "xlnx,axidma-chrdev-5"; dmas = <&axi_dma_4 0>; dma-names = "tx_channel"; }; axidma_chrdev_6: axidma_chrdev_6 { compatible = "xlnx,axidma-chrdev-6"; dmas = <&axi_dma_5 0>; dma-names = "tx_channel"; }; axidma_chrdev_7: axidma_chrdev_7 { compatible = "xlnx,axidma-chrdev-7"; dmas = <&axi_dma_6 0 &axi_dma_6 1>; dma-names = "tx_channel", "rx_channel"; }; axidma_chrdev_8: axidma_chrdev_8 { compatible = "xlnx,axidma-chrdev-8"; dmas = <&axi_dma_7 0 &axi_dma_7 1>; dma-names = "tx_channel", "rx_channel"; }; axidma_chrdev_9: axidma_chrdev_9 { compatible = "xlnx,axidma-chrdev-9"; dmas = <&axi_dma_8 0 &axi_dma_8 1>; dma-names = "tx_channel", "rx_channel"; }; amba_pl: amba_pl { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; ranges ; SSD1306_OLED_ML_0: SSD1306_OLED_ML { compatible = "xlnx,SSD1306-OLED-ML-1.0"; reg = <0x43c00000 0x10000>; xlnx,s00-axi-addr-width = <0x7>; xlnx,s00-axi-data-width = <0x20>; }; axi_gpio_0: gpio { #gpio-cells = <1>; compatible = "xlnx,xps-gpio-1.00.a"; gpio-controller; reg = <0x41200000 0x10000>; xlnx,all-inputs = <0x0>; xlnx,all-outputs = <0x0>; xlnx,dout-default = <0x00000000>; xlnx,gpio-width = <0x10>; xlnx,is-dual = <0x0>; xlnx,tri-default = <0xFFFFFFFF>; }; axi_gpio_1: gpio { #gpio-cells = <1>; compatible = "xlnx,xps-gpio-1.00.a"; gpio-controller; reg = <0x41210000 0x10000>; xlnx,all-inputs = <0x0>; xlnx,all-outputs = <0x0>; xlnx,dout-default = <0x00000000>; xlnx,gpio-width = <0x10>; xlnx,is-dual = <0x0>; xlnx,tri-default = <0xFFFFFFFF>; }; axi_dma_0: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 29 4 0 30 4>; reg = <0x40400000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 29 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; dma-s2mm-channel { compatible = "xlnx,axi-dma-s2mm-channel"; dma-channels = <0x1>; interrupts = <0 30 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x1>; }; }; axi_dma_1: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 31 4 0 32 4>; reg = <0x40410000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 31 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; dma-s2mm-channel { compatible = "xlnx,axi-dma-s2mm-channel"; dma-channels = <0x1>; interrupts = <0 32 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x1>; }; }; axi_dma_2: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 33 4>; reg = <0x40420000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 33 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; }; axi_dma_3: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 34 4>; reg = <0x40430000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 34 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; }; axi_dma_4: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 35 4>; reg = <0x40440000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 35 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; }; axi_dma_5: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 36 4>; reg = <0x40450000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 36 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; }; axi_dma_6: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 52 4 0 53 4>; reg = <0x40460000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 52 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; dma-s2mm-channel { compatible = "xlnx,axi-dma-s2mm-channel"; dma-channels = <0x1>; interrupts = <0 53 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x1>; }; }; axi_dma_7: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 54 4 0 55 4>; reg = <0x40470000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 54 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; dma-s2mm-channel { compatible = "xlnx,axi-dma-s2mm-channel"; dma-channels = <0x1>; interrupts = <0 55 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x1>; }; }; axi_dma_8: dma { #dma-cells = <1>; clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk"; clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>; compatible = "xlnx,axi-dma-1.00.a"; interrupt-parent = <&intc>; interrupts = <0 56 4 0 57 4>; reg = <0x40480000 0x10000>; xlnx,addrwidth = <0x20>; dma-mm2s-channel { compatible = "xlnx,axi-dma-mm2s-channel"; dma-channels = <0x1>; interrupts = <0 56 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x0>; }; dma-s2mm-channel { compatible = "xlnx,axi-dma-s2mm-channel"; dma-channels = <0x1>; interrupts = <0 57 4>; xlnx,datawidth = <0x20>; xlnx,device-id = <0x1>; }; }; IIC: i2c { compatible = "xlnx,xps-iic-2.00.a"; interrupt-parent = <&intc>; interrupts = <0 33 4>; reg = < 0x41600000 0x10000 >; xlnx,clk-freq = <0x5f5e100>; xlnx,gpo-width = <0x1>; xlnx,iic-freq = <0x186a0>; xlnx,scl-inertial-delay = <0x0>; xlnx,sda-inertial-delay = <0x0>; xlnx,ten-bit-adr = <0x0>;

            #address-cells = <1>;
            #size-cells = <0>;
    
            m24c08 {
                compatible = "at,24c08";
                reg = <0x50>;
            };
        } ;
    /*  IIC_1: i2c {
            compatible = "xlnx,xps-iic-2.00.a";
            interrupt-parent = <&intc>;
            interrupts = <0 34 4>;
            reg = < 0x41610000 0x10000 >;
            xlnx,clk-freq = <0x5f5e100>;
            xlnx,gpo-width = <0x1>;
            xlnx,iic-freq = <0x186a0>;
            xlnx,scl-inertial-delay = <0x0>;
            xlnx,sda-inertial-delay = <0x0>;
            xlnx,ten-bit-adr = <0x0>;
    
            #address-cells = <1>;
            #size-cells = <0>;
    
            m24c08 {
                compatible = "at,24c08";
                reg = <0x50>;
            };
        } ; */
    };
    

    };

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    The AXIDMA 1, 2, 7, 8, 9 responsible for RX and TX, while AXIDMA 3, 4, 5, 6 only do TX.

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    Hi Brandon, I have a quick question irrelevant to this issue: Does your driver support AXI-VDMA? If yes, how to config the device tree and write the test-app? I remember there is an old issue to ask the same question, and the answer was "NO". I don't know if there is any update, thanks.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Sorry, I was on vacation for the past week. Looking at your device tree, I noticed that there are entires with duplicate xlnx,device-id properties (such as axidma_0 and axidma_1). All of these have to be unique for the driver to work. I'm surprised you were able to insmod the driver, there are supposed to be sanity checks that prevent that from happening. I suspect that is the issue; otherwise, the entries seem to be in good order.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    Yeah so that's a bit tricky. I did add AXI VDMA support to the driver. The code is there, but I was never able to get it to work; I kept getting timeouts for some reason. So at the moment, it doesn't work as far as I know.

    点赞 评论 复制链接分享
  • weixin_39548787 weixin_39548787 5月前

    Finally I have a work around to combine axivdma and axidma, so that I don't need axidma to do rx and tx simultaneously. It's definitely not a best practice but my system could work now. I have verified the axidma tx in a smaller design, and it works, so it's not a problem to use rx only or tx only, DO NOT to call oneway_transfer twice, first to rx, and second to tx, just as what I did before.

    点赞 评论 复制链接分享
  • weixin_39725873 weixin_39725873 5月前

    There hasn't been any follow up on this issue for a while, so I'm going to close it.

    点赞 评论 复制链接分享

相关推荐