fpga demo测试hello world

一 看下机器上是什么fpga设备

root@bms-airtrunk-b-s11fpgav2-app-10-169-58-141:/data/# sudo fpgainfo fme

Board Management Controller, microcontroller FW version unavailable (I/O error)

Last Power Down Cause: Q){

Last Reset Cause: Software reset

Watchdog timeout

//****** FME ******//

Object Id : 0xEC00001

PCIe s:b:d:f : 0000:D8:00:0

Device Id : 0x09C4

Socket Id : 0x00

Ports Num : 01

Bitstream Id : 0x123000200000185

Bitstream Version : 0x30201

Pr Interface Id : 69528db6-eb31-577a-8c36-68f9faa081f6

Board Management Controller, microcontroller FW version unavailable (I/O error)

Last Power Down Cause: Q){

Last Reset Cause: Software reset

Watchdog timeout

//****** FME ******//

Object Id : 0xEC00000

PCIe s:b:d:f : 0000:3B:00:0

Device Id : 0x09C4

Socket Id : 0x00

Ports Num : 01

Bitstream Id : 0x123000200000185

Bitstream Version : 0x30201

Pr Interface Id : 69528db6-eb31-577a-8c36-68f9faa081f6

二 Hello world demo代码

复制代码
#include <stdio.h>          // 引入标准输入输出库,用于 printf() 打印信息`
`#include <opae/fpga.h>      // 引入 OPAE FPGA API 头文件,提供 fpgaOpen/fpgaEnumerate/MMIO 等接口`
`#include <uuid/uuid.h>      // 引入 UUID 处理库,用于 uuid_parse() 解析 AFU GUID 字符串`

`/*`
` * CHECK_RES 是一个宏,用来检查 OPAE API 的返回值。`
` *`
` * OPAE API 通常返回 fpga_result 类型:`
` *   FPGA_OK 表示成功`
` *   其他值表示失败`
` *`
` * 如果 res 不是 FPGA_OK,就打印错误信息,并直接 return -1 退出程序。`
` */`
`#define CHECK_RES(res, msg) \`
`    if (res != FPGA_OK) { \`
`        printf("Error: %s (Result code: %d)\n", msg, res); \`
`        return -1; \`
`    }`

`int` `main()` `{`                                `// 程序入口函数`

`    fpga_result res;`                        `// 保存 OPAE API 调用的返回结果`

`    fpga_token token;`                       `// FPGA token,表示枚举到的某个 FPGA/AFU 对象`
                                            `// 后续 fpgaOpen() 需要用它来打开设备`

`    fpga_handle handle;`                     `// FPGA handle,表示已经打开的 AFU 句柄`
                                            `// 后续 MMIO 读写都通过这个 handle 完成`

    `uint32_t num_matches =` `0;`               `// 保存 fpgaEnumerate() 找到的匹配对象数量`

`    fpga_properties filter =` `NULL;`          `// FPGA 枚举过滤器`
                                            `// 用它指定"我要找什么类型的 FPGA 对象"`

`    fpga_guid afu_guid;`                     `// 保存 AFU GUID 的二进制形式`
                                            `// AFU GUID 用来精确匹配某个加速器`

    `/*`
`     * 创建一个 properties 对象。`
`     *`
`     * fpgaGetProperties(NULL, &filter) 的意思是:`
`     *   不基于已有 token 获取属性,`
`     *   而是创建一个空的 properties/filter 对象。`
`     *`
`     * 这个 filter 后面会被配置成:`
`     *   只查找 FPGA_ACCELERATOR 类型`
`     *   只匹配指定 AFU GUID`
`     */`
`    res =` `fpgaGetProperties(NULL,` `&filter);`
    `CHECK_RES(res,` `"Failed to get properties");`

    `/*`
`     * 设置枚举对象类型为 FPGA_ACCELERATOR。`
`     *`
`     * 这是这段代码里非常关键的一行。`
`     *`
`     * FPGA_DEVICE 表示整个 FPGA 设备/FME 层;`
`     * FPGA_ACCELERATOR 表示 Port 后面的 AFU 加速器。`
`     *`
`     * MMIO 读写通常是针对 AFU/Accelerator 做的,`
`     * 所以这里必须用 FPGA_ACCELERATOR。`
`     */`
`    res =` `fpgaPropertiesSetObjectType(filter, FPGA_ACCELERATOR);`
    `CHECK_RES(res,` `"Failed to set object type");`

    `/*`
`     * 把字符串形式的 AFU UUID 转成二进制 fpga_guid。`
`     *`
`     * 当前机器上 fpgainfo 显示的 Accelerator Id 是:`
`     *   331db30c-9885-41ea-9081-f88b8f655caa`
`     *`
`     * 这里用这个 GUID 来确保程序打开的是正确的 AFU。`
`     */`
    `if` `(uuid_parse("331db30c-9885-41ea-9081-f88b8f655caa", afu_guid)` `<` `0)` `{`
        `printf("Error: invalid AFU GUID\n");`    `// UUID 字符串格式不合法时打印错误`
        `return` `-1;`                              `// 退出程序`
    `}`

    `/*`
`     * 把 AFU GUID 设置到 filter 里。`
`     *`
`     * 这样 fpgaEnumerate() 只会返回 GUID 匹配的 Accelerator。`
`     */`
`    res =` `fpgaPropertiesSetGUID(filter, afu_guid);`
    `CHECK_RES(res,` `"Failed to set AFU GUID");`

    `/*`
`     * 枚举 FPGA 对象。`
`     *`
`     * 参数解释:`
`     *   &filter       :过滤条件数组,这里只有一个 filter`
`     *   1             :filter 数量`
`     *   &token        :输出参数,用来保存找到的第一个匹配 token`
`     *   1             :最多只取 1 个匹配结果`
`     *   &num_matches  :实际找到的匹配数量`
`     *`
`     * 成功后:`
`     *   token 会指向匹配到的 AFU`
`     *   num_matches 会表示找到几个匹配项`
`     */`
`    res =` `fpgaEnumerate(&filter,` `1,` `&token,` `1,` `&num_matches);`
    `CHECK_RES(res,` `"Failed to enumerate");`

    `/*`
`     * 枚举完成后,filter 已经不再需要,释放它。`
`     *`
`     * 注意:`
`     *   token 还要继续用,所以这里只释放 filter。`
`     */`
    `fpgaDestroyProperties(&filter);`

    `/*`
`     * 如果没有找到匹配的 AFU,说明:`
`     *   1. FPGA 上没有加载这个 AFU;`
`     *   2. GUID 写错;`
`     *   3. 当前环境看不到这个 accelerator;`
`     *   4. 驱动/设备节点有问题。`
`     */`
    `if` `(num_matches ==` `0)` `{`
        `printf("No matching FPGA accelerator found!\n");`
        `return` `-1;`
    `}`

    `/*`
`     * 打开枚举到的 AFU。`
`     *`
`     * fpgaOpen() 成功后会得到 handle。`
`     * 后面的 MMIO map/read/write 都基于这个 handle。`
`     *`
`     * 第三个参数 0 表示默认 open flags。`
`     */`
`    res =` `fpgaOpen(token,` `&handle,` `0);`
    `CHECK_RES(res,` `"Failed to open FPGA accelerator");`

    `/*`
`     * 映射 MMIO region 0。`
`     *`
`     * MMIO = Memory-Mapped I/O。`
`     * Host CPU 可以通过 MMIO 地址读写 FPGA 暴露出来的寄存器。`
`     *`
`     * 参数解释:`
`     *   handle :已经打开的 AFU handle`
`     *   0      :MMIO region index,这里使用 region 0`
`     *   NULL   :不返回直接 mmap 出来的指针`
`     *`
`     * 这里虽然传 NULL,但后面仍然可以使用:`
`     *   fpgaWriteMMIO32()`
`     *   fpgaReadMMIO32()`
`     *`
`     * 因为这些 API 内部会通过 handle 和 region index 完成访问。`
`     */`
`    res =` `fpgaMapMMIO(handle,` `0,` `NULL);`
    `CHECK_RES(res,` `"Failed to prepare MMIO region 0");`

    `/*`
`     * 设置要访问的 AFU 寄存器偏移。`
`     *`
`     * 这里的 0x100 不是 CPU 虚拟地址,`
`     * 而是 AFU MMIO region 0 内部的寄存器偏移。`
`     *`
`     * 是否有效取决于你的 AFU register map。`
`     */`
    `uint32_t offset =` `0x100;`

    `/*`
`     * 准备写入 FPGA 寄存器的数据。`
`     */`
    `uint32_t data_to_fpga =` `0x12345678;`

    `/*`
`     * 打印即将写入的数据。`
`     */`
    `printf("Host CPU is writing data to FPGA register: 0x%X\n", data_to_fpga);`

    `/*`
`     * 向 AFU 的 MMIO region 0 写一个 32-bit 数据。`
`     *`
`     * 参数解释:`
`     *   handle       :AFU handle`
`     *   0            :MMIO region index`
`     *   offset       :寄存器偏移,这里是 0x100`
`     *   data_to_fpga :要写入的数据`
`     *`
`     * 实际含义是:`
`     *   向 FPGA AFU 的 region 0 + 0x100 位置写入 0x12345678。`
`     */`
`    res =` `fpgaWriteMMIO32(handle,` `0, offset, data_to_fpga);`
    `CHECK_RES(res,` `"Failed to write MMIO");`

    `/*`
`     * 准备一个变量,用来保存从 FPGA 读回来的 32-bit 数据。`
`     */`
    `uint32_t data_from_fpga =` `0;`

    `/*`
`     * 从 AFU 的 MMIO region 0 读取一个 32-bit 数据。`
`     *`
`     * 注意:`
`     *   这里读的地址是 offset + 0x10,`
`     *   也就是 0x100 + 0x10 = 0x110。`
`     *`
`     * 也就是说:`
`     *   你写的是 0x100,`
`     *   读的是 0x110。`
`     *`
`     * 因此读回来的值不一定等于刚才写入的 0x12345678。`
`     *`
`     * 这是否正确,取决于你的 AFU register map。`
`     * 例如有些 AFU 设计是:`
`     *   0x100 是输入寄存器`
`     *   0x110 是输出寄存器`
`     */`
`    res =` `fpgaReadMMIO32(handle,` `0, offset,` `&data_from_fpga);`
    `CHECK_RES(res,` `"Failed to read MMIO");`

    `/*`
`     * 打印从 FPGA 读回来的数据。`
`     */`
    `printf("Host CPU read data from FPGA register: 0x%X\n", data_from_fpga);`

    `/*`
`     * 如果程序走到这里,说明:`
`     *   AFU 枚举成功;`
`     *   AFU 打开成功;`
`     *   MMIO map 成功;`
`     *   MMIO write 成功;`
`     *   MMIO read 成功。`
`     */`
    `printf("Hello World! Communication successful!\n");`

    `/*`
`     * 解除 MMIO region 0 的映射。`
`     *`
`     * 这是 fpgaMapMMIO() 的配套释放操作。`
`     */`
    `fpgaUnmapMMIO(handle,` `0);`

    `/*`
`     * 关闭 AFU handle。`
`     *`
`     * 这是 fpgaOpen() 的配套释放操作。`
`     */`
    `fpgaClose(handle);`

    `/*`
`     * 销毁 token。`
`     *`
`     * 这是 fpgaEnumerate() 返回 token 后的配套释放操作。`
`     */`
    `fpgaDestroyToken(&token);`

    `/*`
`     * 返回 0,表示程序正常结束。`
`     */`
    `return` `0;`
`}`
`
复制代码
创建 filter`
`→ 指定查找 FPGA_ACCELERATOR`
`→ 指定 AFU GUID`
`→ 枚举 AFU`
`→ 打开 AFU`
`→ map MMIO region 0`
`→ 写寄存器 0x100`
`→ 读寄存器 0x100`
`→ 释放资源`
`
相关推荐
黑猫学长呀2 小时前
存储宝典第6篇:测试机台的PE板和PPB板有什么区别?
测试工具·fpga开发·ssd·芯片测试·ate·存储芯片·测试机台
GateWorld6 小时前
LCD显示技术完全指南:原理·制造·驱动·FPGA实现之基础一
fpga开发·lcd显示·fpga点亮屏幕·minilvds
Coder-hong17 小时前
TopJTAG Probe连接zynq
fpga开发
Aaron15881 天前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
ALINX技术博客1 天前
【黑金云课堂】FPGA技术教程Linux开发:串行通信接口与实时时钟模块
linux·fpga开发
Felven1 天前
国产ZYNQ multiboot功能介绍与实现
linux·fpga开发·multiboot·国产zynq
cjie2211 天前
DDR3速率分档
fpga开发
坏孩子的诺亚方舟2 天前
open_prj22_IIC读写EEPROM、AD/DA、PLSYSMON
fpga开发·mpsoc
cjie2212 天前
仿真xilinx库加glbl()的作用
fpga开发