FPGAの部屋

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。ご利用ください。 http://marsee101.web.fc2.com/index.html

2018年10月

Ultra96 ボードでデバイスツリー・オーバーレイをテストする6”でUltra96 のデバイスツリー・オーバーレイは完成したので、次は、以前作製したUltra96用PMOD拡張ボードのPMOD にカメラ(MT9D111)を接続してカメラ画像を表示したいのだが、残念ながらDisplayPort が表示出来ていない。よって、その前段階として、Ultra96用PMOD拡張ボードにMT9D111は接続するのだが、Frame Buffer のメモリにDMA Write するだけのVivado 2018.2 プロジェクトを作成したい。そのFrame Buffer をARM プロセッサで読んで、BMP ファイルにできればパソコンへX Window 経由で表示できるはずだ。
キャッシュにも書けるようになっているし、その環境は十分に整っている。Ultra96用PMOD拡張ボードの動作チェックも行うことができる。

まずは、最初にカメラMT9D111 とのインターフェース用のAXI4-Stream 出力のIP を作成する必要がある。さて、そのmt9d111_inf_axis IP を作っていこう。

まずは、ボードファイルUltra96v1:1.2 を使用して、mt9d111_axis_mpsoc プロジェクトを作成した。

次に、カメラのデータを受けるための非同期FIFO の pixel_fifo を作っていこう。このFIFO は入力のクロックはカメラのクロックで、出力のクロックはAXI4-Stream のクロックなため、非同期FIFO として実装する。
最初にIP Catalog を表示し、「fifo」で検索して、FIFO Generator をダブルクリックしてダイアログを表示させた。
705be1f9.png


最初のFIFO Generator のダイアログ画面を示す。Basic タブだ。
最初に、Component Name に pixel_fifo と入力する。
Fifo Implementaion で Independent Clocks Block RAM を選択する。
f92439d5.png


次は、Native Ports タブをクリックする。
Read Mode のラジオボタンをクリックして、First Word Fall Through モードにする。
Data Port Parameters の Write Width と Read Width は 34 に、Write Depth と Read Depth は 512 とする。
66625ebb.png


Status Flags タブで、Optional Flags でAlmost Full Flag とAlmost Empty Flag 、overflow 、underflow のチェックボックスにチェックを入れて活かす。
020ef9a6.png


Data Counts タブで、Data Count Options の More Accurate Data Counts にチェックを入れる。またRead Data Count(Synchronized with Read Clk) にチェックを入れる。
a0381ec4.png


Summary タブで確認して、OK ボタンをクリックする。
9fdc4155.png


これで pixel_fifo が生成された。

Ultra96 ボードでデバイスツリー・オーバーレイをテストする5”の続き。

前回は、Ultra96 でデバイスツリー・オーバーレイでLinux が動作中にデバイスツリーを入れ替えて、異なるハードウェアを動作させることができた。今回は、そのやり方を紹介する。

デバイスツリー・オーバーレイを行うのは、negative と DMA_pow2 だ。2つのディレクトリともに lddtovray.sh と rmdtovray.sh を用意してある。 lddtovray.sh はデバイスツリー・オーバーレイをロードするバッチ・ファイルで、rmdtovray.sh はデバイスツリー・オーバーレイを削除するバッチ・ファイルだ。

negative の lddtovray.sh を示す。

#!/bin/bash

sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/negative
sudo cp negative.dtb /config/device-tree/overlays/negative/dtbo


negative の rmdtovray.sh を示す。

!/bin/bash

sudo rmdir /config/device-tree/overlays/negative
sudo rmdir /config/device-tree/overlays/fclk0
sudo rmdir /config/device-tree/overlays/fpga


DMA_pow2 の lddtovray.sh を示す。

#!/bin/bash

sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo


DMA_pow2 の rmdtovray.sh を示す。

!/bin/bash

sudo rmdir /config/device-tree/overlays/DMA_pow2_test/
sudo rmdir /config/device-tree/overlays/fclk0
sudo rmdir /config/device-tree/overlays/fpga/


lddtovray.sh と rmdtovray.sh を使用したデバイスツリー・オーバーレイを使用して、negative を実行してから、DMA_pow2 を実行する方法を示す。
1. 最初に negative のデバイスツリー・オーバーレイをロードする。
2. ./negative_test2 を実行する。
3. negative のデバイスツリー・オーバーレイを削除する。
4. DMA_pow2 のデバイスツリー・オーバーレイをロードする。
5. ./DMA_pow2_test2 を実行する。

cd ~/examples/negative
./lddtovray.sh
sudo ./negative_test2
./rmdtovray.sh
cd ../DMA_pow2
./lddtovray.sh
sudo ./DMA_pow2_test2


01d29593.png

32537a71.png

c6f3975e.png


その後は、./rmdtovray.sh を行えば、また、異なるハードウェアをロードして試すことができる。とても便利だ。
ikzwm さん、ありがとうございます。

twitter で話題になっていたJTAGアダプタを付けていると、Linux 起動時にハングアップしたりする問題だが、私も1,2回なったことがあるので、対処方法を実行することにした。

twitter での話題はここにある。ひでみさんが解決方法を教えてくれた。

ひでみさんのツィートによると「AR# 69143 2017.x-2018.x Zynq UltraScale+ MPSoC: XSDB を Linux CPU アイドルに接続」に対処方法が書いてあるそうだ。

それによると、bootargs に cpuidle.off=1を追加すれば良いとのことだった。
bootargs が書いてあるのは uEnv.txt なので、そこに追加しよう。

ikwzm さんの Debian だと、/boot ディレクトリに第1パーティションがマウントされていた。
cd /boot
sudo vi uEnv.txt
で編集を行って、bootargs に cpuidle.off=1を追加した.
dfb49b90.png


ciniml さんと同じように xsdb で targets コマンドを使用して、ステータスを見てみた。
source /opt/Xilinx/Vivado/2018.2/settings64.sh
xsdb
connect
targets

be4a3e49.png


ciniml さんと同じ結果で、すべての APU が Running になっている。

disconnect
exit

して xsdb を終了した。

Ultra96 ボードでデバイスツリー・オーバーレイをテストする4”の続き。

前回は「アプリケーション・ソフトを作成して、起動したところSegmentation fault になってしまって困っている。uio にデータを書き込むところでSegmentation fault になっているようだ。」ということだった。今回はSegmentation fault を克服するべく頑張った。ハードウェアではなく、ソフトウェアそれもVivado HLSのドライバに問題があったようだ。

いろいろと ikwzm さんに教えていただいてやってみた。ありがとうございました。
まずは、Vivado 2018.2 の DMA_pow2_test のブロック・デザインで、レジスタ設定用のAXIポートを変更したりした。それでも、うまく行かないので、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”をやってみることにした。

negative.bin を/lib/firmware にコピーして、FPGA のビットストリームをロードし、fclkをデバイスツリー・オーバーレイで変更して、uio と udmabuf をデバイスツリー・オーバーレイで生成した。

sudo python3 negative.py
を実行すると成功した。
59c8d050.png


次に、Vivado HLS のドライバを使用して、C でアプリケーション・ソフトを書いた。
334dfc02.png


その、negative_test.c を示す。

// negative_test.c
// 2018/10/28 by marsee

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

#include "xnegative.h"

int main(){
    XNegative xnegative_ap;
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int Xneg_status;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    printf("1"); fflush(stdout);
    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }
    printf("1"); fflush(stdout);
        
    Xneg_status = XNegative_Initialize(&xnegative_ap, "negative-uio");
    if (Xneg_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XNegative\n");
        return(-1);
    }
    printf("1"); fflush(stdout);
    
    XNegative_Set_in_r(&xnegative_ap, phys_addr);
    printf("1"); fflush(stdout);
    XNegative_Set_out_r(&xnegative_ap, (phys_addr+10*sizeof(int)));
    printf("1"); fflush(stdout);
    XNegative_Set_size(&xnegative_ap, (u32)10);

    printf("1"); fflush(stdout);
    XNegative_Start(&xnegative_ap);
    printf("1"); fflush(stdout);
    
    while(!XNegative_IsDone(&xnegative_ap));

    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }

    return(0);
}


コンパイルして、起動したところ Segmentation fault になってしまった。ikwzm さんのPython コードは問題なく動作しているので、これは、ハードウェアの問題ではなくソフトウェアの問題だということがわかった。
a9614cfd.png


次に、Vivado HLS のドライバを使用しない C のソースコードを書いてみた。negative_test2.c だ。
a5948148.png


negative_test2.c を示す。

// negative_test2.c
// 2018/10/28 by marsee
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int fd1;
    volatile unsigned int *negative;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR|O_SYNC); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }

    // uio initialize (uio1)
    fd1 = open("/dev/uio1", O_RDWR|O_SYNC); // negative IP
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (negative) open error\n");
        exit(1);
    }
    negative = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!negative){
        fprintf(stderr, "negative mmap error\n");
        exit(1);
    }
    
    negative[6] = phys_addr; // Data signal of in_r
    negative[8] = phys_addr+10*sizeof(int); // Data signal of out_r
    negative[10] = 10; // Data signal of size
    
    negative[0] = 1; // ap_start
    
    while (!(negative[0] & 0x2)) ; // ap_done ?
    
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }
    
    munmap((void *)negative, 0x10000);
    close(fd1);
    munmap((void *)udmabuf4_buf, 0x1000);
    close(udmabuf4_fd);
    
    return(0);
}


negative_test2.c をコンパイルして実行したところ、成功した。なお、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”のZynq UltraScale+ MPSoC のAXI4 Master 用のポートは S_AXI_HP0_FPD を使用していてキャッシュに書けるポートを使用してない。よって、udmabuf をキャッシュOFF モードにするため、udmabuf4 をオープンするときのオプションに O_SYNC を加えている。
1b590734.png


これで成功したということは、Vivado HLS のドライバの関数を使用するとSegmentation fault になるということだ。Vivado HLS のドライバが原因だったようだ。

さて、自分の 2 乗IP に戻ろう。
Vivado 2018.2 のブロック・デザインを示す。最初のブロック・デザイン同様に、Zynq UltraScale+ MPSoC のレジスタ設定用のポートは M_AXI_HPM0_FPD を使用した。なお、Ultra96 のボードファイルはUltra96v1 1.2 を使用している。
20df6f44.png


なお、DMP_pow2 IP のPROT value は "010" に、CACHE value は "1111" に設定してある。
b0f74d26.png


Vivado HLS のドライバを使用しない DMA_pow2_test2.c を作成した。
101e097b.png


DMA_pow2_test2.c を示す。

// DMA_pow2_test2.c
// 2018/10/28 by marsee
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int fd1;
    volatile unsigned int *dma_pow2;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<20; i++){
        udmabuf4_buf[i] = i;
    }

    // uio initialize (uio1)
    fd1 = open("/dev/uio1", O_RDWR|O_SYNC); // dma_pow2 IP
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (dma_pow2) open error\n");
        exit(1);
    }
    dma_pow2 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!dma_pow2){
        fprintf(stderr, "dma_pow2 mmap error\n");
        exit(1);
    }
    printf("Address of int size is %d\n", sizeof(int *));
    
    dma_pow2[6] = phys_addr; // Data signal of in_r
    dma_pow2[8] = phys_addr+10*sizeof(int); // Data signal of out_r
    
    dma_pow2[0] = 1; // ap_start
    
    while (!(dma_pow2[0] & 0x2)) ; // ap_done ?
    
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }
    
    munmap((void *)dma_pow2, 0x10000);
    close(fd1);
    munmap((void *)udmabuf4_buf, 0x1000);
    close(udmabuf4_fd);
    
    return(0);
}


デバイスツリー・オーバーレイを行って、コンパイルした DMA_pow2_test2 を実行したところ実行できたのだが、値が合わない。
これは、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”では、boot.bin に regs.init が入っていないので、M_AXI_HPM0_FPD でキャッシュに書けなかったためだった。(ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (基礎編)”の”boot.bin による設定”を参照)

自分で作った boot.bin に regs.init を入れたので、これをSDカードの第1パーティションのULTRA96_BOO に書いた。
b122e2fa.png


そして、Debian をブートしてから、もう一度、DMA_pow2_test2 を実行したところ、(当然、前準備は実行している)成功した。
37d91284.png


やっとうまく行って、本当に良かった。
つまり、Vivado HLS のドライバは、Zynq UltraScale+ MPSoC では使い物にならないんじゃないかな?
やたらと u32 使っているし、DMA_pow2_test2 の実行結果でも分かるように int * のサイズは 8 バイトだったので、アドレスは 64 ビットになっているはずだ。。。

前回の uio がロードできない現象は、使用していた uEnv.txt の ”boot_args”に”uio_pdrv_genirq.of_id=generic-uio”が書いてなかったことだった。これを機会に ikwzm さんの ZynqMP-FPGA-Linux/target/Ultra96/boot のファイルをSDカードの第1パーティションのULTRA96_BOO のファイルとすべて交換したところ uio がロードできるようになった。
uio はロードできるようになったが、アプリケーション・ソフトを作成して、起動したところSegmentation fault になってしまって困っている。uio にデータを書き込むところでSegmentation fault になっているようだ。

まずは、 ikwzm さんの ZynqMP-FPGA-Linux/target/Ultra96/boot のファイルをSDカードの第1パーティションのULTRA96_BOO のファイルとすべて交換した。ULTRA96_BOO の内容を示す。
2ef58843.png


~/examples/DMA_pow2 ディレクトリに行って、デバイスツリー・オーバーレイでFPGAのビットストリーム、PSからPLに出力されるクロック fclk 、uio と udmabuf をロードした。
cd ~/examples/DMA_pow2/
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo

bb417b9f.png


ls -l /sys/class/uio*
をすると、やっと uio1 が見えた。良かった。。。
more /sys/class/uio/uio1/name
をすると dma_pow2-uio が見えた。
67429168.png


ここまで、出来たので、アプリケーション・ソフトを作って動作を確認してみよう。
~/examples/DMA_pow2/drivers/ ディレクトリを作成して、その下に DMA_pow2_test.c を作成した。
3605d7ea.png

// DMA_pow2_test.c
// 2018/10/25 by marsee

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

#include "xdma_pow2.h"

int main(){
    XDma_pow2 xdma_pow2_ap;
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int Xdma_status;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }
        
    Xdma_status = XDma_pow2_Initialize(&xdma_pow2_ap, "dma_pow2-uio");
    if (Xdma_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XDMA_pow2\n");
        return(-1);
    }
    
    XDma_pow2_Set_in_r(&xdma_pow2_ap, phys_addr);
    XDma_pow2_Set_out_r(&xdma_pow2_ap, (phys_addr+10*sizeof(int)));

    XDma_pow2_Start(&xdma_pow2_ap);
    
    while(!XDma_pow2_IsDone(&xdma_pow2_ap));

    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }

    return(0);
}


Makefile を作成した。
21f46493.png

# Makefile(DMA_pow2_test)
# Referred to http://www.ie.u-ryukyu.ac.jp/~e085739/c.makefile.tuts.html

PROGRAM = DMA_pow2_test
OBJS = DMA_pow2_test.o xdma_pow2_linux.o xdma_pow2.o

CC = gcc
CFLAGS = -Wall -O2

.SUFFIXES: .c .o

.PHONY: all

all: DMA_pow2_test

DMA_pow2_test: $(OBJS)
    $(CC) -Wall -o $@ $(OBJS)
    
.c.o:
    $(CC) $(CFLAGS) -c $<

    
.PHONY: clean
clean:
    $(RM) $(PROGRAM) $(OBJS)


~/examples/DMA_pow2/drivers/ ディレクトリに、DMA_pow2 IP のdriver の xdma_pow2_linux.c、 xdma_pow2.h、 xdma_pow2.c、 xdma_pow2_hw.h をコピーした。
make
したところ、DMA_pow2_test が出来た。
DMA_pow2_test を起動したところ、Segmentation fault になってしまった。
どこでSegmentation fault が出るのか?を確かめることにした。
DMA_pow2_test.c にたくさん printf("1"); fflush(stdout); を埋め込んだ。printf("1"); だけではだめで、すぐに 1 を出力させるために、fflush(stdout); が必要だ。プリントしてもバッファリングされるためSegmentation fault まで表示されずに終わってしまう。
a5b3f8f8.png


これで、make して DMA_pow2_test を実行した。
c8eaec20.png


1 は 3 個表示してSegmentation fault だったので、

XDma_pow2_Set_in_r(&xdma_pow2_ap, phys_addr);

でSegmentation fault になっている。つまり、uio1 のDMA_pow2 IP のレジスタに書き込むときにSegmentation fault となっているようだった。

ここで、トラブルシューティングするのだが、ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)”のVivado プロジェクトのブロック・デザインをよく見てみると、DMA_pow2 IP が接続されているZynqMP のポートは、M_AXI_HPM0_LPD だった。私の使用していたのは、M_AXI_HPM0_FPD ポートだったので、M_AXI_HPM0_LPD に変更した。
b281af12.png


これで、Vivado 2018.2 で論理合成、インプリメンテーション、ビットストリームを行って、bin ファイルを生成して、Ultra96 にFTPしてやってみたが、やはり、Segmentation fault だった。

次に、ikwzm さんにUltra96 のボードファイルは複数あるということで、Avnet の Github の bdf プロジェクトを見るとUltra96v1 と Ultra96v2 がある。どちらもVivado 2018.2 にインストールして、ikwzm さんが使用している Ultra96v1 の 1.2 バージョンを使用して、Vivado 2018.2 のプロジェクトを作り直してみたが、やはり、Segmentation fault だった。

↑このページのトップヘ