前言

本篇文章主要讲解在Xilinx ZedBoard上通过VxWorks6.9动态加载FPGA bit/bin文件,从而实现软件定义功能目的。本文力求讲述清楚PS动态加载PL的原理和实现方法,并配套完整的演示软件和相关代码进行验证。下面将从以下几个方面进行讲解。

  1. Zynq7000 PL加载原理设计
  2. VxWorks6.9动态加载FPGA

开发使用工具说明:

  1. WorkBench3.3

1、Zynq7000 PL加载原理设计

图1 非安全启动流程框图

如图1所示,非安全启动流程中PS通过芯片的固件程序从存储设备中读取引导软件fsbl到芯片RAM运行从而完成PS的整个启动流程。PL加载的通道则从PS通过AXI总线到达设备配置模块,然后通过PCAP进行加载。

除了JTAG加载PL之外,PL可以使用PCAP进行配置。用户可以在任何时候配置PL,无论是在PS使用FSBL启动后,还是在操作系统启动之后加载PL的镜像。本节介绍配置PL的要求。PL加载前必须先上电,才能进行配置。重复加载需要复位清除PL的配置SRAM单元。

表1 设备配置寄存器表

本文主要讲解PCAP配置PL的流程,其主要是通过配置表1的寄存器进行操作。

(1) PCAP配置PL

发送配置位流,PL必须完成内部清除工作。其状态由DevC的status寄存器中的[PCFG_INIT]位指示。内部环回功能也必须禁用,并且[PCAP_MODE]位必须设置。位流被传输到PL使用DevC DMA。PCFG_DONE标志表示PL配置成功。具体配置流程为:

1.  等待PL([0xF8007014]STATUS-bit[4])将PCFG_INIT设置为高;

2. 设置内部环回为0 ([0xF8007080]MCTRL-bit[4]),关闭内部环回;

3. 设置PCAP_PR和PCAP_MODE为1 ([0xF8007000]CTRL-bit[27:26]),选择并使能PCAP接口进行配置;

4. 启动一个DevC DMA传输;

a)源地址:PL位流的位置

b)目的地址:0xFFFFFFFF

c)源长度:PL位流中32位字的总数

d)目的长度:PL位流中32位字的总数

5. 等待PL ([0xF800700C]INT_STS-bit[2])将PCFG_DONE设置为高。

(2) PL重复配置

PL配置完成后,使用PCAP重新配置PL,必须在Control中将PCAP_MODE和PCAP_PR位设置为1。内部环回功能也必须禁用。发送重配置位流到使用DevC DMA的PL,源和目标与初始配置相同。PL重复配置流程如下:

  1. 设置PCAP_MODE和PCAP_PR为1, ([0xF8007000]CTRL-bit[27:26]),选择并使能PCAP接口进行配置;

2. 从PL中清除之前的配置;

a)设置PCFG_PROG_B([0xF8007000]CTRL-bit[30])高。

b)设置“PCFG_PROG_B ([0xF8007000]CTRL-bit[30])为低”。

c)检查PCFG_INIT = 0 ([0xF8007014]STATUS-bit[4])。

d)向INT_STS[2]写入1,清除PCFG_DONE_INT。

3.检查PCFG_INIT = 1 (STATUS-bit[4]);

4. 设置INT_PCAP_LPBK为0(MCTRL-bit[4]);

5. 通过向INT_STS[12]写入1来清除D_P_DONE_INT;

6. 启动一个DevC DMA传输;

a)源地址:新PL位流的位置。

b)目的地址:0xFFFF_FFFF。

c)Source Length:新的PL位流中32位字的总数。

d) Destination Length:新PL位流中32位字的总数。

7. 轮询或等待devcfg。INT_STS[D_P_DONE_INT]触发中断;

8. (可选)如果清除了之前的配置,请检查INT_STS上的PCFG_DONE_INT。

如果之前的PL配置没有被使用清除,那么PCFG_DONE标志将不会被设置PCFG_PROG_B。在这种情况下,应该使用D_P_DONE_INT来指示新的位流,需要注意的是,PCAP和ICAP接口是相互排斥的。一次只有一个接口可以与PL配置控制器通信,使用哪个接口是由DevC的控制寄存器中的PCAP_PR位控制的。

2、VxWorks6.9动态加载FPGA

本文主要目的是为了讲解VxWorks6.9系统下动态加载FPGA位流文件。对外提供一个VxWorks系统加载FPGA位流文件的接口函数。在BSP包里面实现fpga_load_driver.c、fpga_load_driver.h文件,如下图所示。

/****************************************************************

*  文件名称: fpga_load_driver.h

*  文件标识: 定义头文件

*  内容摘要: ZYNQ7000平台FPGA软件加载驱动.

*  其它说明: PS->PL加载,涉及PCAP接口.支持bit和bin格式自适应加载.

*

*  当前版本: V1.00.00

*  作    者: root

*  完成日期: 02/19/2020

****************************************************************/

#ifndef __FPGA_LOAD_H__

#define __FPGA_LOAD_H__

//#define  FPGA_LOAD_DEBUG                 1

/* fpga load return value definitions */

#define FPGA_SUCCESS                    0

#define FPGA_FAIL                       -1

int zynq_load_fs(char *pFilePath);

#endif /* __FPGA_LOAD_H__ */

1、定义操作寄存器接口

#define ZYNQ_SYS_CTRL_BASEADDR          0xF8000000

#define ZYNQ_DEV_CFG_APB_BASEADDR       0xF8007000

/* Reflect slcr offsets */

struct slcr_regs {

UINT32 scl; /* 0x0 */

UINT32 slcr_lock; /* 0x4 */

UINT32 slcr_unlock; /* 0x8 */

UINT32 reserved0_1[61];

UINT32 arm_pll_ctrl; /* 0x100 */

UINT32 ddr_pll_ctrl; /* 0x104 */

UINT32 io_pll_ctrl;  /* 0x108 */

UINT32 reserved0_2[5];

UINT32 arm_clk_ctrl; /* 0x120 */

UINT32 ddr_clk_ctrl; /* 0x124 */

UINT32 dci_clk_ctrl; /* 0x128 */

UINT32 aper_clk_ctrl; /* 0x12c */

UINT32 reserved0_3[2];

UINT32 gem0_rclk_ctrl; /* 0x138 */

UINT32 gem1_rclk_ctrl; /* 0x13c */

UINT32 gem0_clk_ctrl; /* 0x140 */

UINT32 gem1_clk_ctrl; /* 0x144 */

UINT32 smc_clk_ctrl;  /* 0x148 */

UINT32 lqspi_clk_ctrl; /* 0x14c */

UINT32 sdio_clk_ctrl; /* 0x150 */

UINT32 uart_clk_ctrl; /* 0x154 */

UINT32 spi_clk_ctrl; /* 0x158 */

UINT32 can_clk_ctrl; /* 0x15c */

UINT32 can_mioclk_ctrl; /* 0x160 */

UINT32 dbg_clk_ctrl; /* 0x164 */

UINT32 pcap_clk_ctrl; /* 0x168 */

UINT32 reserved0_4[1];

UINT32 fpga0_clk_ctrl; /* 0x170 */

UINT32 reserved0_5[3];

UINT32 fpga1_clk_ctrl; /* 0x180 */

UINT32 reserved0_6[3];

UINT32 fpga2_clk_ctrl; /* 0x190 */

UINT32 reserved0_7[3];

UINT32 fpga3_clk_ctrl; /* 0x1a0 */

UINT32 reserved0_8[8];

UINT32 clk_621_true; /* 0x1c4 */

UINT32 reserved1[14];

UINT32 pss_rst_ctrl; /* 0x200 */

UINT32 reserved2[15];

UINT32 fpga_rst_ctrl; /* 0x240 */

UINT32 reserved3[5];

UINT32 reboot_status; /* 0x258 */

UINT32 boot_mode; /* 0x25c */

UINT32 reserved4[116];

UINT32 trust_zone; /* 0x430 */ /* FIXME */

UINT32 reserved5_1[63];

UINT32 pss_idcode; /* 0x530 */

UINT32 reserved5_2[51];

UINT32 ddr_urgent; /* 0x600 */

UINT32 reserved6[6];

UINT32 ddr_urgent_sel; /* 0x61c */

UINT32 reserved7[56];

UINT32 mio_pin[54]; /* 0x700 - 0x7D4 */

UINT32 reserved8[74];

UINT32 lvl_shftr_en; /* 0x900 */

UINT32 reserved9[3];

UINT32 ocm_cfg; /* 0x910 */

};

struct devcfg_regs {

UINT32 ctrl; /* 0x0 */

UINT32 lock; /* 0x4 */

UINT32 cfg; /* 0x8 */

UINT32 int_sts; /* 0xc */

UINT32 int_mask; /* 0x10 */

UINT32 status; /* 0x14 */

UINT32 dma_src_addr; /* 0x18 */

UINT32 dma_dst_addr; /* 0x1c */

UINT32 dma_src_len; /* 0x20 */

UINT32 dma_dst_len; /* 0x24 */

UINT32 rom_shadow; /* 0x28 */

UINT32 reserved1[2];

UINT32 unlock; /* 0x34 */

UINT32 reserved2[18];

UINT32 mctrl; /* 0x80 */

UINT32 reserved3;

UINT32 write_count; /* 0x88 */

UINT32 read_count; /* 0x8c */

};

#define devcfg_base ((struct devcfg_regs *)ZYNQ_DEV_CFG_APB_BASEADDR)

#define slcr_base   ((struct slcr_regs *)ZYNQ_SYS_CTRL_BASEADDR)

#define vxReadl(addr)        *(volatile UINT32 *)(addr)

#define vxWritel(data, addr)    *(volatile UINT32 *)(addr) = (data)

2、配置DMA传输初始化

static int zynq_dma_transfer(UINT32 srcbuf, UINT32 srclen, UINT32 dstbuf, UINT32 dstlen)

{

UINT32 isr_status;

struct timeval start_time, now;

/* Set up the transfer */

vxWritel((UINT32)srcbuf, &devcfg_base->dma_src_addr);

vxWritel(dstbuf, &devcfg_base->dma_dst_addr);

vxWritel(srclen, &devcfg_base->dma_src_len);

vxWritel(dstlen, &devcfg_base->dma_dst_len);

isr_status = vxReadl(&devcfg_base->int_sts);

/* Polling the PCAP_INIT status for Set */

gettimeofday(&start_time, NULL);

while (!(isr_status & DEVCFG_ISR_DMA_DONE))

{

if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) {

printf("%s: Error: isr = 0x%08X\n", __func__,

isr_status);

printf("%s: Write count = 0x%08X\n", __func__,

vxReadl(&devcfg_base->write_count));

printf("%s: Read count = 0x%08X\n", __func__,

vxReadl(&devcfg_base->read_count));

return FPGA_FAIL;

}

gettimeofday(&now, NULL);

if (now.tv_sec - start_time.tv_sec > CONFIG_SYS_FPGA_PROG_TIME) {

printf("%s: Timeout wait for DMA to complete\n",

__func__);

return FPGA_FAIL;

}

isr_status = vxReadl(&devcfg_base->int_sts);

}

debug("%s: DMA transfer is done\n", __func__);

/* Clear out the DMA status */

vxWritel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);

return FPGA_SUCCESS;

}

3、 实现FPGA文件动态加载接口

int zynq_load_fs(char *pFilePath)

{

int fd;

int ret;

UINT32 swap, diff;

int filehead, fileend, filelen;

UINT32 *buf_start = NULL;

fd = open(pFilePath, O_RDONLY, 0777);

if (fd < 0)

{

printf("no %s such file\n", pFilePath);

return FPGA_FAIL;

}

filehead = lseek(fd, 0, SEEK_SET);

fileend = lseek(fd, 0, SEEK_END);

lseek(fd, 0, SEEK_SET);

filelen = fileend - filehead;

//dcache_disable();

char *buf = (char *)malloc(filelen);

if(NULL == buf)

{

printf("not enough mem!\n");

return FPGA_FAIL;

}

read(fd, (char *)buf, filelen);

buf_start = check_data((UINT8 *)buf, filelen, &swap);

diff = (UINT32)buf_start - (UINT32)buf;

/* fpga bit file */

if (diff != 0)

{

ret = zynq_load(buf+diff, filelen-diff, BIT_FULL);

}

else  /* fpga bin file */

{

ret = zynq_load(buf, filelen, BIT_FULL);

}

//dcache_enable();

if (ret != FPGA_SUCCESS)

{

printf("fpga load fail!\n");

free(buf);

close(fd);

return FPGA_FAIL;

}

printf("fpga load success!\n");

free(buf);

close(fd);

return FPGA_SUCCESS;

}

基于Zynq7000平台VxWorks6.9开发应用——FPGA动态加载篇相关推荐

  1. 爬取在行平台数据(1)——动态加载页面分析

    谈及动态加载页面,最先想到的一种情形是这样的--"加载更多": 面对这种动态加载的页面,要想获得更多的数据,往往需要借助开发者工具进行辅助分析.回归正题,本文依次介绍爬取对象.分析 ...

  2. LVGL学习之路——基于lv_lib_freetype库的TTF字体文件动态加载中文字体(阿里普惠字体)

    前言   在学习lvgl中,在英文字体上很多人都用过,但是中文字体往往需要靠取模去实现.那么我就在想,如何像windows那样加载动态的字体呢,这样想做多大字体都行.于是就开始了字体的移植. 什么是t ...

  3. 携程Android App插件化和动态加载实践

    转载自:http://www.infoq.com/cn/articles/ctrip-android-dynamic-loading?email=947091870@qq.com 编者按:本文为携程无 ...

  4. osgi框架 android,基于OSGi的Android应用模块动态加载框架设计与实现

    摘要: 伴随着移动互联网科技水平向4G的飞跃,移动终端的使用日趋常态化,移动智能设备的普及率越来越高,得到了大量使用者的追捧.与此同时,各手机操作系统下应用商店里正充斥着琳琅满目的移动应用产品,用户对 ...

  5. xilinx FPGA的远程更新(动态加载)详解(Using a Microprocessor to Configure 7 Series FPGAs)

    目录 1 概述 2 参考文件 3 远程更新思路 4 MIC配置FPGA的模式 4.1 slave serial mode情况 4.2 slave selectMAP mode情况 5 FPGA配置时序 ...

  6. 基于vue-router的从后端动态加载菜单的实现

    基于vue-router的从后端动态加载菜单的实现 源码下载 前言 后端模拟加载菜单的例子实现 VueRouterController.java CorsConfig.java application ...

  7. vue 动态修改后端请求_vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单...

    一. 前言 本篇基于 有来商城 youlai-mall微服务项目,通过对vue-element-admin的权限菜单模块理解个性定制其后台接口,实现对vue-element-admin工程几乎不做改动 ...

  8. flink sql udf jar包_FlinkSQL 动态加载 UDF 实现思路

    导读: 最近在对 Flink 进行平台化,基于 REST API 构建一个平台实现通过纯 SQL 化编写和管理 Job.尽管 Flink官方希望用户将所有的依赖和业务逻辑打成一个fat jar,这样方 ...

  9. netcore实践:跨平台动态加载native组件

    缘起netcore框架下实现基于zmq的应用.在.net framework时代,我们进行zmq开发由很多的选择,比较常用的有clrzmq4和NetMQ. 其中clrzmq是基于libzmq的Inte ...

  10. flinksql获取系统当前时间搓_FlinkSQL 动态加载 UDF 实现思路

    导读: 最近在对 Flink 进行平台化,基于 REST API 构建一个平台实现通过纯 SQL 化编写和管理 Job.尽管 Flink官方希望用户将所有的依赖和业务逻辑打成一个fat jar,这样方 ...

最新文章

  1. MySQL数据库服务器的架设
  2. 深入浅出SQL(三)——表的规范化
  3. 基于开源流程引擎Activiti5的工作流开发平台BPMX3
  4. 可重入锁 不可重入锁_什么是可重入锁?
  5. JS之字符串连接方法join
  6. Android 自动动画布局更新 使用,在RecyclerView上使用布局动画(Layout animation)
  7. jenkins source files 和 Remove Prefix 用户
  8. java描述线性探测_实现基于线性探测的哈希表1
  9. 为什么 Nginx 比 Apache 更牛叉?
  10. vs2005启动不了,手把手教你修复它
  11. 林子雨spark scala版编程小结
  12. Butterworth低通滤波器 Matlab实现
  13. k620显卡linux驱动下载,K620k620驱动的安装方法和丽台k620显卡可以玩哪些游戏
  14. 软考倒计时19天:招投标法、合同法、采购法
  15. Let's Encrypt申请证书-保姆教程
  16. BUUCTF中的“新年快乐”
  17. css实现六边形图片(最简单易懂方法实现高逼格图片展示)
  18. php微信支付mch_id参数格式错误,在.net core上,Web网站调用微信支付-统一下单接口(xml传参)一直返回错误:mch_id参数格式错误...
  19. 微信步数日历打卡小程序
  20. 辛普森悖论和朴素贝叶斯

热门文章

  1. Spring核心注解
  2. 我国无线2.4g及5g信道-个人笔记
  3. Netty 是什么,Netty原理详解
  4. java 主流框架_java的三大主流框架介绍
  5. 【开发工具】【Java开发工具 IDEAIU-2017.3】【安装和激活】
  6. 制造业生产规划与排程的福音—APS系统
  7. Android BT STACK BTU 和 HCI之间的消息传递
  8. httppost请求工具类
  9. prometheus使用cAdvisor监控容器
  10. win10卸载内置应用_如何卸载Windows 10的内置应用程序(以及如何重新安装它们)...