FC2カウンター FPGAの部屋 Zynq の PCAP を使用して DFX する3(xdevcfg_polled_example.c をマージする1)
fc2ブログ

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

FPGAの部屋

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

Zynq の PCAP を使用して DFX する3(xdevcfg_polled_example.c をマージする1)

”Zynq の PCAP を使用して DFX する3(embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/)”の続き。

前回は、”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/”に良いサンプルがあったので、その内の xdevcfg_selftest_example.c と xdevcfg_polled_example.c をやってみた。今回は、その内の xdevcfg_polled_example.c を”画像フィルタを DFX する14(DFX_filter_test プロジェクト7)”の DFX_filter_test.c にマージして DFX してみよう。

さて、 xdevcfg_polled_example.c を DFX_filter_test.c にマージした。
PCAP_20_210826.png

デバックモードで起動する。
PCAP_21_210826.png

デバックモードの画面の内 xsct の画面を使用する。
まずは、カレントディレクトリを表示する。
pwd
ホーム・ディレクトリにいることが分かった。
PCAP_22_210826.png

ホーム・ディレクトリに lap_filter_axis_partial.bin をコピーした。(”Zynq の PCAP を使用して DFX する2(.bin ファイルの生成)”参照)
PCAP_23_210826.png

lap_filter_axis_partial.bin をメモリにダウンロードした。
dow -data lap_filter_axis_partial.bin 0x11000000
PCAP_24_210826.png

ログを示す。

xsct% pwd
/home/masaaki
xsct% dow -data lap_filter_axis_partial.bin 0x11000000

  0%    0MB   0.0MB/s  ??:?? ETA
 38%    0MB   0.3MB/s  ??:?? ETA
 94%    0MB   0.4MB/s  ??:?? ETA
100%    0MB   0.4MB/s  00:01    
Successfully downloaded /home/masaaki/lap_filter_axis_partial.bin
xsct% 


Resume ボタンをクリックして、ソフトウェアを走らせる。
PCAP_25_210826.png

gtkterm に ”Press the key.”が表示された。
カメラ画像が表示された。
PCAP_27_210826.jpg

Enter キーを押すと、”Download the partial bit file of the Laplacian filter and press the key.”が表示された。
Enter キーを押すと、 ”Press the key.”が表示された。
表示画像はラプラシアン・フィルタのようだが、止まっていて、カメラの前で手を振っても画像に反映されない。
PCAP_28_210826.jpg

DFX は成功したようだが?まだ不可解な部分がある。
もしかして、PS の FCLK_RESET0_N が 0 で全体をリセットしたのか?

DFX_filter_test.c を貼っておく。なお、全部貼ると長いので、 cam_reg_set() を除いたコードを貼っておく。 cam_reg_set() については、”画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”を参照のこと。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.
// 2021/08/26 : PCAP partial configuration (Quoted from the following URL)
//              https://github.com/Xilinx/embeddedsw/blob/master/XilinxProcessorIPLib/drivers/devcfg/examples/xdevcfg_polled_example.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "xil_io.h"
#include "xparameters.h"
#include "xdevcfg.h"

#include "xvflip_dma_write.h"
#include "xdma2axis.h"
#include "xthrough_axis.h"
#include "xlap_filter_axis_hw.h"
#include "xsobel_filter_axis_hw.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

#define XLAP_FILTER_AXIS_BASEADDR   0x40000000
#define XSOBEL_FILTER_AXIS_BASEADDR 0x40000000

/************************** Constant Definitions *****************************/
/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are only defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define DCFG_DEVICE_ID      XPAR_XDCFG_0_DEVICE_ID

/*
 * The BIT_STREAM_LOCATION is a dummy address and BIT_STREAM_SIZE_WORDS is a
 * dummy size. This has to replaced with the actual location/size of the bitstream.
 *
 * The 2 LSBs of the Source/Destination address when equal to 2�b01 indicate
 * the last DMA command of an overall transfer.
 * The 2 LSBs of the BIT_STREAM_LOCATION in this example is set to 2b01
 * indicating that this is the last DMA transfer (and the only one).
 */
#define BIT_STREAM_LOCATION 0x11000001  /* Bitstream location */
#define BIT_STREAM_SIZE_WORDS   0x20000     /* Size in Words (32 bit)*/

/*
 * SLCR registers
 */
#define SLCR_LOCK   0xF8000004 /**< SLCR Write Protection Lock */
#define SLCR_UNLOCK 0xF8000008 /**< SLCR Write Protection Unlock */
#define SLCR_LVL_SHFTR_EN 0xF8000900 /**< SLCR Level Shifters Enable */
#define SLCR_PCAP_CLK_CTRL XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x168 /**< SLCR
                    * PCAP clock control register address
                    */

#define SLCR_PCAP_CLK_CTRL_EN_MASK 0x1
#define SLCR_LOCK_VAL   0x767B
#define SLCR_UNLOCK_VAL 0xDF0D

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);
int XDcfgPolledExample(XDcfg *DcfgInstPtr, u16 DeviceId);

XDcfg DcfgInstance;     /* Device Configuration Interface Instance */

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    XThrough_axis XTh_axis_ap;
    int inbyte_in;
    int Status;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);
    XThrough_axis_Initialize(&XTh_axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // through_axis start
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    XThrough_axis_DisableAutoRestart(&XTh_axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);
    while(XThrough_axis_IsIdle(&XTh_axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Laplacian filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Status = XDcfgPolledExample(&DcfgInstance, DCFG_DEVICE_ID);
    //Status = XST_SUCCESS;
    if (Status != XST_SUCCESS) {
        xil_printf("Dcfg Polled Example Test Failed\r\n");
        return XST_FAILURE;
    }

    xil_printf("Successfully ran Dcfg Polled Example Test\r\n");

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // laplacian filter start
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    XThrough_axis_DisableAutoRestart(&XTh_axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);
    while(XThrough_axis_IsIdle(&XTh_axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Sobel filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // sobel filter start
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}

/*****************************************************************************/
/**
* This function downloads the Non secure bit stream to the FPGA fabric
* using the Device Configuration Interface.
*
* @param    DcfgInstPtr is a pointer to the instance of XDcfg driver.
* @param    DeviceId is the unique device id of the device.
*
* @return
*       - XST_SUCCESS if successful
*       - XST_FAILURE if unsuccessful
*
* @note     None
*
****************************************************************************/
int XDcfgPolledExample(XDcfg *DcfgInstPtr, u16 DeviceId)
{
    int Status;
    u32 IntrStsReg = 0;
    u32 StatusReg;
    u32 PartialCfg = 0;

    XDcfg_Config *ConfigPtr;

    /*
     * Initialize the Device Configuration Interface driver.
     */
    ConfigPtr = XDcfg_LookupConfig(DeviceId);

    /*
     * This is where the virtual address would be used, this example
     * uses physical address.
     */
    Status = XDcfg_CfgInitialize(DcfgInstPtr, ConfigPtr,
                    ConfigPtr->BaseAddr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }


    Status = XDcfg_SelfTest(DcfgInstPtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Check first time configuration or partial reconfiguration
     */
    IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    if (IntrStsReg & XDCFG_IXR_DMA_DONE_MASK) {
        PartialCfg = 1;
    }

    /*
     * Enable the pcap clock.
     */
    StatusReg = Xil_In32(SLCR_PCAP_CLK_CTRL);
    if (!(StatusReg & SLCR_PCAP_CLK_CTRL_EN_MASK)) {
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_PCAP_CLK_CTRL,
                (StatusReg | SLCR_PCAP_CLK_CTRL_EN_MASK));
        Xil_Out32(SLCR_UNLOCK, SLCR_LOCK_VAL);
    }

    /*
     * Disable the level-shifters from PS to PL.
     */
    if (!PartialCfg) {
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_LVL_SHFTR_EN, 0xA);
        Xil_Out32(SLCR_LOCK, SLCR_LOCK_VAL);
    }

    /*
     * Select PCAP interface for partial reconfiguration
     */
    if (PartialCfg) {
        XDcfg_EnablePCAP(DcfgInstPtr);
        XDcfg_SetControlRegister(DcfgInstPtr, XDCFG_CTRL_PCAP_PR_MASK);
    }

    /*
     * Clear the interrupt status bits
     */
    XDcfg_IntrClear(DcfgInstPtr, (XDCFG_IXR_PCFG_DONE_MASK |
                    XDCFG_IXR_D_P_DONE_MASK |
                    XDCFG_IXR_DMA_DONE_MASK));

    /* Check if DMA command queue is full */
    StatusReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,
                XDCFG_STATUS_OFFSET);
    if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_F_MASK) ==
            XDCFG_STATUS_DMA_CMD_Q_F_MASK) {
        return XST_FAILURE;
    }

    /*
     * Download bitstream in non secure mode
     */
    XDcfg_Transfer(DcfgInstPtr, (u8 *)BIT_STREAM_LOCATION,
            BIT_STREAM_SIZE_WORDS,
            (u8 *)XDCFG_DMA_INVALID_ADDRESS,
            0, XDCFG_NON_SECURE_PCAP_WRITE);

    /* Poll IXR_DMA_DONE */
    IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    while ((IntrStsReg & XDCFG_IXR_DMA_DONE_MASK) !=
            XDCFG_IXR_DMA_DONE_MASK) {
        IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    }

    if (PartialCfg) {
        /* Poll IXR_D_P_DONE */
        while ((IntrStsReg & XDCFG_IXR_D_P_DONE_MASK) !=
                XDCFG_IXR_D_P_DONE_MASK) {
            IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
        }
    } else {
        /* Poll IXR_PCFG_DONE */
        while ((IntrStsReg & XDCFG_IXR_PCFG_DONE_MASK) !=
                XDCFG_IXR_PCFG_DONE_MASK) {
            IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
        }
        /*
         * Enable the level-shifters from PS to PL.
         */
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_LVL_SHFTR_EN, 0xF);
        Xil_Out32(SLCR_LOCK, SLCR_LOCK_VAL);
    }

    return XST_SUCCESS;
}


BIT_STREAM_LOCATION だが、その説明のDeepL 翻訳結果を貼っておく。

Source/Destinationアドレスの2LSBが2b01に等しい場合は、全体の転送の最後のDMAコマンドを示します。
この例のBIT_STREAM_LOCATIONの2つのLSBは2b01に設定され、これが最後のDMA転送(そして唯一の転送)であることを示しています。

  1. 2021年08月26日 05:14 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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