2

バックグラウンド:

私がやりたいことは、ARM プロセッサから Zynq 7000 上の BRAM に書き込めるようにすることです。

これを行うには、次のコンポーネントがあります。

-M_AXI_GP0 on PS7 connects to S_AXI_LITE on axi_cdma_0 through an AXI Interconnect

-cdma_introut on axi_cdma_0 connects to IRQ_F2P on PS7 through sys_concat, input 11. This means that this maps to Interrupt 87 on PS7.

-M_AXI on axi_cdma_0 connects to S00_AXI on axi_mem_intercon

-M01_AXI on axi_mem_intercon connects to S_AXI_HP3 on PS7

-M00_AXI on axi_mem_intercon connects to S_AXI on axi_bram_ctrl_0

-BRAM_PORTA on axi_bram_ctrl_0 connects to BRAM_PORTA on blk_mem_gen0

================================================== =======================

私の考えでは、このセットアップが行うべきことは次のとおりです。

  1. ARM DMA エンジンからトランザクションが送信されると、Zynq は GP0 を使用してコマンドを CDMA コントローラーに送信します。

  2. CDMA コントローラーは、そのスレーブ AXI_LITE ポートでコマンドを受信し、その要求を解釈して HP3 経由で RAM にアクセスします。

  3. CDMA コントローラーは、M01_AXI の hp3 からトランザクション データを取得し、M00_AXI を介して BRAM コントローラーに送信するために、axi_mem_intercon を介してデータを移動します。

  4. BRAM コントローラーは AXI-4 入力を受け取り、それを適切な BRAM ポートに変換して、blk_mem_gen_0 によって生成された BRAM にデータを書き込みます。

  5. このアクションが完了すると、CDMA は sys_concat を介して割り込みを送信し、作業が完了したことを DMA エンジンに示します。

この hdl デザインを PL ファブリックにロードした後、カーネル モジュールを介してトランザクションを DMA エンジンに送信しようとしました。その結果、タイムアウトが発生し、DMA エンジンが明らかにタスクを完了していません。

================================================== =======================

問題を解明しようとする試みの中で、私は次の観察を行いました。

  1. タイムアウトになる書き込みトランザクションを試みた後、同じ DMA チャネルに対して読み取りトランザクションを試みましたが、データを読み取るように構成されていました。返されるのは、書き込もうとしたすべてのデータです。これは、DMA エンジンがどこかに書き込みを行っているが、タスクの完了を認識していないことを示しているように思えます。

  2. 問題の BRAM はデュアル ポート RAM で、もう一方のポートは BRAM のデータを読み取り、LED をトグルしてデータを反映します。この書き込みトランザクションを試行しても LED がトグルしないため、DMA トランザクションが BRAM まで到達していないように見えます。

  3. cat /proc/interrupts を見ると、いくつかの割り込みが表示されますが、GIC 87 は表示されません。前述のとおり、使用している割り込みラインは IRQ concat ブロックの入力 11 に接続されています。入力 12 への割り込みラインが実際に /proc/interrupts の GIC 88 に対応していることを確認できたので、どの割り込みを探しているかについての私の理解は正しいと思います。したがって、何らかの理由で、その割り込みがプロセッサに登録されていません。

================================================== =======================

これに基づいて、この CDMA の devicetree エントリが間違っていると思います。

Vivado では、Address Editor に次のエントリが表示されます (簡潔にするために一部のエントリは省略されています)。

sys_ps7
    Data(32 address bits:0x40000000 [1G])
        axi_cdma_0                S_AXI_LITE    Reg    0x43C0_0000    64K    0x43C0_FFFF


axi_cdma_0
    Data(32 address bits : 4G)
        axi_bram_ctrl_0           S_AXI         Mem0   0xC000_0000    4K    0xC000_0FFF
        sys_ps7                   S_AXI_HP3     HP3... 0x0000_0000    1G    0x3FFF_FFFF

devicetree エントリを書き込もうとする試みは次のとおりです。

axi-cdma@43C00000{
    #dma-cells = <0x1>;
    compatible = "tst,axi-cdma-ctrl-1.00.a";
    reg = <0x10000000 0x1000>;
    interrupts = <0x0 0x37 0x4>;
    interrupt-parent = <0x1>;

    dma-channel@C0000000{
        buswidth = <0x20>;
    }

Before I added this entry in my kernel module failed to even register a transaction channel, and now it does, so I am fairly certain that the kernel is accepting this entry at least enough to assign a DMA channel. However, I don't understand much about how exactly the devicetree works, specifically with the addressing, so there is a good chance I have written this incorrectly, and that is why my transaction doesn't succeed. Can anyone help me correct my design? }

4

1 に答える 1

2

デバイス ツリーで IP コアを宣言するだけでは不十分です。ザイリンクスが CDMAテスト クライアントで行うように、DMA クライアントも宣言する必要があります。

 cdmatest_1: cdmatest@1 {
              compatible ="xlnx,axi-cdma-test-1.00.a";
              dmas = <&axi_cdma_0 0>;
              dma-names = "cdma";
 } ;  

dmasフィールドでは、デバイス ツリーで定義されているaxi_cdma_0ように、CDMA IP コアと0その最初の dma チャネルを参照します。

 axi_cdma_0: dma@4e200000 {
              #dma-cells = <1>;
              clock-names = "s_axi_lite_aclk", "m_axi_aclk";
              clocks = <&clkc 15>, <&clkc 15>;
              compatible = "xlnx,axi-cdma-1.00.a";
              interrupt-parent = <&intc>;
              interrupts = <0 31 4>;
              reg = <0x4e200000 0x10000>;
              xlnx,addrwidth = <0x20>;
              xlnx,include-sg ;
              dma-channel@4e200000 {
                      compatible = "xlnx,axi-cdma-channel";
                      interrupts = <0 31 4>;
                      xlnx,datawidth = <0x20>;
                      xlnx,device-id = <0x0>;
                      xlnx,include-dre ;
                      xlnx,max-burst-len = <0x10>;
              };
 };

その後、クライアントをプラットフォーム ドライバーとして登録する必要があります。繰り返しますが、CDMA テスト クライアントソースから:

static const struct of_device_id xilinx_cdmatest_of_ids[] = {
    { .compatible = "xlnx,axi-cdma-test-1.00.a", },
    { }
 };

 static struct platform_driver xilinx_cdmatest_driver = {
     .driver = {
         .name = "xilinx_cdmatest",
         .owner = THIS_MODULE,
         .of_match_table = xilinx_cdmatest_of_ids,
     },
     .probe = xilinx_cdmatest_probe,
     .remove = xilinx_cdmatest_remove,
 };

 static int __init cdma_init(void)
 {
     return platform_driver_register(&xilinx_cdmatest_driver);
 }

compatibleデバイス ツリーとプラットフォーム ドライバー定義のフィールドに注意してください。これらの文字列は一致する必要があります。これを行わないと、 はdma_request_slave_channel()CDMA IP コアからチャネルを予約できません。さらに、ザイリンクス カーネル >= 4.0 でサポートされていないものは使用しないdma_request_channel()でください。チャネルを適切に予約できず、転送が完了せず、DMA が割り込みなしでタイムアウトします。観測 1 についてはよくわかりませんが、キャッシュ効果である可能性があります。dma_alloc_coherent()の代わりに使用してみてくださいkmalloc()

PS: いずれにせよ、可能であればベアメタル アプリを使用して、ハードウェアに問題がないことを確認してください。

于 2017-01-21T15:25:44.300 に答える