FC2カウンター FPGAの部屋 ZUBoard 1CG の i4filters プロジェクトの回路を Petalinux で動作させる9
fc2ブログ

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

FPGAの部屋

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

ZUBoard 1CG の i4filters プロジェクトの回路を Petalinux で動作させる9

ZUBoard 1CG の i4filters プロジェクトの回路を Petalinux で動作させる8”の続き。

今まで ZUBoard 1CG の PYNQ Linux で動作させてきた i4filters プロジェクトの回路Petalinux で動作させてみようということで、前回は、”u-dma-buf を ZUBoard 1CG 用の Petalinux 2022.2 でビルドする”でビルドした u-dma-buf.ko を SFTP で ZUBoard 1CG の Petalinux 2022.2 にアップロードして、動作を確認した。UIO の状態も確認できた。今回は、Vits 2022.2 を起動して、”ZUBoard 1CG の i4filters プロジェクトの回路を Petalinux で動作させる6”の XSA ファイルを使用して、zub1cg_i4filters_peta_pf プラットフォーム・プロジェクトと zub1cg_i4filters_peta_system アプリケーション・プロジェクトを作成した。zub1cg_i4filters_peta.c と bmp_header.h を追加して、ビルドし成功した。

u-dma-buf を ZUBoard 1CG 用の Petalinux 2022.2 でビルドする”の Vivado から Vitis 2022.2 を起動した。

Vitis IDE Launcher が起動した。
HDL/2023.1/zub1cg/i4filters_peta/vitis_work を新規作成し、Workspace に指定した。

Vitis 2022.2 が起動した。

Create Application Project をクリックし、アプリケーション・プロジェクトを新規作成する。
New Application Project ダイアログの Create a New Application Project が表示された。

Platform
Create a new platform from hardware (XSA) タブをクリックした。
Hardware Specfication の XSA File に /media/masaaki/Ubuntu_Disk/HDL/2023.1/zub1cg/i4filters_peta/i4filters_peta_wrapper.xsa を指定した。
Platform name を i4filters_peta_pf に書き換えた。
zub1cg_i4filters_67_231005.png

Application Project Details
Application project name に zub1cg_i4filters_peta を指定した。
Select target processor for the Appliction project で psu_cortex53 SMP を選択した。
zub1cg_i4filters_68_231005.png

Domain
Application settings の Root FS には、ZUBoard1CG/Avnet_2022_2/petalinux/projects/zub1cg_i4filters_peta/images/linux/rootfs.ext4 を指定した。
Application settings の Kernel Image には、ZUBoard1CG/Avnet_2022_2/petalinux/projects/zub1cg_i4filters_peta/images/linux/Image を指定した。
zub1cg_i4filters_69_231005.png

Templates
Linux Empty Application を選択して、Finish ボタンをクリックした。
zub1cg_i4filters_70_231005.png

Explorer に i4filters_peta_pf プラットフォーム・プロジェクトと zub1cg_i4filters_peta_system アプリケーション・プロジェクトが生成された。
zub1cg_i4filters_71_231005.png

Vitis の Explorer から zub1cg_i4filters_peta_system -> zub1cg_i4filters_peta -> src を右クリックし、右クリックメニューから New -> File を選択した。
zub1cg_i4filters_72_231005.png

Create New File ダイアログが表示された。
File name に zub1cg_i4filters_peta.c と入力した。
Finish ボタンをクリックした。
zub1cg_i4filters_73_231005.png

zub1cg_i4filters_peta.c が生成されて、ソースコードを書いた。
zub1cg_i4filters_74_231005.png

同様に bmp_header.h も生成して、ソースコードをコピーした。
zub1cg_i4filters_75_231005.png

ビルドを行って成功した。
zub1cg_i4filters_76_231005.png

bmp_header.h を示す。

// bmp_header.h
// BMP ファイルフォーマットから引用させて頂きました
// http://www.kk.iij4u.or.jp/~kondo/bmp/
//
// 2017/05/04 : takseiさんのご指摘によりintX_tを使った宣言に変更。takseiさんありがとうございました
//              変数の型のサイズの違いによってLinuxの64ビット版では動作しなかったためです
//              http://marsee101.blog19.fc2.com/blog-entry-3354.html#comment2808
//

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

// BITMAPFILEHEADER 14bytes
typedef struct tagBITMAPFILEHEADER {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
} BITMAPFILEHEADER;

// BITMAPINFOHEADER 40bytes
typedef struct tagBITMAPINFOHEADER{
    uint32_t biSize;
    int32_t biWidth;
    int32_t biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int32_t biXPixPerMeter;
    int32_t biYPixPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImporant;
} BITMAPINFOHEADER;

typedef struct BMP24bitsFORMAT {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
} BMP24FORMAT;


zub1cg_i4filters_peta.c を示す。

// zub1cg_i4filters_peta.c
// 2023/10/04 by marsee
//

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

#include "bmp_header.h"

char INPUT_IMG_FILE[] = "test2.bmp";
char OUTPUT_IMG_FILE[] = "output_img.bmp";

int main(){
    BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
    BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
    FILE *fbmpr, *fbmpw;
    volatile uint32_t *rd_bmp, *wr_bmp;
    int blue, green, red;
    int fd4, fd5, fd6, fd7, fd8, fd9;
    volatile uint32_t *axi_dma;
    volatile uint32_t *color_converter_RGB24;
    volatile uint32_t *gaussian_axis_RGB24;
    volatile uint32_t *median_axis_RGB24;
    volatile uint32_t *sobel_axis_RGB24;
    volatile uint32_t *image_buf;
    u_int32_t fd_paddr;
    unsigned char  attr[1024];
    unsigned long  phys_addr;

    // Image file open
    if ((fbmpr = fopen(INPUT_IMG_FILE, "rb")) == NULL){ // test.bmp をオープン
        fprintf(stderr, "Can't open %s by binary read mode\n", INPUT_IMG_FILE);
        exit(1);
    }
    // bmpヘッダの読み出し
    fread(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);
    uint32_t image_all_pixels = bmpihr.biHeight * bmpihr.biWidth;
    uint32_t image_all_bytes = image_all_pixels * sizeof(uint32_t);

    // udmabuf0
    fd9 = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled.
    if (fd9 == -1){
        fprintf(stderr, "/dev/udmabuf0 open error\n");
        exit(-1);
    }
    image_buf = (volatile uint32_t *)mmap(NULL, 2*image_all_bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd9, 0);
    if (image_buf == -1){
        fprintf(stderr, "frame_buffer_bmdc mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf0
    fd_paddr = open("/sys/class/u-dma-buf/udmabuf0/phys_addr", O_RDONLY);
    if (fd_paddr == -1){
        fprintf(stderr, "/sys/class/u-dma-buf/udmabuf0/phys_addr open errorn");
        exit(-1);
    }
    read(fd_paddr, (void *)attr, 1024);
    sscanf((const char *)attr, "%lx", &phys_addr);
    close(fd_paddr);
    printf("phys_addr = %x\n", (unsigned int)phys_addr);

    // ピクセルを入れるメモリを定義する
    rd_bmp = image_buf;
    wr_bmp = & image_buf[image_all_pixels];

    // rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = fgetc(fbmpr);
            green = fgetc(fbmpr);
            red = fgetc(fbmpr);
            rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
        }
    }
    fclose(fbmpr);

    // uio のオープン
    // axi_dma (UIO 4)
    fd4 = open("/dev/uio4", O_RDWR); // axi_dma interface AXI4 Lite Slave
    if (fd4 < 1){
        fprintf(stderr, "/dev/uio4 (axi_dma) open error\n");
        exit(-1);
    }
    axi_dma = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
    if (!axi_dma){
        fprintf(stderr, "axi_dma mmap error\n");
        exit(-1);
    }

    // color_converter_RGB24 (UIO 5)
    fd5 = open("/dev/uio5", O_RDWR); // color_converter_RGB24 interface AXI4 Lite Slave
    if (fd5 < 1){
        fprintf(stderr, "/dev/uio5 (color_converter_RGB24) open error\n");
        exit(-1);
    }
    color_converter_RGB24 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd5, 0);
    if (!color_converter_RGB24){
        fprintf(stderr, "color_converter_RGB24 mmap error\n");
        exit(-1);
    }

    // gaussian_axis_RGB24 (UIO 6)
    fd6 = open("/dev/uio6", O_RDWR); // gaussian_axis_RGB24 interface AXI4 Lite Slave
    if (fd6 < 1){
        fprintf(stderr, "/dev/uio6 (gaussian_axis_RGB24) open error\n");
        exit(-1);
    }
    gaussian_axis_RGB24 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd6, 0);
    if (!gaussian_axis_RGB24){
        fprintf(stderr, "gaussian_axis_RGB24 mmap error\n");
        exit(-1);
    }

    // median_axis_RGB24 (UIO 7)
    fd7 = open("/dev/uio7", O_RDWR); // median_axis_RGB24 interface AXI4 Lite Slave
    if (fd7 < 1){
        fprintf(stderr, "/dev/uio7 (median_axis_RGB24) open error\n");
        exit(-1);
    }
    median_axis_RGB24 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
    if (!median_axis_RGB24){
        fprintf(stderr, "median_axis_RGB24 mmap error\n");
        exit(-1);
    }

    // sobel_axis_RGB24 (UIO 8)
    fd8 = open("/dev/uio8", O_RDWR); // sobel_axis_RGB24 interface AXI4 Lite Slave
    if (fd8 < 1){
        fprintf(stderr, "/dev/uio8 (sobel_axis_RGB24) open error\n");
        exit(-1);
    }
    sobel_axis_RGB24 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd8, 0);
    if (!sobel_axis_RGB24){
        fprintf(stderr, "sobel_axis_RGB24 mmap error\n");
        exit(-1);
    }

    // gaussian_axis_RGB24
    gaussian_axis_RGB24[8] = bmpihr.biHeight;    // row_size
    gaussian_axis_RGB24[10] = bmpihr.biWidth;    // col_size
    gaussian_axis_RGB24[6] = 2;     // function_r, ORG_IMGwAxiDma
    //gaussian_axis_RGB24[6] = 3;   // function_r, GAUSSIANwAxiDma

    // median_axis_RGB24
    median_axis_RGB24[8] = bmpihr.biHeight;    // row_size
    median_axis_RGB24[10] = bmpihr.biWidth;    // col_size
    //median_axis_RGB24[6] = 2; // function_r, ORG_IMGwAxiDma
    median_axis_RGB24[6] = 3;   // function_r, MEDIANwAxiDma

    // color_converter_RGB24
    color_converter_RGB24[8] = bmpihr.biHeight;    // row_size
    color_converter_RGB24[10] = bmpihr.biWidth;    // col_size
    color_converter_RGB24[6] = 2;       // function_r, ORG_IMGwAxiDma
    //color_converter_RGB24[6] = 3;     // function_r, COLOR_CONVwAxiDma
    color_converter_RGB24[12] = 0x2000;     // 32.0, ap_ufixed<16, 8, AP_TRN_ZERO, AP_SAT>
    color_converter_RGB24[14] = 0x0100;  // 1.0, ap_ufixed<16, 8, AP_TRN_ZERO, AP_SAT>
    color_converter_RGB24[16] = 0x0100;   // 1.0, ap_ufixed<16, 8, AP_TRN_ZERO, AP_SAT>

    // sobel_axis_RGB24
    sobel_axis_RGB24[8] = bmpihr.biHeight;    // row_size
    sobel_axis_RGB24[10] = bmpihr.biWidth;    // col_size
    //sobel_axis_RGB24[6] = 2; // function_r, ORG_IMGwAxiDma
    sobel_axis_RGB24[6] = 3;   // function_r, MEDIANwAxiDma

    // DMA Start
    // MM2S Channel
    axi_dma[0] = 1;         // MM2S_DMACR, Run/Stop bit(bit 0) = 1
    axi_dma[6] = phys_addr; // MM2S_SA
    axi_dma[10] = image_all_bytes; // MM2S_LENGTH(bytes), Start
    // S2MM Channel
    axi_dma[12] = 1;        // S2MM_DMACR, Run/Stop bit(bit 0) = 1
    axi_dma[18] = phys_addr + image_all_bytes; // S2MM_SA
    axi_dma[22] = image_all_bytes; // S2MM_LENGTH(bytes), Start
    // Image IPs start
    gaussian_axis_RGB24[0] = 1; // start
    median_axis_RGB24[0] = 1;   // start
    color_converter_RGB24[0] = 1;   // start
    sobel_axis_RGB24[0] = 1;    // start

    // Waiting for DMA to finish
    while(!(axi_dma[13] & 2)) ;     // Waiting Idle bit (S2MM_DMASR, bit 1)

    // Write filtered image file
    if ((fbmpw=fopen(OUTPUT_IMG_FILE, "wb")) == NULL){
        fprintf(stderr, "Can't open %s by binary write mode\n", OUTPUT_IMG_FILE);
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);

    // RGB データの書き込み、逆順にする
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            uint32_t pixel = wr_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x];
            blue = pixel & 0xff;
            green = (pixel >> 8) & 0xff;
            red = (pixel >> 16) & 0xff;

            fputc(blue, fbmpw);
            fputc(green, fbmpw);
            fputc(red, fbmpw);
        }
    }
    fclose(fbmpw);

    munmap((void *)image_buf, 2*image_all_bytes);
    munmap((void *)axi_dma, 0x10000);
    munmap((void *)gaussian_axis_RGB24, 0x10000);
    munmap((void *)median_axis_RGB24, 0x10000);
    munmap((void *)color_converter_RGB24, 0x10000);
    munmap((void *)sobel_axis_RGB24, 0x10000);

    close(fd4);
    close(fd5);
    close(fd6);
    close(fd7);
    close(fd8);
    close(fd9);

    return(0);
}

  1. 2023年10月05日 04:58 |
  2. ZUBoard
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/6058-bdecb639
この記事にトラックバックする(FC2ブログユーザー)