欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2019.6.17 xilinx FPGA zynq && zynqMP linux bitstream烧写程序

程序员文章站 2022-07-12 11:29:19
...

bitstream PL 加载参考地址:
zynqMP:https://xilinxwiki.atlassian.net/wiki/spaces/A/pages/18841847/Solution+ZynqMP+PL+Programming
zynq:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841750/Solution+Zynq+PL+Programming
烧写github:https://github.com/clancylea/auto_loadbitstream
本文参考xilinx官方案例,可省去手工加载bitstream过程,直接生成./elf可执行文件。
方便了应用程序中的使用,如有错误之处还请不吝赐教!

1、需在在SDK中创建linux应用程序

#include <iostream>

using namespace std;
#include <string>
#include <limits.h>
#include <stdlib.h>
#include <stdexcept>
#include <chrono>
#include <vector>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <thread>


class GeneralUtils {
    public:
        typedef std::chrono::high_resolution_clock::time_point chrono_t;
        static bool dirExists(std::string const &path);
        static bool fileExists(std::string const &path);
        static std::string dirname(std::string const &);
        static std::string filename(std::string const &);
        static std::string abspath(std::string const &);
        static std::string abspathReference(std::string const &, std::string const &);
        static std::string readStringFile(std::string const &);
        static void readStringFile(std::string &, std::string const &);
        static std::vector<char> readBinaryFile(std::string const &);
        static void readBinaryFile(std::vector<char> &, std::string const &);
        static void configureFabric(std::vector<char> const &buffer);
        static void loadBitstreamFile(std::string const &);
        static unsigned int padTo(unsigned int , unsigned int );
        static signed long long getTime(chrono_t &);
        static chrono_t getTimer();
    private:
        GeneralUtils() {};
        ~GeneralUtils() {};
};


GeneralUtils::chrono_t GeneralUtils::getTimer() {
    return std::chrono::high_resolution_clock::now();
}

signed long long GeneralUtils::getTime(GeneralUtils::chrono_t &timer) {
    chrono_t now =  std::chrono::high_resolution_clock::now();
    return (signed long long) std::chrono::duration_cast<std::chrono::microseconds>(now - timer).count();
}

std::string GeneralUtils::abspathReference(std::string const &path, std::string const &ref) {
    std::string result;
    std::size_t slash = path.find_first_of("\\/");
    if (slash != std::string::npos && slash == 0) {
        return GeneralUtils::abspath(path);
    } else {
        return GeneralUtils::abspath(ref + "/" + path);
    }
}

std::string GeneralUtils::abspath(std::string const &path) {
    char *p = (char *) malloc(PATH_MAX * sizeof(char));
    if (realpath(path.c_str(), p) == NULL) {
        free(p);
        throw std::runtime_error("Could not find " + path+ "!");
    }
    std::string result(p);
    free(p);
    return result;
}

std::string GeneralUtils::dirname(std::string const &path) {
    std::size_t slash = path.find_last_of("\\/");
    if (slash != std::string::npos) {
        return path.substr(0, slash);
    } else {
        return std::string("./");
    }
}

std::string GeneralUtils::filename(std::string const &path) {
    std::size_t slash = path.find_last_of("\\/");
    if (slash != std::string::npos) {
        return path.substr(slash+1, std::string::npos);
    } else {
        return std::string("");
    }
}

std::string GeneralUtils::readStringFile(std::string const &filename) {
    std::string buf;
    GeneralUtils::readStringFile(buf, filename);
    return buf;
}

void GeneralUtils::readStringFile(std::string &buffer, std::string const &filename) {
    std::vector<char> buf;
    GeneralUtils::readBinaryFile(buf, filename);
    buffer = std::string(buf.begin(), buf.end());
}

std::vector<char> GeneralUtils::readBinaryFile(std::string const &filename) {
    std::vector<char> buf;
    GeneralUtils::readBinaryFile(buf, filename);
    return buf;
}

void GeneralUtils::readBinaryFile(std::vector<char> &buffer, std::string const &filename) {
    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file.is_open()) {
        throw std::runtime_error("Could not open file " + filename);
    } else {
        file.seekg(0, std::ios::end);
        std::streampos fileSize = file.tellg();
        file.seekg(0, std::ios::beg);
        buffer.resize(fileSize);
        file.read(buffer.data(), fileSize);
        if (file.gcount() != fileSize) {
            throw std::runtime_error("Could not read all file characters!");
        }
        file.close();
    }
}

unsigned int GeneralUtils::padTo(unsigned int num, unsigned int padTo) {
    if(num % padTo == 0) {
        return num;
    } else {
        return num + padTo - (num % padTo);
    }
}

bool GeneralUtils::fileExists(std::string const &path) {
    struct stat info;
    if ( stat(path.c_str(), &info) != 0 ) {
        return false;
    } else if( info.st_mode & S_IFDIR ) {
        return false;
    }
    return true;
}

bool GeneralUtils::dirExists(std::string const &path) {
    struct stat info;
    if ( stat(path.c_str(), &info) != 0 ) {
        return false;
    } else if (info.st_mode & S_IFDIR) {
        return true;
    }
    return false;
}




void GeneralUtils::configureFabric(std::vector<char> const &buffer) {
    if (GeneralUtils::fileExists("/dev/xdevcfg")) {
        //We are on Kernel 4.6 or lower
        FILE *fd = fopen("/dev/xdevcfg", "w");
        if (fd == NULL) {
            throw std::runtime_error("Could not open /dev/xdevcfg device");
        }
        size_t written = fwrite(buffer.data(), sizeof(char), buffer.size(), fd);
        if (written != buffer.size()) {
            throw std::runtime_error("Could not write complete bitstream to /dev/xdevcfg");
        }
        fclose(fd);
    } else if (GeneralUtils::fileExists("/sys/class/fpga_manager/fpga0/firmware")) {
        const char bitstreamFile[] = "fabric_bitstream.bin";

        std::ofstream bitstream(std::string("/lib/firmware/") + bitstreamFile, std::ios::out | std::ios::binary | std::ios::trunc);
        bitstream.write(buffer.data(), buffer.size());
        bitstream.close();

        std::ofstream firmware("/sys/class/fpga_manager/fpga0/firmware");
        firmware << bitstreamFile;
        firmware.close();
        if (!firmware.good()) {
            throw std::runtime_error("Fabric configuration through fpga_manager failed!");
        }
        // Loading was successful, wait for half a second before using the fpga!
        // or else the board is gone... praise the fpga_manager
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    } else {
        // TODO load AWS bitstream
    }
}

void GeneralUtils::loadBitstreamFile(std::string const &bitstreamPath) {
    GeneralUtils::configureFabric(GeneralUtils::readBinaryFile(bitstreamPath));
}

2、主程序

int main()
{
    // load test images from binary files
	std::string const &bitstreamPath = "design_1_wrapper.bin";
	GeneralUtils::loadBitstreamFile(bitstreamPath);
	printf("loadBitstreamFile ok");
}