FC2カウンター FPGAの部屋 Ultra96 ボードでデバイスツリー・オーバーレイをテストする4
FC2ブログ

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

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

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

前回の 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 の内容を示す。
Ultra96_ikwzm_86_181027.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

Ultra96_ikwzm_87_181027.png

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

ここまで、出来たので、アプリケーション・ソフトを作って動作を確認してみよう。
~/examples/DMA_pow2/drivers/ ディレクトリを作成して、その下に DMA_pow2_test.c を作成した。
Ultra96_ikwzm_89_181027.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 を作成した。
Ultra96_ikwzm_90_181027.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 まで表示されずに終わってしまう。
Ultra96_ikwzm_92_181027.png

これで、make して DMA_pow2_test を実行した。
Ultra96_ikwzm_93_181027.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 に変更した。
Ultra96_ikwzm_94_181028.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 だった。
  1. 2018年10月28日 05:55 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:3

コメント

Marsee san,
Thank you for your sharing.
I would like to refer to the following files, may I know where can I get them?
1. xdma_pow2_linux.c
2. xdma_pow2.h
3. xdma_pow2.c
4. xdma_pow2_hw.h
よろしくお願いします。
  1. 2018/12/12(水) 15:03:35 |
  2. URL |
  3. tiong #-
  4. [ 編集 ]

http://marsee101.blog19.fc2.com/blog-entry-4333.html
を参考にしてVivado HLSでDMA_pow2 IPを作成してください。
すべての作業を終えると、DMA_pow2/solution1/impl/ip/drivers/src ディレクトリにそれらのファイルが生成されているはずです。
  1. 2018/12/12(水) 21:21:04 |
  2. URL |
  3. marsee #f1oWVgn2
  4. [ 編集 ]

Marsee san,
ご説明を頂きありがとうございます。
Thank you very much for solving my problem!
  1. 2018/12/12(水) 23:19:55 |
  2. URL |
  3. tiong #-
  4. [ 編集 ]

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/4339-4c881918
この記事にトラックバックする(FC2ブログユーザー)