FC2カウンター FPGAの部屋 PYNQ

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

FPGAの部屋

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

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を使用してカメラの画像を表示

「”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる9(入れ替え2)」では、FASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路を使用して、カメラ画像を表示することができなかった。これは、PS から出力される fclk の出力周波数が設定されていないのが原因ではないか?というご指摘を ikwzm さんから頂いた。
そこで、「ikwzm さんの構築したPYNQ ボード用DebianでのPS出力クロックfclkの設定方法」で、デバイスツリー・オーバーレイを使用した。fclk の設定のやり方を学習したので、実際にFASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路に適用して試してみよう。

まずは、「”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる7(shellスクリプト)」で作成した devtov スクリプトを変更した。
PYNQ_Linux_ikwzm_107_170419.png

#!/bin/sh
# device tree overlay command (devtov)
# Be sure to run it as superuser
# $1 is device tree name

mkdir /config/device-tree/overlays/$1
cp $1.dtbo /config/device-tree/overlays/$1/dtbo
echo 1 > /config/device-tree/overlays/$1/status

sleep 0.1
chmod 666 /dev/uio*
ls -l /dev/uio*

if test -e /dev/udmabuf*; then
    chmod 666 /dev/udmabuf*
    ls -l /dev/udmabuf*
fi

if test -e /dev/fclk0; then
    chmod 666 /dev/fclk*
    ls -l /dev/fclk*
fi


次に、「ikwzm さんの構築したPYNQ ボード用DebianでのPS出力クロックfclkの設定方法」を参考に fclk のエントリを追加したデバイスツリー・オーバーレイの pynq_fastx_fclk.dts を作成した。
PYNQ_Linux_ikwzm_108_170419.png

/dts-v1/;
/ {
    fragment@0 {
        target-path = "/amba";
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x1>;
            axi_iic_0@41600000 {
                compatible = "generic-uio";
                reg = <0x41600000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axi_vdma_0@43000000 {
                compatible = "generic-uio";
                reg = <0x43000000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axis_switch_0@43C10000 {
                compatible = "generic-uio";
                reg = <0x43C10000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axis_switch_1@43C20000 {
                compatible = "generic-uio";
                reg = <0x43C20000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            bitmap_disp_cntrler_axi_master_0@43C00000 {
                compatible = "generic-uio";
                reg = <0x43C00000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            fastx_corner_det_0@43C30000 {
                compatible = "generic-uio";
                reg = <0x43C30000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            lap_filter_axis_0@43C50000 {
                compatible = "generic-uio";
                reg = <0x43C50000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            mt9d111_inf_axis_0@43C40000 {
                compatible = "generic-uio";
                reg = <0x43C40000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            unsharp_mask_axis_0@43C60000 {
                compatible = "generic-uio";
                reg = <0x43C60000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            udmabuf4 {
                compatible = "ikwzm,udmabuf-0.10.a";
                minor-number = <4>;
                size = <0x00600000>;
            };
            fclk0 {
                compatible  = "ikwzm,fclkcfg-0.10.a";
                clocks      = <1 15>;
            };
            fclk1 {
                compatible  = "ikwzm,fclkcfg-0.10.a";
                clocks      = <1 16>;
            };
            fclk2 {
                compatible  = "ikwzm,fclkcfg-0.10.a";
                clocks      = <1 17>;
            };
        };
    };
};


dtc -I dts -O dtb -o pynq_fastx_fclk.dtbo pynq_fastx_fclk.dts
で dts をコンパイルして、pynq_fastx_fclk.dtbo を生成した。
PYNQ_Linux_ikwzm_109_170419.png

スーパーユーザーになって、
./devtov pynq_fastx_fclk
で、デバイスツリー・オーバーレイをロードした。uio, udmabuf, fclk のデバイスツリー・オーバーレイがロードされた。
PYNQ_Linux_ikwzm_110_170419.png

/sys/class/fclkcfg/fclk0 ディレクトリに移動して fclk0 のステータスを見た。
100 MHz に設定されていた。 enable = 1 なので、すでに出力されている。
cd /sys/class/fclkcfg/fclk0
cat rate
cat round_rate
cat enable

PYNQ_Linux_ikwzm_111_170419.png

/sys/class/fclkcfg/fclk1 ディレクトリに移動して fclk1 のステータスを見た。
rate を 25 MHz に設定した。
cd ../fclk1
cat rate
cat round_rate
cat enable
su
echo 25000000 > round_rate
cat round_rate
echo 25000000 > rate
cat rate
exit

PYNQ_Linux_ikwzm_112_170419.png

/sys/class/fclkcfg/fclk2 ディレクトリに移動して fclk2 のステータスを見た。
rate を 72 MHz に設定したが、round_rate の結果をみると、71.428572 MHz だった。
cd ../fclk2
cat rate
cat round_rate
cat enable
su
echo 72000000 > round_rate
cat round_rate
echo 72000000 > rate
cat rate
exit

PYNQ_Linux_ikwzm_113_170419.png

~/device_tree_overlay/ ディレクトリに戻って、pynq_fastx_wrapper.bit をPYNQ ボードにコンフィギュレーションした。
cd ~/device_tree_overlay/
ls
su
./fpgamag pynq_fastx_wrapper.bit
exit


”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる9(入れ替え2)」の cam_disp.c の表示が出ないように書き換えて、コンパイルを行った。
cam_disp を起動した。
gcc -o cam_disp cam_disp.c
./cam_disp

PYNQ_Linux_ikwzm_114_170419.png

すると、カメラ画像を表示することができました。(部屋が散らかっていて、お見苦しい点をお詫びいたします)
PYNQ_Linux_ikwzm_115_170419.jpg

最後に、修正した cam_disp.c を貼っておきます。

// cam_disp.c
// 2017/04/08 by marsee
//

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

#define NUMBER_OF_WRITE_FRAMES  3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600
#define PIXEL_NUM_OF_BYTES  4
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES)

#define FASTX_THRESHOLD     20

void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2// reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main()
{
    int fd0, fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8;
    int fd_udmabuf, fd_paddr;
    volatile unsigned int *axi_iic_0, *axi_vdma_0, *axis_switch_0, *axis_switch_1;
    volatile unsigned int *bitmap_disp_cntrler_axim_0, *fastx_corner_det_0;
    volatile unsigned int *mt9d111_inf_axis_0;
    volatile unsigned int *frame_buffer;
    unsigned char  attr[1024];
    unsigned long  phys_addr;

    // axi_iic_0 (uio0)
    fd0 = open("/dev/uio0", O_RDWR); // axi_iic_0
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 (axi_iic_0) open errorn");
        exit(-1);
    }
    axi_iic_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (axi_iic_0 == MAP_FAILED){
        fprintf(stderr, "axi_iic_0 mmap errorn");
        exit(-1);
    }
    
    // axi_vdma_0 (uio1)
    fd1 = open("/dev/uio1", O_RDWR); // axi_vdma_0
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (axi_vdma_0) open errorn");
        exit(-1);
    }
    axi_vdma_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (axi_vdma_0 == MAP_FAILED){
        fprintf(stderr, "axi_vdma_0 mmap errorn");
        exit(-1);
    }

    // axis_switch_0 (uio2)
    fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0
    if (fd2 < 1){
        fprintf(stderr, "/dev/uio2 (axis_switch_0) open errorn");
        exit(-1);
    }
    axis_switch_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
    if (axis_switch_0 == MAP_FAILED){
        fprintf(stderr, "axis_switch_0 mmap errorn");
        exit(-1);
    }
    
    // axis_switch_1 (uio3)
    fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 (axis_switch_1) open errorn");
        exit(-1);
    }
    axis_switch_1 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (axis_switch_1 == MAP_FAILED){
        fprintf(stderr, "axis_switch_1 mmap errorn");
        exit(-1);
    }
    
    // bitmap_disp_cntrler_axim_0 (uio4)
    fd4 = open("/dev/uio4", O_RDWR); // bitmap_disp_cntrler_axim_0
    if (fd4 < 1){
        fprintf(stderr, "/dev/uio4 (bitmap_disp_cntrler_axim_0) open errorn");
        exit(-1);
    }
    bitmap_disp_cntrler_axim_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
    if (bitmap_disp_cntrler_axim_0 == MAP_FAILED){
        fprintf(stderr, "bitmap_disp_cntrler_axim_0 mmap errorn");
        exit(-1);
    }
    
    // mt9d111_inf_axis_0 (uio7)
    fd7 = open("/dev/uio7", O_RDWR); // mt9d111_inf_axis_0
    if (fd7 < 1){
        fprintf(stderr, "/dev/uio7 (mt9d111_inf_axis_0) open errorn");
        exit(-1);
    }
    mt9d111_inf_axis_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
    if (mt9d111_inf_axis_0 == MAP_FAILED){
        fprintf(stderr, "mt9d111_inf_axis_0 mmap errorn");
        exit(-1);
    }
    
    // udmabuf4
    fd_udmabuf = open("/dev/udmabuf4", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled. 
    if (fd_udmabuf == -1){
        fprintf(stderr, "/dev/udmabuf4 open errorn");
        exit(-1);
    }
    frame_buffer = (volatile unsigned int *)mmap(NULL, (ALL_DISP_ADDRESS*3), PROT_READ|PROT_WRITE, MAP_SHARED, fd_udmabuf, 0);
    if (frame_buffer == MAP_FAILED){
        fprintf(stderr, "frame_buffer mmap errorn");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_paddr = open("/sys/devices/soc0/amba/amba:udmabuf4/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_paddr == -1){
        fprintf(stderr, "/sys/devices/soc0/amba/amba:udmabuf4/udmabuf/udmabuf4/phys_addr open errorn");
        exit(-1);
    }
    read(fd_paddr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_paddr);
    printf("phys_addr = %x\n", (unsigned int)phys_addr);
    
    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_1[16] = 0x0// 0x40 = 0
    axis_switch_1[17] = 0x80000000// 0x44 = 0x80000000, disable
    axis_switch_1[18] = 0x80000000// 0x48 = 0x80000000, disable
    axis_switch_1[19] = 0x80000000// 0x4C = 0x80000000, disable
    axis_switch_1[0] = 0x2// Comit registers
    
    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_0[16] = 0x0// 0x40 = 0;
    axis_switch_0[0] = 0x2// Comit registers

    // AXI VDMA Initialization sequence (axi_vdma_0)
    axi_vdma_0[12] = 0x4// S2MM_VDMACR (S2MM VDMA Control Register  Offset 30h) is 0x4 
    while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
    axi_vdma_0[12] = 0x4// S2MM_VDMACR (S2MM VDMA Control Register  Offset 30h) is 0x4 
    while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
    axi_vdma_0[18] = NUMBER_OF_WRITE_FRAMES; // S2MM_FRMSTORE (0x48) register
    axi_vdma_0[12] = 0x00010002// S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1)
    axi_vdma_0[41] = HORIZONTAL_PIXELS*PIXEL_NUM_OF_BYTES; // S2MM Horizontal Size Register(S2MM_HSIZE)0xc80 = 3200dec = 800 x 4
    axi_vdma_0[42] = HORIZONTAL_PIXELS*PIXEL_NUM_OF_BYTES; // S2MM Frame Delay and Stride Register(S2MM_FRMDLY_STRIDE)0xc80 = 3200dec = 800 x 4
    axi_vdma_0[43] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 1
    axi_vdma_0[44] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 2
    axi_vdma_0[45] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 3
    axi_vdma_0[12] = 0x00010003// S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1, Run/stop = 1)
    while((axi_vdma_0[13] & 0x1) == 0x1) ; // Halt? (S2MM_VDMASR 0x34)
    axi_vdma_0[40] = VERTICAL_LINES; // S2MM Vertical Size (S2MM_VSIZE  Offset 0xA0) 0x258 = 600dec

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(axi_iic_0);
    
    cam_i2c_write(axi_iic_0, 0xba, 0xf00x1);        // Changed regster map to IFP page 1
    cam_i2c_write(axi_iic_0, 0xba, 0x970x20);    // RGB Mode, RGB565

    mt9d111_inf_axis_0[1] = 0;
    mt9d111_inf_axis_0[0] = (unsigned int)phys_addr;

    bitmap_disp_cntrler_axim_0[0] = (unsigned int)phys_addr;
        
    munmap((void *)axi_iic_0, 0x10000);
    munmap((void *)axi_vdma_0, 0x10000);
    munmap((void *)axis_switch_0, 0x10000);
    munmap((void *)axis_switch_1, 0x10000);
    munmap((void *)bitmap_disp_cntrler_axim_0, 0x10000);
    munmap((void *)mt9d111_inf_axis_0, 0x10000);
    munmap((void *)frame_buffer, (ALL_DISP_ADDRESS*3));
    
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd7);
    close(fd_udmabuf);
}

  1. 2017年04月19日 04:55 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる9(入れ替え2)

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる8(入れ替え1)”の続き。

前回は、新たなFPGA回路として、以前作ったFASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路をコンフィギュレーションし、デバイスツリー・オーバーレイを行った。今回は、その動作をチェック(動作しなかったのだが)し、その後で、PYNQのLinux を起動しながら、GPIO でLED をテストする回路をコンフィギュレーションし、デバイスツリー・オーバーレイを行って、動作を確認する。

デバイスツリー・オーバーレイ用のShell スクリプトの devtov を変更して、/dev/udmabuf* があるときは、udmabuf* も chmod 666 に変更するようにスクリプトを書き換えた。

FASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路のデバイスツリー・オーバーレイのロードによって、コンソール・ウインドウに出ている udmabuf のステータスを示す。
PYNQ_Linux_ikwzm_89_170413.png

次に、FASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路をディスプレイに表示するためのアプリケーションソフトの cam_disp.c を作成した。
PYNQ_Linux_ikwzm_90_170413.png

cam_disp.c を
gcc -o cam_disp cam_disp.c
でコンパイルした。(もうすでにしてあった)
./cam_disp を起動したが、HDMI 画面には何も映らなかった。下の図ではデバック用に一部のレジスタの内容を表示している。
cam_disp.c は間違ってはいないと私は思うのだが?どこかおかしいのかもしれない。ちなみにベアメタル・アプリケーションとして、SDKから起動するとカメラの画像を表示できる。
もっと簡単な事例でもう一度、確かめてみよう。

動作を確認することはできなかったが、PYNQ のFPGA部分のコンフィギュレーションとデバイスツリー・オーバーレイを行った。これのデバイスツリー・オーバーレイを削除して、GPIO でLED をテストする回路のビットファイルに入れ替えて、それ用のデバイスツリー・オーバーレイをロードしよう。

まずは、FASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路のデバイスツリー・オーバーレイを削除する。
/config/device-tree/overlays に pynq_fastx ディレクトリがあるので、Shell スクリプトの rmdevtov で削除する。
./rmdevtov pynq_fastx
PYNQ_Linux_ikwzm_92_170413.png

pynq_fastx ディレクトリが削除された。
PYNQ_Linux_ikwzm_92_170413.png

次に、GPIO でLED をテストする回路のビットファイルをPYNQ のFPGA 部分にダウンロードする。
./fpgamag pynq_led_test_wrapper.bit

GPIO でLED をテストする回路のデバイスツリー・オーバーレイをロードする。
./devtov uio_gpio_0

アプリケーションソフトを起動すると正常に動作し、LED を +1 しながら、表示することができた。
./pynq_led_test
PYNQ_Linux_ikwzm_94_170413.png

最後に、FASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路用の現在のアプリケーションソフトの cam_disp.c を貼っておく。

// cam_disp.c
// 2017/04/08 by marsee
//

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

#define NUMBER_OF_WRITE_FRAMES    3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS    800
#define VERTICAL_LINES        600
#define PIXEL_NUM_OF_BYTES    4
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES)

#define FASTX_THRESHOLD        20

void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2// reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main()
{
    int fd0, fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8;
    int fd_udmabuf, fd_paddr;
    volatile unsigned int *axi_iic_0, *axi_vdma_0, *axis_switch_0, *axis_switch_1;
    volatile unsigned int *bitmap_disp_cntrler_axim_0, *fastx_corner_det_0;
    volatile unsigned int *mt9d111_inf_axis_0;
    volatile unsigned int *frame_buffer;
    unsigned char  attr[1024];
    unsigned long  phys_addr;

    // axi_iic_0 (uio0)
    fd0 = open("/dev/uio0", O_RDWR); // axi_iic_0
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 (axi_iic_0) open errorn");
        exit(-1);
    }
    axi_iic_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (axi_iic_0 == MAP_FAILED){
        fprintf(stderr, "axi_iic_0 mmap errorn");
        exit(-1);
    }
    
    // axi_vdma_0 (uio1)
    fd1 = open("/dev/uio1", O_RDWR); // axi_vdma_0
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (axi_vdma_0) open errorn");
        exit(-1);
    }
    axi_vdma_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (axi_vdma_0 == MAP_FAILED){
        fprintf(stderr, "axi_vdma_0 mmap errorn");
        exit(-1);
    }

    // axis_switch_0 (uio2)
    fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0
    if (fd2 < 1){
        fprintf(stderr, "/dev/uio2 (axis_switch_0) open errorn");
        exit(-1);
    }
    axis_switch_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
    if (axis_switch_0 == MAP_FAILED){
        fprintf(stderr, "axis_switch_0 mmap errorn");
        exit(-1);
    }
    
    // axis_switch_1 (uio3)
    fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 (axis_switch_1) open errorn");
        exit(-1);
    }
    axis_switch_1 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (axis_switch_1 == MAP_FAILED){
        fprintf(stderr, "axis_switch_1 mmap errorn");
        exit(-1);
    }
    
    // bitmap_disp_cntrler_axim_0 (uio4)
    fd4 = open("/dev/uio4", O_RDWR); // bitmap_disp_cntrler_axim_0
    if (fd4 < 1){
        fprintf(stderr, "/dev/uio4 (bitmap_disp_cntrler_axim_0) open errorn");
        exit(-1);
    }
    bitmap_disp_cntrler_axim_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
    if (bitmap_disp_cntrler_axim_0 == MAP_FAILED){
        fprintf(stderr, "bitmap_disp_cntrler_axim_0 mmap errorn");
        exit(-1);
    }
    
    // mt9d111_inf_axis_0 (uio7)
    fd7 = open("/dev/uio7", O_RDWR); // mt9d111_inf_axis_0
    if (fd7 < 1){
        fprintf(stderr, "/dev/uio7 (mt9d111_inf_axis_0) open errorn");
        exit(-1);
    }
    mt9d111_inf_axis_0 = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
    if (mt9d111_inf_axis_0 == MAP_FAILED){
        fprintf(stderr, "mt9d111_inf_axis_0 mmap errorn");
        exit(-1);
    }
    
    // udmabuf4
    fd_udmabuf = open("/dev/udmabuf4", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled. 
    if (fd_udmabuf == -1){
        fprintf(stderr, "/dev/udmabuf4 open errorn");
        exit(-1);
    }
    frame_buffer = (volatile unsigned int *)mmap(NULL, (ALL_DISP_ADDRESS*3), PROT_READ|PROT_WRITE, MAP_SHARED, fd_udmabuf, 0);
    if (frame_buffer == MAP_FAILED){
        fprintf(stderr, "frame_buffer mmap errorn");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_paddr = open("/sys/devices/soc0/amba/amba:udmabuf4/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_paddr == -1){
        fprintf(stderr, "/sys/devices/soc0/amba/amba:udmabuf4/udmabuf/udmabuf4/phys_addr open errorn");
        exit(-1);
    }
    read(fd_paddr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_paddr);
    printf("phys_addr = %x\n", (unsigned int)phys_addr);
    
    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_1[16] = 0x0// 0x40 = 0
    axis_switch_1[17] = 0x80000000// 0x44 = 0x80000000, disable
    axis_switch_1[18] = 0x80000000// 0x48 = 0x80000000, disable
    axis_switch_1[19] = 0x80000000// 0x4C = 0x80000000, disable
    axis_switch_1[0] = 0x2// Comit registers
    printf("axis_swtich_1[17] = %x\n", axis_switch_1[17]);
    
    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_0[16] = 0x0// 0x40 = 0;
    axis_switch_0[0] = 0x2// Comit registers
    printf("axis_swtich_0[16] = %x\n", axis_switch_0[16]);

    // AXI VDMA Initialization sequence (axi_vdma_0)
    axi_vdma_0[12] = 0x4// S2MM_VDMACR (S2MM VDMA Control Register  Offset 30h) is 0x4 
    while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
    printf("axi_vdma_0[12] = %x\n", axi_vdma_0[12]);
    axi_vdma_0[12] = 0x4// S2MM_VDMACR (S2MM VDMA Control Register  Offset 30h) is 0x4 
    while ((axi_vdma_0[12] & 0x4) == 0x4) ; // Reset is progress
    axi_vdma_0[18] = NUMBER_OF_WRITE_FRAMES; // S2MM_FRMSTORE (0x48) register
    axi_vdma_0[12] = 0x00010002// S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1)
    axi_vdma_0[41] = HORIZONTAL_PIXELS*PIXEL_NUM_OF_BYTES; // S2MM Horizontal Size RegisterS2MM_HSIZE0xc80 = 3200dec = 800 x 4
    axi_vdma_0[42] = HORIZONTAL_PIXELS*PIXEL_NUM_OF_BYTES; // S2MM Frame Delay and Stride RegisterS2MM_FRMDLY_STRIDE0xc80 = 3200dec = 800 x 4
    axi_vdma_0[43] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 1
    axi_vdma_0[44] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 2
    axi_vdma_0[45] = (unsigned)phys_addr; // S2MM Start Address (1 to 16) Start Address 3
    axi_vdma_0[12] = 0x00010003// S2MM_VDMACR(IRQFrameCount = 0x1, Circular_Park = 1, Run/stop = 1)
    while((axi_vdma_0[13] & 0x1) == 0x1) ; // Halt? (S2MM_VDMASR 0x34)
    axi_vdma_0[40] = VERTICAL_LINES; // S2MM Vertical Size (S2MM_VSIZE  Offset 0xA0) 0x258 = 600dec

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(axi_iic_0);
    
    cam_i2c_write(axi_iic_0, 0xba, 0xf00x1);        // Changed regster map to IFP page 1
    cam_i2c_write(axi_iic_0, 0xba, 0x970x20);    // RGB Mode, RGB565

    mt9d111_inf_axis_0[1] = 0;
    mt9d111_inf_axis_0[0] = (unsigned int)phys_addr;
    printf("mt9d111_inf_axis_0[0] = %x\n", mt9d111_inf_axis_0[0]);

    bitmap_disp_cntrler_axim_0[0] = (unsigned int)phys_addr;
    printf("bitmap_disp_cntrler_axim_0[0] = %x\n", bitmap_disp_cntrler_axim_0[0]);
    printf("frame_buffer[0] = %x\n", frame_buffer[0]);
    printf("frame_buffer[1] = %x\n", frame_buffer[1]);
        
    munmap((void *)axi_iic_0, 0x10000);
    munmap((void *)axi_vdma_0, 0x10000);
    munmap((void *)axis_switch_0, 0x10000);
    munmap((void *)axis_switch_1, 0x10000);
    munmap((void *)bitmap_disp_cntrler_axim_0, 0x10000);
    munmap((void *)mt9d111_inf_axis_0, 0x10000);
    munmap((void *)frame_buffer, (ALL_DISP_ADDRESS*3));
    
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd7);
    close(fd_udmabuf);
}

  1. 2017年04月13日 04:22 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる8(入れ替え1)

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる7(shellスクリプト)”の続き。

前回は、デバイスツリー・オーバーレイとFPGA Manager を使いやすいようにShell スクリプトを作成した。今回は、2つのFPGA回路とデバイスツリーをLinux 起動しながら入れ替えてみようと思う。

まずは、新たなFPGA回路として、以前作ったFASTX コーナー検出、ラプラシアンフィルタ、アンシャープ・マスクキング・フィルタの回路をコンフィギュレーションして、動作を確認する。

まずは、デバイスツリーを作成しよう。
pynq_fastx.dts を作成した。それぞれのデバイスとudmabuf を記述した。udmabuf はSVGA 3画面分のメモリを確保することにした。
PYNQ_Linux_ikwzm_86_170408.png

/dts-v1/;
/ {
    fragment@0 {
        target-path = "/amba";
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x1>;
            axi_iic_0@41600000 {
                compatible = "generic-uio";
                reg = <0x41600000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axi_vdma_0@43000000 {
                compatible = "generic-uio";
                reg = <0x43000000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axis_switch_0@43C10000 {
                compatible = "generic-uio";
                reg = <0x43C10000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            axis_switch_1@43C20000 {
                compatible = "generic-uio";
                reg = <0x43C20000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            bitmap_disp_cntrler_axi_master_0@43C00000 {
                compatible = "generic-uio";
                reg = <0x43C00000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            fastx_corner_det_0@43C30000 {
                compatible = "generic-uio";
                reg = <0x43C30000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            lap_filter_axis_0@43C50000 {
                compatible = "generic-uio";
                reg = <0x43C50000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            mt9d111_inf_axis_0@43C40000 {
                compatible = "generic-uio";
                reg = <0x43C40000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            unsharp_mask_axis_0@43C60000 {
                compatible = "generic-uio";
                reg = <0x43C60000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
            udmabuf4 {
                compatible = "ikwzm,udmabuf-0.10.a";
                minor-number = <4>;
                size = <0x00600000>;
            };
        };
    };
};


デバイスツリー・ソースを
dtc -I dts -O dtb -o pynq_fastx.dtbo pynq_fastx.dts
でコンパイルした。
pynq_fastx.dtbo を使用してデバイスツリー・オーバーレイを行う。そのために、前回作成したShell スクリプトを使用する。
まずは、FPGA Manager を使用して、FPGA をコンフィグレーションする。
./fpgamag pynq_fastx_wrapper.bit
次に、デバイスツリー・オーバーレイを行う。
./devtov pynq_fastx
udmabuf がロードされたかどうか?確かめてみよう。
ls -l /dev/udmabuf4
PYNQ_Linux_ikwzm_87_170408.png

/sys/devices/soc0/amba を見ると、各 uio と udmabuf4 が見える。
PYNQ_Linux_ikwzm_88_170408.png
  1. 2017年04月08日 06:57 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる7(shellスクリプト)

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる6(FPGA Manager)”の続き。

前回は、FPGA Manager を試して、ikwzm さんのおかげでビットファイルをダウンロードして、アプリケーションソフトを動作させることができた。今回は、デバイスツリー・オーバーレイとFPGA Manager を shell スクリプトにしてみようと思う。

まずは、デバイスツリー・オーバーレイから shell コマンドを作ってみた。
コマンド名は、devtov だ。第1引数はデバイスツリー名を設定する。
PYNQ_Linux_ikwzm_82_170407.png

#!/bin/sh
# device tree overlay command (devtov)
# Be sure to run it as superuser
# $1 is device tree name

mkdir /config/device-tree/overlays/$1
cp $1.dtbo /config/device-tree/overlays/$1/dtbo
echo 1 > /config/device-tree/overlays/$1/status

sleep 0.1
chmod 666 /dev/uio*
ls -l /dev/uio*

if test -e /dev/udmabuf*; then
    chmod 666 /dev/udmabuf*
    ls -l /dev/udmabuf*
fi


devtov のコマンドで、なぜ sleep 0.1 が入っているか?だが、この sleep を入れないと chmod が効かなかったからだ。つまり、/dev/uio* にマウントするのに一定の時間がかかるらしく、chmod するときには、uio が完全にできていないためだと思う。

次に、デバイスツリー・オーバーレイを削除する rmdevtov を示す。やはり、第1引数はデバイスツリー名を設定する。
PYNQ_Linux_ikwzm_83_170407.png

#!/bin/sh
# Remove device tree overlay command (rmdevtov)
# Be sure to run it as superuser
# $1 is device tree name

rmdir /config/device-tree/overlays/$1


FPGA Manager でビットファイルをFPGA にダウンロードするコマンドが fpgamag だ。第1引数はビットファイルを指定する。
PYNQ_Linux_ikwzm_84_170407.png

#!/bin/sh
# fpga manager command (fpgamag)
# Be sure to run it as superuser
# $1 is bit file name

echo 1 > /sys/class/fpgacfg/fpgacfg0/data_format
echo 1 > /sys/class/fpgacfg/fpgacfg0/load_start
cp $1 /dev/fpgacfg0


rmdevtov, devtov, fpgamag を使って、ロードしてあったデバイスツリー・オーバーレイを削除して、再度デバイスツリー・オーバーレイをロードし、FPGA をコンフィギュレーションして、./pynq_led_test を動かしたスナップショットを示す。ちゃんとLED が点灯して動作した。
PYNQ_Linux_ikwzm_85_170407.png
  1. 2017年04月07日 04:41 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる6(FPGA Manager)

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる5(デバイスツリー・オーバーレイ)”の続き。

前回は、デバイスツリー・オーバーレイを試して、成功した。今回は、FPGAをコンフィギュレーションする FPGA Manager を試してみた。

(2017/04/06:修正 デバイスツリー・オーバーレイとFPGA Manager がうまく動作した)

最初に PYNQ ボードのFPGA 部分をコンフィギュレーションする。
まずは、lsmod で、どんなモジュールが insmod されているか?を確かめた。
fpgacfg も入っている。
ls /dev/fpgacfg0 をやってみたが、すでにデバイスがあった。
PYNQ_Linux_ikwzm_70_170405.png

pynq_led_test_wrapper.bit を WinSCP で PYNQ ボードの Debian に転送した。/home/fpga/device_tree_overlay ディレクトリに転送した。
PYNQ_Linux_ikwzm_77_170405.png

FPGA をコンフィギュレーションした。
su
echo 1 > /sys/class/fpgacfg/fpgacfg0/data_format
echo 1 > /sys/class/fpgacfg/fpgacfg0/load_start
cp pynq_led_test_wrapper.bit /dev/fpgacfg0

PYNQ_Linux_ikwzm_72_170405.png
するとDONEランプが点灯した。

次に、デバイスツリー・オーバーレイを行った。
mkdir /config/device-tree/overlays/uio_gpio_0
cp uio_gpio_0.dtbo /config/device-tree/overlays/uio_gpio_0/dtbo
echo 1 > /config/device-tree/overlays/uio_gpio_0/status
ls /dev/uio0

PYNQ_Linux_ikwzm_73_170405.png

/dev/uio0 をユーザーからもリード、ライトできるように、chmod を 666 に設定した。
ls -l /dev/uio0
chmod 666 /dev/uio0
ls -l /dev/uio0

PYNQ_Linux_ikwzm_74_170406.png

pynq_led_test.c を作成した。
PYNQ_Linux_ikwzm_79_170406.png

// pynq_led_test.c
// 2017/04/06 by marsee
//

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

 int main() {
    int fd;
    volatile unsigned int *led_gpio;

    fd = open("/dev/uio0", O_RDWR);
    if (fd < 1){
        fprintf(stderr, "/dev/uio0 open error\n");
        exit(-1);
    }

    led_gpio = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
    if (led_gpio == MAP_FAILED){
        fprintf(stderr, "mmap error\n");
        exit(-1);
    }
    
    unsigned int i = 0;  
    while(i<17){
        led_gpio[0] = i++;
        sleep(1);
    }
    
    munmap((void *)led_gpio, 0x10000);
    return(0);
}


pynq_led_test.c を gcc でコンパイルした。
gcc -o pynq_led_test pynq_led_test.c
PYNQ_Linux_ikwzm_80_170406.png

./pynq_led_test を起動すると、LD3~0が2進数で +1 されて表示された。
PYNQ_Linux_ikwzm_81_170406.png

デバイスツリー・オーバーレイとFPGA Manager がうまく動作した。
  1. 2017年04月06日 06:09 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる5(デバイスツリー・オーバーレイ)

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる4(環境の整備)”の続き。

前回は、ikwzm さんの配布しているDebian の環境整備を行った。今回は、 デバイスツリー・オーバーレイを確かめてみよう。

FPGA+SoC+LinuxでDevice Tree Overlayを試してみた”を参考に、デバイスツリー・オーバーレイを試してみよう。追加するデバイスツリーは、下の2つの記事で作成したAXI GPIO を使用したLED表示回路とする。
PYNQのLED表示プロジェクト1(ブロックデザインの作成)”
”PYNQのLED表示プロジェクト2(完成)

まずは、dtbocfg.ko はどこにあるのだろうか?ということで、nautilus を起動して、検索した。
その結果、/lib/modules/4.8.17-armv7-fpga/ikwzm ディレクトリにあることが分かった。
PYNQ_Linux_ikwzm_61_170401.png

ls -la /config/device-tree/overlays/
をやってみたところ、あったので、dtbocfg デバイスドライバはロードされているようだ。
PYNQ_Linux_ikwzm_62_170402.png

/config/device-tree/overlays で uio_gpio_0 ディレクトリを作成した。
sudo mkdir uio_gpio_0
ls -la uio_gpio_0/
でディレクトリを見ると、dtbo と status ファイルが生成されていた。
PYNQ_Linux_ikwzm_63_170402.png

uio_gpio_0..dts を address editor の内容とテンプレートを参考に作成した。
PYNQ_Linux_ikwzm_64_170402.png

/dts-v1/;
/ {
    fragment@0 {
        target-path = "/amba";
        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x1>;
            uio_gpio_0@41200000 {
                compatible = "generic-uio";
                reg = <0x41200000 0x10000>;
                #interrupts = <0x0 0x1d 0x4>;
            };
        };
    };
};


(2017/04/06:修正 デバイスツリーの領域を 0x1000 から 0x10000 に修正した)

uio_gpio_0.dts をコンパイルして uio_gpio_0.dtbo を生成した。
dtc -I dts -O dtb -o uio_gpio_0.dtbo uio_gpio_0.dts
スーパーユーザーになって、uio_gpio_0.dtbo を /config/device-tree/overlays/uio_gpio_0/dtbo にコピーした。
cp uio_gpio_0.dtbo /config/device-tree/overlays/uio_gpio_0/dtbo
PYNQ_Linux_ikwzm_65_170402.png

echo 1 > /config/device-tree/overlays/uio_gpio_0/status を行った。
/dev/uio0 が見えた。
ls -la /dev/uio*
なお、uio_gpio_0/status に 1 を書く前は /dev/uio0 は存在しない。
PYNQ_Linux_ikwzm_66_170402.png

/sys/devices/soc0/amba ディレクトリに 41200000.uio._gpio_0 ディレクトリがあった。
PYNQ_Linux_ikwzm_67_170402.png

/sys/devices/soc0/amba/41200000.uio._gpio_0/uio/uio0 ディレクトリを示す。
PYNQ_Linux_ikwzm_68_170402.png

/sys/devices/soc0/amba/41200000.uio._gpio_0/uio/uio0 ディレクトリの name ファイルの内容を示す。
uio_gpio_0 だった。
PYNQ_Linux_ikwzm_69_170402.png

デバイスツリー・オーバーレイで uio_gpio_0 をロードできることが分かった。
  1. 2017年04月04日 05:00 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

PYNQのLED表示プロジェクト2(完成)

PYNQのLED表示プロジェクト1(ブロックデザインの作成)”の続き。

前回は、ikwzm さんのFPGA Managerデバイスツリー・オーバーレイを確かめてみるために、簡単な例としてPYNQボードのLED表示プロジェクトを作ることにして、ブロックデザインを作って、論理合成を始めるところまでだった。今回は、論理合成、インプリメント、ビットストリームの生成を行って、SDKでアプリケーションソフトを作って、PYNQで確かめた。

前回は、Synthesis -> Run Synthesis をクリックして、論理合成を行ったところまでだった。
Launch Runs ダイアログが表示された。OKボタンをクリックした。
PYNQ_LED_test_24_170402.png

論理合成が終了して、Synthesis Completed ダイアログが表示された。
Open Synthesized Design のラジオボタンをクリックして、OKボタンをクリックした。
PYNQ_LED_test_25_170402.png

Lyaout から I/O Planning を選択した。
PYNQ_LED_test_26_170402.png

Package 画面が表示された。下のI/O Ports も表示された。
LD が見える。これを制約する。
PYNQ_LED_test_27_170402.png

なお、LD のピン配置を確認するために”PYNQ-Z1 Reference Manual”のFigure 12.1. PYNQ-Z1 GPIO を引用する。
PYNQ_LED_test_28_170402.png

Figure 12.1. PYNQ-Z1 GPIO の通りに LD をピン配置を制約すれば良い。
I/O Std をLVCMOS33 にして、LD[3 ] から LD[0] のPackage Pin を制約した。
PYNQ_LED_test_29_170402.png

セーブ・ボタンをクリックすると、Out of Data Design ダイアログが表示された。OKボタンをクリックする。
PYNQ_LED_test_30_170402.png

次に、Save Constraints ダイアログが表示された。
File name に pynq_led_test と入力して、OKボタンをクリックした。
PYNQ_LED_test_31_170402.png

pynq_led_test.xdc を示す。
PYNQ_LED_test_32_170402.png

Generate Bitstream をクリックして、論理合成、インプリメント、ビットストリームの生成を行った。
結果を示す。
PYNQ_LED_test_33_170402.png

ハードウェアをエクスポートして、SDK を起動した。
PYNQ_LED_test_34_170402.png

Vivado 2016.4 のSDKでデバイスツリーのソース(DTS)を生成する”を行って、AXI GPIO のデバイスツリーを生成してみた。
PYNQ_LED_test_35_170402.png

pynq_led_test アプリケーション・プロジェクトを作成し、pynq_led_test.c を作成した。
PYNQ_LED_test_36_170403.png

PYNQを電源ON し、FPGA ビットストリームをダウンロードして、アプリケーションソフトを起動したところ、0 から 16 まで、LEDに2進数で表示された。動作した。
これで、ikwzm さんのFPGA Managerデバイスツリー・オーバーレイを確かめる準備は完了した。
  1. 2017年04月03日 04:47 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0
»