本帖最后由 FPGA课程 于 2024-9-14 13:08 编辑
软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
1概述 有一些网友跟我提出需要让PS做一些加密算法,PCIE把需要加密的数据发送给下位机,也就是PS的ARM ,ARM计算后,再把数据发送给PCIE。为了正确演示这个数据通路,我们以上位机发送图片数据到开发板的PS,然后PS的ARM对部分数据修改后发送给PCIE上位机。本方案演示PCIE数据和PS DDR数据的交互方案。 2系统构架
3FPGA代码
4SDK代码
主要看下主程序,主程序中分配的内存地址必须确保和PCIE程序中分配的内存地址保持一致,上位机把数据写到UIFDMA_DBUF[0]指向的PS DDR内存地址,PS 程序读出数据并且修改,保持到UIFDMA_DBUF[1]指向的内存地址空间。数据修改完成后,通过GPIO反转,产生一个XDMA中断,通知PCIE数据处理完成。 - int main()
- {
- u32 x=0,y=0 ;
- UIFDMA_DBUF[0] = (void*)BUF_PC2PS;
- UIFDMA_DBUF[1] = (void*)BUF_PS2PC;
- memset(UIFDMA_DBUF[0], 0x00, IMG_SIZE);
- memset(UIFDMA_DBUF[1], 0x00, IMG_SIZE);
- //initial reset gpio
- XGpio_Initialize(&ps2pl_gpio, XPAR_PS2PC_INTR_DEVICE_ID);
- XGpio_SetDataDirection(&ps2pl_gpio, 1, 0x0); XGpio_DiscreteWrite(&ps2pl_gpio, 1, 0x0);
- //set up intrrupt
- init_intr_sys();
- while(1){
- if(wf ram1_cap_done == 1)//wait vmda s2mm write channel intrrupt {
- wfram1_cap_done =0;
- //frush cache data all into ddr
- Xil_DCacheInvalidateRange((INTPTR) UIFDMA_DBUF[0], IMG_SIZE) ;
- for(y=0; y < VIDEO_VSIZE ; y++)
- {
- for(x=0; x < 1920 ; x++)
- {
- UIFDMA_DBUF[1][x+y*1920] = UIFDMA_DBUF[0][x+y*1920]&0x000000ff;
- }
- }
- //frush cache data all into ddr
- Xil_DCacheFlushRange((INTPTR)UIFDMA_DBUF[1], IMG_SIZE);
- //notice pc
- XGpio_DiscreteWrite(&ps2pl_gpio, 1, 0x1);
- usleep(1000);
- XGpio_DiscreteClear(&ps2pl_gpio, 1, 0x0);
- printf("image change done !");
- }
- }
- return XST_SUCCESS;
- }
复制代码
5上位机程序设计
本demo演示中,选择一个彩色的BMP测试图片发送到开发板的PS DDR中,并且通过GPIO产生一个PL中断通知PS,数据已经写入到DDR. PS取出数据,对图像数据做修改后,再次写回到DDR中,并且通过GPIO产生一个中断通知PCIE上位机。 上位机的发送函数如下:
- void MainWindow::on_pushButton_clicked()
- {
- QString filename;
- QPixmap m_Qpixmap;
- unsigned char val;
- char * name;
- filename = QFileDialog::getOpenFileName(this, tr("Select Pic"), "", tr("Images (*.bmp)"));
- if (filename.isEmpty())
- {
- return;
- }
- QByteArray ba = filename.toLatin1();
- name = ba.data();
- get_image_data(&image_h, &image_v, name);
- val = 0x01;
- user_write(ADDR_PC2PL_INTC, 4, &val);
- QImage image(filename);
- m_Qpixmap = QPixmap::fromImage(image, Qt::AutoColor);
- m_Qpixmap = m_Qpixmap.scaled(ui->label1->width() / 8 * 8, ui->label1->height() / 8 * 8, Qt::IgnoreAspectRatio, Qt::FastTransformation);
- ui->label1->setPixmap(m_Qpixmap);
- val = 0x00;
- user_write(ADDR_PC2PL_INTC, 4, &val);
- }
复制代码 上位机的接收函数如下:- void MainWindow ::on_pushButton 2 clicked()
- {
- QPixmap m_Qpixmap ;
- QImage *m_Qimage = new QImage(c2h_align_mem_tmp, image_h, image_v, QImage ::Format_RGB32) ;
- c2h_transfer(FPGA_DDR_START_ADDR2, image_h*image_v * 4, c2h_align_mem_tmp) ;
- m_Qpixmap = QPixmap ::fromImage(*m_Qimage, Qt::AutoColor) ;
- m_Qpixmap = m_Qpixmap.scaled(ui->label2->width() / 8 * 8, ui->label2->height() / 8 * 8, Qt::IgnoreAspectRatio, Qt::FastTransformation) ;
- ui->label2->setPixmap (m_Qpixmap) ;
- }
复制代码
以上函数中回继续调用pcie_fun.c中的DMA通道函数,以及user_write函数,具体的可以打开源码阅读。
6硬件安装
7实验结果
|