XILINX FPGA软核MicroBlaze开发资料汇总分享-Xilinx-AMD论坛-FPGA CPLD-ChipDebug

XILINX FPGA软核MicroBlaze开发资料汇总分享

MicroBlaze

所述的MicroBlaze是一个软微处理器核心设计用于赛灵思 现场可编程门阵列(FPGA)。作为软核处理器,MicroBlaze完全在Xilinx FPGA的通用存储器和逻辑结构中实现。

概述

就其指令集架构而言,MicroBlaze类似于Patterson和Hennessy在流行的计算机体系结构书籍中描述的基于RISC的DLX架构。除了少数例外,MicroBlaze可以在每个周期发出新指令,在大多数情况下保持单周期吞吐量。

MicroBlaze具有多功能互连系统,可支持各种嵌入式应用。MicroBlaze的主要I / O总线即AXI互连,是一种具有主从功能的系统内存映射事务总线。较旧版本的MicroBlaze使用CoreConnect PLB总线。大多数供应商提供的和第三方IP接口直接(或通过AXI互连)到AXI。为了访问本地存储器(FPGA RAM),MicroBlaze使用专用的LMB总线,提供快速的片上存储。通过专用的AXI4-Stream连接支持用户定义的协处理器。协处理器接口可以通过将部分或全部计算卸载到用户设计的硬件模块来加速计算密集型算法。

MicroBlaze的许多方面都可以由用户配置:缓存大小,流水线深度(3级,5级或8级),嵌入式外围设备,内存管理单元和总线接口可以定制。MicroBlaze的区域优化版本使用3级流水线,牺牲了时钟频率以减少逻辑区域。性能优化版本将执行流程扩展到5个阶段,允许超过700 MHz的最高速度(在Virtex UltraScale + FPGA系列上)。此外,关键处理器指令这些很少使用但在硬件中实现起来更昂贵,可以有选择地添加/删除(例如乘法,除法和浮点运算)。此自定义使开发人员能够针对特定的主机硬件和应用程序软件要求进行适当的设计权衡。

通过内存管理单元,MicroBlaze能够托管需要基于硬件的分页和保护的操作系统,例如Linux内核。否则,它仅限于具有简化保护和虚拟内存模型的操作系统,例如FreeRTOS或不支持MMU的Linux。MicroBlaze的整体吞吐量基本上小于可比硬化CPU核心(如ARM的Cortex-A9在ZYNQ)。

Vivado

Xilinx的Vivado设计套件是用于在Xilinx FPGA中构建当前MicroBlaze(或ARM – 参见Zynq)嵌入式处理器系统的开发环境。旧版本使用Xilinx的EDK(嵌入式开发套件)开发包。

设计人员使用Vivado IP Integrator配置和构建其嵌入式系统的硬件规格(处理器内核,内存控制器,I / O外设等).IP Integrator将设计人员的块设计转换为可合成的RTL描述(Verilog或VHDL)),并自动执行嵌入式系统(从RTL到比特流文件。)对于MicroBlaze核心,Vivado生成加密(非人类可读)网表。

SDK处理将在嵌入式系统上执行的软件。SDK 由GNU工具链(GNU编译器集合,GNU调试器)提供支持,使程序员能够为其嵌入式系统编写,编译和调试C / C ++应用程序。Xilinx的工具提供了在仿真中运行软件的可能性,或者使用合适的FPGA板在实际系统上下载和执行。

Vivado的购买者获得永久许可,可在Xilinx FPGA中使用MicroBlaze,且不会产生经常性使用费。许可证不授予在Xilinx设备之外使用MicroBlaze的权利。

Altium提供了替代编译器和开发工具,但仍需要EDK安装和许可证。

开源

2009年6月,MicroBlaze成为第一个融入主线Linux内核源代码树的软CPU架构。这项工作由Michal Simek执行,并由PetaLogix和Xilinx提供支持。

截至2009年9月,MicroBlaze GNU工具支持也被贡献给自由软件基金会的主线存储库。从版本4.6 [1]开始,GCC版本中包含对MicroBlaze的支持

###
其他软处理器

Nios II
TSK3000
Xtensa
LatticeMico32
ARC


在FPGA设计中使用Xilinx的MicroBlaze

本文为机译,原文为《Utilizing Xilinx’s MicroBlaze in FPGA Design》

MicroBlaze是一款32位软RISC处理器内核,旨在加速传统上需要一个或多个微控制器的成本敏感型大批量应用的开发。

Xilinx成本优化产品组合FPGA上的MicroBlaze提供了工具套件和FPGA平台的进步,有助于简化开发工作并最大限度地减少系统预算。Xilinx致力于提高MicroBlaze处理器软核的可用性,使工程师能够快速配置嵌入式硬件平台,并立即在行业标准环境中启动软件编码。

作为嵌入式处理器,MicroBlaze使Xilinx的FPGA产品组合能够满足工业,通信基础设施,医疗设备,汽车和消费者市场的集成和性能要求。通过平台和处理器的正确组合,设计人员可以设计解决方案,以满足其架构挑战,包括I / O外设,通信接口,实时功能和操作系统支持的正确组合。

Xilinx_Microblaze_figure_1.jpg
图1. MicroBlaze核心架构

MicroBlaze有何不同之处?

传统上,在FPGA中实现像MicroBlaze这样的处理器软核以获得最大的集成优势意味着需要相当长的时间。加速上市时间意味着迫切需要立即开始软件开发,最后需要的是在编码开始之前额外的学习曲线和微控制器平台的设计开销。通过引入开发流程来解决此问题,该开发流程允许编码立即启动,而无需等待定制的硬件平台。

这些更新可用于成本优化的FPGA系列的一系列开发套件,包括要构建的示例项目。如果您需要与MicroBlaze集成的特定功能,例如收发器,接口或DSP算法,则可以通过可与MicroBlaze集成的工具链获得“拖放”IP组合。在大多数情况下,IP提供商都有示例项目和教程,可指导您完成实施,并通过试用期或系留选项使设计人员能够立即进行原型设计。Xilinx工具提供支持大多数开发板的免费Web版本。

这与以前的FPGA不同,在这些FPGA中,您必须移植自己的开源操作系统版本或创建自己的内核来运行代码。当Linux版本存在时,它们通常是错误的并且难以实现,因为在wiki上浪费了时间并且构建指令不一致或不充分。今天,MicroBlaze提供操作系统支持,包括freeRTOS和Linux。

它们带有可根据需要进行修改的真实示例项目 – 相对于过去有限的操作系统支持而言是一个相当大的进步。现在可以选择具有可靠确定性的高效实时操作系统或主线内核可接受的Linux环境,也可作为预构建的ram磁盘。令人惊讶的是,轻松地“敲定”Linux实现,将其连接到网络接口,并拥有一个简单的Web服务器。
xilinx_microblaze_figure2_updated.jpg

图2.运行实时操作系统’FreeRTOS’的MicroBlaze示例

一个好的架构必须能够实现新功能的引入,面向未来的设计,减少硬件平台迭代,并结合设计安全性。MicroBlaze是一个功能齐全的微处理器架构,包含这些和许多附加功能。这些功能包括虚拟内存管理,缓存一致性,流链接支持和浮点处理单元。

还应用了具有容错配置选项的高效应用程序因子分解的需求。这些相同的容错选项有助于为安全敏感的应用程序提供防篡改功能。两个或多个“并行”MicroBlaze核心无形锁定监视正在运行的处理器并检测单个事件扰乱或黑客攻击,使系统能够自我诊断并响应其他灾难性情况。
microblaze_figure3.jpg

图3. Lockstep MicroBlaze容错架构示例

软核实现

Xilinx的成本优化产品组合还有许多其他进展可帮助改进软核实现。高速SPI配置为驻留在具有多重启动功能的串行闪存中的程序代码提供了更快的启动选项,以支持多处理器应用程序。通过内置的安全更新功能,包括256位AES加密和HMAC / SHA-256身份验证,可实现动态的现场升级。

Xilinx通过部分重配置功能支持FPGA固件更新。这样可以通过下载部分位文件来动态修改FPGA上的逻辑,同时剩余的逻辑继续运行而不会中断。设计可以在不需要额外设备的情况下连续运行,而不是使用多个设备或要求FPGA脱机更新。

从历史上看,随着设计人员被迫在次标准环境中编写和调试代码,FPGA软核集成的好处在于增加了设计复杂性以及开发定制桥接逻辑,外设开发和持续低效的价格标签。MicroBlaze具有传统嵌入式微控制器中的所有外设,可轻松与软核集成。

基于Eclipse的工具链是一个全面,熟悉的环境,提供完整的混合级调试,并且还支持多处理器开发。软件设计人员可以在同一开发环境中在ARM或Microblaze编译和调试支持之间切换。创建自动板支持包可以访问Microblaze硬件架构的存储器映射,包括外设和I / O. 外围驱动程序中的BSP链接包括一个automake工具,使设计能够以最小的开销进行。

选择最佳FPGA平台,然后使用SDK打开三个预先配置的MicroBlaze架构之一,并按照快速入门指南 (PDF)中的说明进行操作。软件设计人员可以在大约五分钟内启动并运行“hello world”。这使工程师能够熟悉Microblaze并开始实施,而无需使用Vivado FPGA工具套件。如果需要更多专用定制,则可以使用Vivado的IP Integrator工具调整模板项目。该工具集成了连接和块自动化配置向导,并提供了一种添加附加IP,修改接口外设,总线连接和内存映射的简单方法。
Microblaze_figure_4.jpg

图4.使用Vivado IP Integrator工具快速添加外设

成本优化的FPGA产品组合

成本优化的FPGA Spartan-6,Spartan-7,Artix-7和Zynq-7000系列提供量身定制的特性和功能,以满足各种目标应用的需求。尽管它们都具有实现硬件算法和基于微处理器的控制系统的能力,但它们的差异反映了特定于目标应用的要求,这些要求仅通过通用逻辑以经济高效的方式获得是不切实际的。

Spartan-6和Spartan-7

Spartan-6和Spartan-7 FPGA平台适用于任意连接,桥接应用和传感器接口。话虽如此,它们仍然足以支持高性能算法,同时仍然提供当今最高的I / O连接平台。由于采用小型封装选项,它们可以实现缩小的四层PCB设计。

Spartan-7的性能降低了电源尺寸和成本,从而提高了成本和尺寸。许多内置系统级模块,包括DSP Slice,PLL,双12位1MHz ADC和系统监控磁贴,可将功能映射到FPGA中,从而进一步节省成本。其他功能包括高速DDR3接口功能和大量现成的IP模块,可连接到行业标准的AMBA AXI-4总线。汽车级版本可用于需要更高温度耐受性的应用,架构师可通过AES和Device DNA保护增强IP安全性来确保其设计。

xilinx_COP_layout_figure4.jpg

图5. Xilinx成本优化的产品组合概述

产品Artix-7

Artix-7适用于需要高速串行接口或信号处理繁重应用的设计。具有6.6Gbps功能的收发器是目前业界最快的收发器。此速度使PCI Express,DisplayPort,串行ATA,HDMI,USB3.0和具有UHD功能的SDI等接口可与MicroBlaze系统集成。

ZYNQ-7000

Zynq-7000是一款SoC,具有单核或双核ARM-Cortex-A9子系统,具有超过3000个与FPGA架构的高速互连,可实现高速算法加速。为了获得更高的速度,设计人员可以使用Zynq UltraScale + MPSoC双核和四核A53。Xilinx提供系统和以IP为中心的设计,在接口级集成即插即用IP,而不是IP构建模块的信号级。设计生态系统支持使用C / C ++进行高级综合,system-C open-CL通过Eclipse使软件开发人员更容易加速。

MicroBlaze集成

MicroBlaze集成到Xilinx的可配置逻辑分析仪Chipscope Pro软件中。这允许硬件接口,包括串行和并行总线,通用I / O和任何逻辑互连,可以直接逐周期捕获并跟踪微处理器操作。物理配置,编程和调试接口可用于将高级软件调试连接到MicroBlaze系统,以启用所需的所有熟悉的断点和步进设施。

Xilinx提供用于CPLD和FPGA开发套件的USB 2下载电缆以及JTAG电缆,可根据需要直接连接到设备本身。如果需要远程调试,则可以通过集线器连接到LAN,或通过独立供电的以太网连接到JTAG电缆。如果需要其他选项,或者需要与现有工具链兼容,则可以从第三方提供商处获得调试解决方案。

MicroBlaze既可作为主处理器,也可作为ARM子系统的协处理器,实现实时算法加速和关键功能隔离。通过硬件设计更改(包括添加更多MicroBlaze处理器)实现实时改进,新功能可靠地增加。升级可以通过高安全性实现,软件和FPGA逻辑映像可在不间断运行期间升级。低成本的集成ARM解决方案为FPGA提供了应用空间和物联网功能,可以根据实时算法支持的需要包含尽可能多的MicroBlaze协处理器。

Xilinx的OpenCL C-to-VHDL功能可实现软件设计的隐形在线硬件加速。将MicroBlaze与成本优化的产品组合相结合,可提供可扩展的面向未来的架构,该架构具有统一的工具链,该工具链使用全面的IP目录。

其他资源


基于FPGA软核MicroBlaze的嵌入式C编程经验及技巧小结

作者:宫易政 时间:2012年4月4日

引言:最近在完成“用MicroBlaze下的嵌入式C编写testbench实现对芯片功能验证”的过程中查阅了FPGA的EDK的相关知识、MicroBlaze的相关知识、嵌入式C的主要语法、编程技巧等,获得了很多知识,并成功应用到实验中,顺利完成了预期的任务。现将读书总结和任务经验列于下,目的一是将某些想法和技巧列于笔端,检验当前的掌握程度,二是不断总结之前的经验为以后的相关工作做准备,三是为他人的相关工作做“铺路人”。

一、MicroBlaze 体系结构

MicroBlaze 是基于Xilinx公司FPGA的微处理器IP核,和其它外设IP核一起,可以完成可编程系统芯片(SOPC)的设计。MicroBlaze 处理器采用RISC架构和哈佛结构的32位指令和数据总线,可以全速执行存储在片上存储器和外部存储器中的程序,并访问其的数据。
MicroBlaze内部有32个32位通用寄存器和2个32位特殊寄存器—PC指针和MSR状态标志寄存器。为了提高性能,MicroBlaze还具有指令和数据缓存。所有的指令字长都是32位,有3个操作数和2种寻址模式。指令按功能划分有逻辑运算、算术运算、分支、存储器读/写和特殊指令等。指令执行的流水线是并行流水线,它分为3级流水:取指、译码和执行。
MicroBlaze可以响应软件和硬件中断,进行异常处理,通过外加控制逻辑,可以扩展外部中断。利用微处理器调试模块(MDM)IP核,可通过JTAG接口来调试处理器系统。多个MicroBlaze处理器可以用1个MDM来完成多处理器调试。
MicroBlaze处理器具有8个输入和8个输出快速单一链路接口(FSL)。FSL通道是专用于单一方向的点到点的数据流传输接口。FLS和MicroBlaze的接口宽度是32位。每一个FSL通道都可以发送和接收控制或数据字。
在由电源、MicroBlaze以及FPGA构成的主板和内存所组成的最小系统下,我们就可以像在PC机上使用C语言一样进行编程,从而对硬件进行操作。硬件可以是系统内存,也可以是双端口RAM、 SRAM等。只要该外设与最小系统的总线相连,那么我们就可以通过指针的方式来完成各种操作,这也是为何只有高级语言C语言才可以用来编写嵌入式程序。

二、嵌入式系统内存布局

由C语言代码形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段。编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,连接过程则将各个源文件生成的二进制机器代码文件组合成一个文件。C语言编写的程序经过编译-连接后,将形成一个统一文件,它由几部分组成。在程序运行时又会产生其他几个部分,各个部分代表了不同的存储区域。
这些区域包括代码段(Code)、只读数据段(RO DATA)、已初始化读写数据段(RW DATA)、未初始化数据段(BSS)、堆(heap)、栈(stack)。
其中Code、RO DATA、RW DATA、BSS属于静态存储区,这类内存直到程序运行完成才进行释放,例如我们经常使用的关键字static、const修饰的变量,全局变量,在程序开始的变量初始化以及整个代码指令;heap和stack属于动态内存,在程序运行过程中动态分配和释放。栈内存由编译器进行控制,例如对于函数传递的参数或在函数内部定义的自动局部变量,都存储在栈内存中,当退出函数后栈会被清空。堆内存的分配和释放通过调用库函数(#include<stdlib>)完成,其中最常用的函数为malloc、calloc、realloc以及free函数,我们通过以上函数的调用来完成堆内存的分配和释放。</stdlib>

三、嵌入式C的主要任务

与PC系统的软件设计相比,嵌入式系统的C编程更重视对硬件的操作以及字节的位操作。

3.1 硬件操作

嵌入式系统的内存包括真正的内存、内部寄存器以及外部部件的地址映射等部分。无论上述哪种内存,一般都将映射到处理器的内存空间中。从编程的角度来看,嵌入式系统和PC系统的软件设计的一个重要的区别即在于嵌入式系统可以更重视对硬件的操作。而对于硬件的操作需要通过操作内部寄存器和外围部件内存映射的地址实现,其实现方式都是对内存的读、写操作。
不论是哪种地址,在内存中都是以32位的形式在内存中进行存储,基于这种观点我们不难理解通过指针进行的各种操作。
我们可以让指针指向一个变量,或者一段内存空间:

int a;
int *p = &a;

或者

void *p = malloc(1024);

上述操作主要用于系统内存的操作,例如初始化变量(静态内存)或申请堆内存时采用。
我们也可以定义指针为确定的整数(int或unsigned long型)值,例如我们可以定义指针变量p为0x826300ff:
void *p = (void *)0x826300ff;
这种方式对于硬件的操作是最常用的,通常我们会通过宏命令定义我们操作的硬件的总线地址,然后通过指针赋初值和定义指针类型来完成之后的读写操作。
例如我们可以定义p为指向32位整数的指针,那么就可以通过强制内存转换的方式:
p = (int *)p;
对内存的读写我们直接通过赋值语句即可,编译器和系统会帮我们寻址和相关硬件操作。我们一般采用宏定义的方式:
#define write32b(addr,data) *( (volatile unsigned long *)(addr)) = (unsigned long)data
通过上述代码,我们完成了32位数据的写操作,需要的注意的是采用宏定义方式而不是函数的方式主要是为了减少参数压栈出栈所消耗的时间,这个后面会进一步进行说明。另外需要注意的是使用了关键字volatile,是为了告诉编译器地址addr的数据可能会被意想不到地改变,在这种情况下,编译器就不会去假设这个变量的值,即优化器会在用到这个变量时必须每次都重新读取它的值。volatile在嵌入式系统中普遍用于可能具有并行操作性质的数据,这些变量可能是被外部改变或者内部并行的程序改变,尤其是对于硬件的操作。

3.2 位操作

除了硬件操作外,嵌入式C最主要的操作就是位操作。在嵌入式系统的编程中,位操作比其他运算更常用。这是由于在嵌入式系统中涉及了更多有关硬件寄存器的操作。我们经常会遇到对制定位进行判断或者改变指定位的操作。
对某几位进行判断
判断无规律的某几位,例如第31位,第27位:
通过x&0x88000000,或者x|~0x88000000来得到x第31位和第27位的数据,进行下一步的判断。
另外更常用的是获取一个32位无符号整数的m位到第n位的值,我们通过以下宏完成:
#define BITS(value32u,m,n) ((unsigned int)(value32u<<(31-(n)) >> ((31-(n)+(m)))
改变指定位
例如对单个位的置0和置1操作:

#define SETBIT(x,n) x = x | (1<<n)
#define CLRBIT(x,n) x = x & ~(1<<n)

多位的操作可以转化为多个单个位的操作。
四、嵌入式程序的优化
嵌入式系统与PC系统相比,内存空间小,主频低,因此嵌入式系统对程序性能是非常敏感的,有以下几个方面的开销:首先是程序各段执行的效率,这是程序开销的主要方面;其次是函数的参数和返回值传递中入栈和出栈的时间。因此在编程的过程中有以下技巧可以对程序进行优化:
使用宏定义常用的函数
由于函数入栈出栈消耗额外的时间,利用宏定义可以将这类时间去除,而且不用申请相应的栈空间,上面介绍的多种宏定义函数都是出于这样的考虑。
优化运行频率高的程序
对于一些运行效率较高的程序,某些命令实际上并不是每次运行都有效用,那么我们就可以通过技巧将这些无用的命令去掉,缩短整体运行时间,提高运行效率。如下例:
for(i= 0;i<get_count():i++)
对于上面代码的get_count(),每循环一次都要运行一次,但是实际上不需要,如果写成:

int k = ger_count();
for(i= 0;i<k:i++)

以上代码段将判断语句的部分操作移到循环外部,通过临时变量来代替函数调用,这样在循环次数较多的情况下,减少大量不必要的函数调用。
自定义函数内部操作优化
函数传递尽量以指针变量为主,在函数内部少申请栈空间。例如:

struct s100{ char cc[100];};
int fs(struct s100 a);

当使用函数fs时,就需要将规模为100字节的结构体全部保存其中。编译器将会生成相关的代码,调用fs函数的时候,将首先在栈上按照结构体s100的大小开辟100字节的空间;然后将传奇给参数的结构体struct中的值全部复制到栈上的空间内,再进行操作。显而易见这种操作既耗内存效率也低。如果采用指针传递参数,那么我们就会在内存和效率方面都会得到显著地提高:
int fs(struct s100 *a);
在调用fs时,只需要在栈上保存一个指针即可,同样可以达到对相应内存的操作,若不希望改变传递参数的内容,那么可以通过以下操作:
int fs(const struct s100 *a);
小数操作
在嵌入式系统中,浮点数的操作对资源的开销是很大的,对于某些特殊的小数我们可以通过定点数来表示,例如我们可以用定点数0x0005.2c来表示5.171875,在计算的过程中我们用整数来代替小数,计算完成后再转化为小数。例如要求sum = 0.326*a+0.413*b;那么我们可以先求sum=326*a+413*b,然后sum = sum/1000,这样在计算过程中就取消了浮点数的使用,大大提高了操作效率。
其他技巧
利用脑力替CPU完成某部分操作,例如查表法:在一个4位的二进制数中,确定有几位为1,如果按照经典的一般的思路就是使用循环的方法让程序在这个4位的数中依次查找各个位是否为1,最后累加得出1的数目。如果采用穷举的列表法就可以大大提高速度:

const int table[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
int getnumber (unsigned int a)
{
Return table[a&0xf];
}

如上,我们就可以利用数组来得到结果。
总之,只要我们知道嵌入式系统的操作规律,熟悉了嵌入式系统的特点,并且善于发动自己的智慧,那么我们就会很容易的对嵌入式C程序进行有效的优化。

在Xilinx MicroBlaze上移植freeRTOS

在Spartan-6 FPGA上演示, 使用Xilinx ISE设计套件(嵌入式版)移植freeRTOS
Xilinx-Spartan-6-SP605-development-board.jpg

以下为机译,原文《Xilinx MicroBlaze Port——Demonstrated on a Spartan-6 FPGA, using the Xilinx ISE Design Suite (Embedded Edition)》

此MicroBlaze端口使用Xilinx ISE设计套件(嵌入式版)的 13.1 版生产,支持MicroBlaze软核处理器核的 8.10版,并在基于Spartan-6 FPGA的SP605评估套件上开发和测试 。它代表了一个主要的FreeRTOS端口升级,并取代了在Virtex-4 FPGA上开发的 预先存在的旧端口。

该演示包括使用lwIP TCP / IP堆栈 1.4.0版的嵌入式Web服务器实现。Web服务器的服务器端包含(SSI)功能用于提供包含动态任务和运行时统计信息的页面。

在Xilinx SDK环境中有两种使用FreeRTOS的方法:

使用独立的BSP
独立板支持包(BSP)是由SDK生成的库,专用于硬件设计(FPGA配置)。它包含MicroBlaze软处理器本身的软件驱动程序以及设计中包含的所有外设,但它不支持FreeRTOS。通过构建FreeRTOS源文件作为引用BSP库的应用程序的一部分,FreeRTOS可以与独立的BSP一起使用。本页描述的演示应用程序就是这样做的。

使用FreeRTOS BSP
FreeRTOS BSP扩展了上述独立的BSP,还包括FreeRTOS源文件。FreeRTOS可以与FreeRTOS BSP一起使用,而不必将FreeRTOS源文件作为引用BSP库的应用程序的一部分。本页描述的演示应用程序不使用FreeRTOS BSP,但提供 了一个单独的文档页面,描述了如何生成和使用FreeRTOS BSP,以及SDK如何自动生成完整(但简单)的FreeRTOS示例应用程序使用FreeRTOS BSP库。

Creating-FreeRTOS-BSP-packages-and-applications-in-the-Xilinx-SDK.jpg

使用Xilinx SDK创建使用FreeRTOS BSP的Hello World样式FreeRTOS应用程序

最后,FreeRTOS Eclipse内核感知调试器插件 可与Xilinx SDK一起使用,以协助调试FreeRTOS应用程序。
FreeRTOS-kernel-aware-debugger-plug-in-viewed-in-the-Xilinx-SDK.jpg

在Xilinx SDK中查看FreeRTOS内核感知调试器插件


重要!使用MicroBlaze软核处理器核心RTOS端口的注意事项
在使用此RTOS端口之前,请阅读以下所有要点。

  • 源代码组织
  • 准备项目目录
  • 演示应用程序
  • 功能
  • 硬件设置
  • 网络设置
  • 将演示应用程序导入SDK
  • 构建演示应用程序
  • 从SDK工具运行演示应用程序
  • 预期的行为
  • 配置和使用细节
  • 需要由应用程序提供的回调函数
  • 实现中断服务例程(ISR)
  • 从ISR切换上下文
  • 安装和启用ISR
  • 异常处理(仅限高级用户)
  • RTOS端口特定配置
  • 内存分配
  • 创建和使用FreeRTOS BSP(指向单独页面的链接)
  • 使SDK可以识别FreeRTOS
  • 使用SDK创建FreeRTOS应用程序
  • 创建FreeRTOS BSP以用于任何应用程序
    另请参阅常见问题解答我的应用程序未运行,可能出现什么问题?

源代码组织

FreeRTOS下载包含所有FreeRTOS端口和每个演示应用程序的源代码。这意味着它包含的文件比使用MicroBlaze端口或官方MicroBlaze演示应用程序所需的文件多得多。有关 下载文件的说明以及有关创建新项目的信息,请参阅本网站的“ 源代码组织”部分。
下面显示并描述了演示应用程序使用的目录结构。根MicroBlaze_Spartan-6_EthernetLite目录本身位于FreeRTOS / Demo中。

MicroBlaze_Spartan-6_EthernetLite
    |
    + -KernelAwareBSPRepository    用于将FreeRTOS集成到SDK中的文件存储库
    |
    + -PlatformStudioProject       用于创建硬件比特流的XPS项目
    |
    + -SDKProjects                 各种SDK项目
        |
        + -RTOSDemo                    演示应用程序项目本身
        |
        + -StandAloneBSP               BSP库代码
        |
        + -HardwareWithEthernetLite    硬件项目

与目录结构有关的注释:
用于构建演示应用程序的SDK项目存储在 SDKProjects / RTOSDemo目录中。这是唯一需要显式构建以生成演示项目可执行文件的项目。另外两个SDK项目(BSP库和硬件项目)是RTOSDemo项目的依赖项,因此在需要时自动构建。
StandAloneBSP库项目由SDK专门为硬件配置创建。由于它是一个独立的库,它不包含FreeRTOS源文件,而FreeRTOS源文件则包含在RTOSDemo应用程序中。 提供了一个单独的网页 ,描述了FreeRTOS BSP的使用,它包含了FreeRTOS源文件,因此无需将FreeRTOS文件直接包含在正在构建的应用程序中。
除非您特别想要更改硬件配置,否则不需要打开或修改PlatformStudioProject目录中 包含的XPS(硬件)项目。RTOSDemo SDK(软件)项目依赖于从硬件项目导出的文件,但导出过程已经完成,导出的文件已存储在 SDKProjects / HardwareWithEthernetLite目录中。

准备Xilinx软件开发工具包(SDK)项目目录

Eclipse项目可以是标准makefile项目,也可以是托管make项目。演示应用程序中提供的项目是托管make项目。这反过来意味着:
构建项目所需的所有源文件必须位于包含项目文件本身的文件夹/目录下,或者
需要配置Eclipse工作区(注释工作区,而不是项目)以在硬盘上的其他位置找到文件。
在这种情况下使用选项1。为此,目录FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / SDKProjects / RTOSDemo 包含一个名为CreateProjectDirectoryStructure.bat的批处理文件,该文件将所有必需的FreeRTOS源文件复制到演示项目目录中的子目录中。批处理文件适用于Windows主机。Linux用户需要创建等效的脚本文件,或检查提供的批处理文件,然后手动执行相同的复制操作。 必须在将SDK项目导入Eclipse工作区之前执行CreateProjectDirectoryStructure.bat。

MicroBlaze演示应用程序
功能
SDK项目包含两个构建配置,一个名为Blinky,它创建一个非常简单的入门示例,另一个名为Full,它创建了一个全面的示例:

构建配置 描述
Blinky范例 这是一个非常简单的入门示例。它创建了两个任务,一个是软件计时器,还使用了一个按钮中断。这两个任务通过队列进行通信 – 队列发送任务和队列接收任务。每次收到值时,队列接收任务都会切换LED。按任何用户按钮(SW4,SW5,SW7或SW8)将产生中断,中断的服务程序会在打开LED之前重置软件定时器。软件定时器具有五秒的周期,当五秒钟到期时,软件定时器回调功能再次关闭LED。因此,按下按钮将打开LED指示灯,LED将保持亮起,直到整整五秒钟没有再次按下按钮。Blinky构建配置使用 main-blinky.c源文件。
Full范例 这是一个全面的演示,可以创建大量任务,队列,信号量(各种类型)和软件定时器。它还包括嵌入式Web服务器。完整构建配置从标准演示 任务集创建了许多 任务。标准演示任务不执行任何特定功能。他们的目的首先是测试FreeRTOS端口,其次是提供如何使用FreeRTOS API函数的示例。完整版本配置创建的其他任务包括: 注册检查任务——这两个任务通过首先用已知且唯一的值填充每个MicroBlaze寄存器来测试RTOS内核上下文切换机制,然后在任务的生命周期内重复检查最初写入寄存器的值是否保留在寄存器中。任务以尽可能低的优先级(空闲优先级)执行,因此经常被抢占。这些任务的性质要求它们是用汇编语言编写的。“检查”软件计时器和回调——Check计时器是一个非常简单的看门狗类型计时器的示例。它监控所有其他标准演示任务和寄存器检查任务,并使用LED提供有关系统状态的可视反馈。检查计时器的周期最初设置为五秒。检查计时器回调函数检查所有标准演示任务和寄存器检查任务不仅仍在执行,而是在不报告任何错误的情况下执行,然后切换LED。如果检查计时器发现某个任务已停顿或报告错误,则它会将自己的周期从最初的五秒更改为仅200毫秒。因此,如果LED每五秒切换一次,则没有发现任何问题,而如果LED每200ms切换一次,则至少在一项任务中发现了一个问题。上次报告的问题被锁存到pcStatusMessage变量中。lwIP任务——lwIP任务执行lwIP TCP / IP堆栈,并执行嵌入式Web服务器。本页的网络设置部分介绍了使用嵌入式Web服务器所需的网络配置。嵌入式Web服务器提供的页面在本页的预期行为部分中进行了描述 。

Xilinx MicroBlaze端口
在Spartan-6 FPGA上演示,
使用Xilinx ISE设计套件(嵌入式版)

Xilinx Spartan 6 SP605开发板
此页面上记录的演示已被弃用,因为它已被使用以后硬件和工具版本的演示所取代。

此MicroBlaze端口使用Xilinx ISE设计套件(嵌入式版)的 13.1 版生产,支持MicroBlaze软核处理器核的 8.10版,并在基于Spartan-6 FPGA的SP605评估套件上开发和测试 。它代表了一个主要的FreeRTOS端口升级,并取代了在Virtex-4 FPGA上开发的 预先存在的旧端口。

该演示包括使用lwIP TCP / IP堆栈 1.4.0版的嵌入式Web服务器实现。Web服务器的服务器端包含(SSI)功能用于提供包含动态任务和运行时统计信息的页面。

在Xilinx SDK环境中有两种使用FreeRTOS的方法:

使用独立的BSP
独立板支持包(BSP)是由SDK生成的库,专用于硬件设计(FPGA配置)。它包含MicroBlaze软处理器本身的软件驱动程序以及设计中包含的所有外设,但它不支持FreeRTOS。通过构建FreeRTOS源文件作为引用BSP库的应用程序的一部分,FreeRTOS可以与独立的BSP一起使用。本页描述的演示应用程序就是这样做的。

使用FreeRTOS BSP
FreeRTOS BSP扩展了上述独立的BSP,还包括FreeRTOS源文件。FreeRTOS可以与FreeRTOS BSP一起使用,而不必将FreeRTOS源文件作为引用BSP库的应用程序的一部分。本页描述的演示应用程序不使用FreeRTOS BSP,但提供 了一个单独的文档页面,描述了如何生成和使用FreeRTOS BSP,以及SDK如何自动生成完整(但简单)的FreeRTOS示例应用程序使用FreeRTOS BSP库。

在Xilinx SDK中创建FreeRTOS BSP包和应用程序
使用Xilinx SDK创建使用FreeRTOS BSP的Hello World样式FreeRTOS应用程序

最后,FreeRTOS Eclipse内核感知调试器插件 可与Xilinx SDK一起使用,以协助调试FreeRTOS应用程序。

FreeRTOS Eclipse RTOS内核感知调试器插件
在Xilinx SDK中查看FreeRTOS内核感知调试器插件
重要!使用MicroBlaze软核处理器核心RTOS端口的注意事项
在使用此RTOS端口之前,请阅读以下所有要点。
源代码组织
准备项目目录
演示应用程序
功能
硬件设置
网络设置
将演示应用程序导入SDK
构建演示应用程序
从SDK工具运行演示应用程序
预期的行为
配置和使用细节
需要由应用程序提供的回调函数
实现中断服务例程(ISR)
从ISR切换上下文
安装和启用ISR
异常处理(仅限高级用户)
RTOS端口特定配置
内存分配
创建和使用FreeRTOS BSP(指向单独页面的链接)
使SDK可以识别FreeRTOS
使用SDK创建FreeRTOS应用程序
创建FreeRTOS BSP以用于任何应用程序
另请参阅常见问题解答我的应用程序未运行,可能出现什么问题?
源代码组织
FreeRTOS下载包含所有FreeRTOS端口和每个演示应用程序的源代码。这意味着它包含的文件比使用MicroBlaze端口或官方MicroBlaze演示应用程序所需的文件多得多。有关 下载文件的说明以及有关创建新项目的信息,请参阅本网站的“ 源代码组织”部分。
下面显示并描述了演示应用程序使用的目录结构。根MicroBlaze_Spartan-6_EthernetLite目录本身位于FreeRTOS / Demo中。

MicroBlaze_Spartan-6_EthernetLite
|

+ -KernelAwareBSPRepository    用于将FreeRTOS集成到SDK中的文件存储库
|
+ -PlatformStudioProject       用于创建硬件比特流的XPS项目
|
+ -SDKProjects                 各种SDK项目
    |
    + -RTOSDemo                    演示应用程序项目本身
    |
    + -StandAloneBSP               BSP库代码
    |
    + -HardwareWithEthernetLite    硬件项目

与目录结构有关的注释:
用于构建演示应用程序的SDK项目存储在 SDKProjects / RTOSDemo目录中。这是唯一需要显式构建以生成演示项目可执行文件的项目。另外两个SDK项目(BSP库和硬件项目)是RTOSDemo项目的依赖项,因此在需要时自动构建。
StandAloneBSP库项目由SDK专门为硬件配置创建。由于它是一个独立的库,它不包含FreeRTOS源文件,而FreeRTOS源文件则包含在RTOSDemo应用程序中。 提供了一个单独的网页 ,描述了FreeRTOS BSP的使用,它包含了FreeRTOS源文件,因此无需将FreeRTOS文件直接包含在正在构建的应用程序中。
除非您特别想要更改硬件配置,否则不需要打开或修改PlatformStudioProject目录中 包含的XPS(硬件)项目。RTOSDemo SDK(软件)项目依赖于从硬件项目导出的文件,但导出过程已经完成,导出的文件已存储在 SDKProjects / HardwareWithEthernetLite目录中。

准备Xilinx软件开发工具包(SDK)项目目录
Eclipse项目可以是标准makefile项目,也可以是托管make项目。演示应用程序中提供的项目是托管make项目。这反过来意味着:
构建项目所需的所有源文件必须位于包含项目文件本身的文件夹/目录下,或者
需要配置Eclipse工作区(注释工作区,而不是项目)以在硬盘上的其他位置找到文件。
在这种情况下使用选项1。为此,目录FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / SDKProjects / RTOSDemo 包含一个名为CreateProjectDirectoryStructure.bat的批处理文件,该文件将所有必需的FreeRTOS源文件复制到演示项目目录中的子目录中。批处理文件适用于Windows主机。Linux用户需要创建等效的脚本文件,或检查提供的批处理文件,然后手动执行相同的复制操作。 必须在将SDK项目导入Eclipse工作区之前执行CreateProjectDirectoryStructure.bat。

MicroBlaze演示应用程序
功能
SDK项目包含两个构建配置,一个名为Blinky,它创建一个非常简单的入门示例,另一个名为Full,它创建了一个全面的示例:
构建配置 描述
的Blinky 这是一个非常简单的入门示例。它创建了两个任务,一个是软件计时器,还使用了一个按钮中断。
这两个任务通过队列进行通信 – 队列发送任务和队列接收任务。每次收到值时,队列接收任务都会切换LED。

按任何用户按钮(SW4,SW5,SW7或SW8)将产生中断,中断的服务程序会在打开LED之前重置软件定时器。软件定时器具有五秒的周期,当五秒钟到期时,软件定时器回调功能再次关闭LED。因此,按下按钮将打开LED指示灯,LED将保持亮起,直到整整五秒钟没有再次按下按钮。

Blinky构建配置使用 main-blinky.c源文件。

充分 这是一个全面的演示,可以创建大量任务,队列,信号量(各种类型)和软件定时器。它还包括嵌入式Web服务器。
完整构建配置从标准演示 任务集创建了许多 任务。标准演示任务不执行任何特定功能。他们的目的首先是测试FreeRTOS端口,其次是提供如何使用FreeRTOS API函数的示例。

完整版本配置创建的其他任务包括:

注册检查任务
这两个任务通过首先用已知且唯一的值填充每个MicroBlaze寄存器来测试RTOS内核上下文切换机制,然后在任务的生命周期内重复检查最初写入寄存器的值是否保留在寄存器中。任务以尽可能低的优先级(空闲优先级)执行,因此经常被抢占。这些任务的性质要求它们是用汇编语言编写的。

“检查”软件计时器和回调
Check计时器是一个非常简单的看门狗类型计时器的示例。它监控所有其他标准演示任务和寄存器检查任务,并使用LED提供有关系统状态的可视反馈。

检查计时器的周期最初设置为五秒。检查计时器回调函数检查所有标准演示任务和寄存器检查任务不仅仍在执行,而是在不报告任何错误的情况下执行,然后切换LED。

如果检查计时器发现某个任务已停顿或报告错误,则它会将自己的周期从最初的五秒更改为仅200毫秒。因此,如果LED每五秒切换一次,则没有发现任何问题,而如果LED每200ms切换一次,则至少在一项任务中发现了一个问题。上次报告的问题被锁存到pcStatusMessage变量中。

lwIP任务
lwIP任务执行lwIP TCP / IP堆栈,并执行嵌入式Web服务器。本页的网络设置部分介绍了使用嵌入式Web服务器所需的网络配置。嵌入式Web服务器提供的页面在本页的预期行为部分中进行了描述 。

硬件设置
演示应用程序包括通过UART发送和接收字符的任务。一个任务发送的字符必须由另一个任务接收。如果任何字符丢失或无序接收,则会标记错误条件。
有两种常见的方法可以确保每个传输的角色也被接收。第一种是使用环回连接器将发送引脚连接到接收引脚。第二种是将UART连接到echo服务器。SP605硬件使用UART转USB转换器,无需安装环回连接器。因此,在这种情况下,UART必须连接到外部回显服务器。在开发过程中,免费(Windows)Comm Echo实用程序用于此目的。Comm Echo可以从http://www.serialporttool.com/CommEcho.htm 下载。

以下部分介绍了所需的网络设置。

演示应用程序使用内置于SP605硬件上的LED和按钮,因此无需进一步的硬件设置。

网络设置
分配给SP605硬件的IP地址由常量configIP_ADDR0设置为configIP_ADDR3。这些在FreeRTOSConfig.h头文件的底部指定(位于FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / SDKProjects / RTOSDemo目录中)定义MAC地址的常量和NET掩码位于同一文件的同一位置。
Web浏览器和SP605硬件使用的IP地址必须兼容。这可以通过使两个IP地址的前三个八位字节相同来确保。例如,如果Web浏览器计算机使用IP地址192.168.0.1,则可以为SP605开发板提供192.168.0.2到192.168.0.254范围内的任何地址(除了同一网络上已存在的任何地址)。

分配给SP605的MAC地址在其所连接的网络上必须是唯一的。

将演示应用程序项目导入SDK Eclipse工作区

要将Xilinx软件开发工具包(SDK)项目导入现有或新的Eclipse工作区:

  1. 从SDK“文件”菜单中选择“导入”。将出现如下所示的对话框。选择General-> Existing Project into Workspace,如图所示。
    Importing-the-Xilinx-MicroBlaze-RTOS-demo-project-into-the-SDK.jpg
    首次单击“导入”时出现的对话框
  2. 在下一个对话框中,选择FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / SDKProjects 作为根目录。然后,确保在“项目”区域中检查RTOSDemo,StandAloneBSP和HardwareWithEthernetLite项目,并且在单击“完成”按钮之前未选中“将项目复制到工作区”框(请参阅下图中的正确复选框状态)。
    Selecting-the-RTOS-Demo-Source-project-during-the-SDK-import-process.jpg
    确保选中了RTOSDemo,并且未选中“将项目复制到工作区”
  3. 导入所有三个项目后,SDK IDE的项目浏览器窗口将如下所示。
    请记住,只需要显式构建RTOSDemo项目,并且FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / PlatformStudioProject目录中也提供了用于生成硬件项目的XPS项目 。
    The-RTOSDemo-and-two-dependent-projects-viewed-in-the-project-explorer-window.jpg

所有三个项目都导入到工作区中

构建演示应用程序

  1. 确保已执行CreateProjectDirectoryStructure.bat,并且项目已正确导入Eclipse工作区。
  2. 选择所需的构建配置。要选择活动的构建配置(实际构建的构建配置),首先右键单击SDK IDE的Project Explorer窗口中的RTOSDemo项目名称,然后选择所需的弹出菜单项,如下图所示。
    selecting-a-build-configuration-in-the-Xilinx-sdk-ide.jpg

使用Xilinx SDK IDE中的弹出菜单选择活动的构建配置
注意: 两个构建配置各自包含和排除各自构建中的不同文件。例如,完整版本配置构建main-full.c,而Blinky构建配置则构建main-blinky.c。Eclipse Project Explorer窗口应显示一个带有十字标记的图标,以指示哪些文件从活动的构建配置中排除。但是 – 此特定功能似乎无法正常工作。更改构建配置将确保构建正确的文件,并排除正确的文件,但Project Explorer窗口不一定会正确更新其图标。

  1. 从IDE“项目”菜单中选择“全部重建”。应用程序应该构建没有任何错误或警告。StandAloneBSP项目也将构建,因为它是RTOSDemo项目的依赖项。

使用SDK工具运行演示应用程序

  1. 确保SP605硬件已上电,并且其JTAG端口已连接到主机。
  2. 在下载软件项目之前,需要使用SDK硬件项目中的比特流对Spartan-6 FPGA进行编程。要将比特流编程到FPGA中,首先从SDK IDE的“Xilinx Tools”菜单中选择“Program FPGA”,然后在Program FPGA对话框中选择SDKProjects / HardwareWithEthernetLite 目录中的.bit和.bmm文件。如下图所示。
    Programming-the-bitstream-into-the-Spartan-6-FPGA.jpg
    用于编程FPGA的对话
  3. 完成FPGA编程后,从IDE的“运行”菜单中选择“调试配置…”。
  4. 在出现的对话框中,在左侧的目标树中突出显示“Xilinx C / C ++ ELF”,然后单击“新启动配置”速度按钮。速度按钮由下图中的红色方框突出显示。
  5. 将创建一个新的调试配置,该配置已经过命名以匹配正在使用的构建配置。自动生成的名称由下图中的黄色矩形突出显示。
  6. 确保使用正确的应用程序文件 – Blinky / RTOSDemo.elf用于Blinky构建配置,Full / RTOSDemo.elf用于完整构建配置。应用程序文件条目由下图中的绿色矩形突出显示。
  7. 单击“调试”按钮开始调试。
    Creating-an-Eclipse-debug-build-configuration-in-the-Xilinx-SDK-IDE.jpg

创建调试配置
Blinky和Full构建配置需要单独的调试配置,每次启动新的调试会话时都必须小心选择正确的调试配置。

预期的行为

完整版本配置的行为如下:

标有DS4,DS5和DS6的LED处于标准演示’闪存’任务的控制之下。每个都将以固定频率切换,LED DS6使用最快频率,LED DS4使用最慢频率。
标有DS3的LED处于“检查”软件定时器的控制之下。如果没有报告错误,DS3将每5秒切换一次,如果标准演示或注册检查任务报告错误,则每隔200ms切换一次。可以通过关闭通信回送服务器或拔出UART电缆来测试此机制,从而故意导致通信测试任务失败。
嵌入式Web服务器行为将在下一节中介绍。

Blinky构建配置的行为如下:

标记为DS6的LED处于队列接收任务的控制之下。每次队列接收任务收到一个值(每200ms)时,它将切换。
当按下任何用户按钮SW4,SW5,SW8或SW9时(假设它尚未打开),标记为DS5的LED将亮起。最后一次按下其中一个按钮五秒后,LED软件定时器将再次关闭LED DS5。

使用Web服务器

每个提供的页面的顶部包括一个菜单,其中包含指向其他页面的链接。
在连接的计算机上打开Web浏览器。
在浏览器地址栏中键入“HTTP://”,然后输入目标IP地址。
enterurl.gif

在Web浏览器中输入IP地址
(显然使用系统的正确IP地址)

提供的网页
task-stats-page-served-by-the-lwIP-embedded-web-server-on-the-Spartan-6-FPGA.jpg

服务任务统计页面 – 显示
系统中运行的每个任务的状态 – 包括
任务堆栈高水位线
task-run-time-stats-page-served-by-the-lwIP-embedded-web-server-on-the-Xilinx-SP605.jpg

服务的运行时统计信息页面 – 显示
每个任务消耗的CPU时间

第三个页面显示了一个大的JPG图像。

FreeRTOS内核配置和使用细节

需要由应用程序提供的回调函数

void vApplicationSetupTimerInterrupt(void);
这是一个应用程序定义的回调函数,用于安装tick中断处理程序。它作为应用程序回调提供,而不是RTOS内核端口层的组成部分,因为RTOS内核将运行在许多不同的MicroBlaze和FPGA配置上 – 并非所有配置都具有定义或可用的相同定时器外设。

vApplicationSetupTimerInterrupt()必须将RTOS内核定义函数vPortTickISR()安装为tick中断处理程序。

官方演示应用程序包括main-full.c和main-blinky.c中的vApplicationSetupTimerInterrupt()的示例实现。示例实现使用AXI定时器0作为节拍中断源。如果硬件平台上有AXI Timer 0外设,则可以不加修改地使用示例实现。

void vApplicationClearTimerInterrupt(void);
这是一个应用程序定义的回调函数,用于清除vApplicationSetupTimerInterrupt()回调函数安装的任何中断。它作为应用程序回调提供,因为RTOS内核将在许多不同的MicroBlaze和FPGA配置上运行 – 并非所有配置都具有定义或可用的相同定时器外设。

官方演示应用程序包括main-full.c和main-blinky.c中的vApplicationClearTimerInterrupt()的示例实现。该示例实现通过清除AXI定时器0外设产生的中断来补充在相同文件中找到的vApplicationSetupTimerInterrupt()的示例实现。如果您的应用程序未修改vApplicationSetupTimerInterrupt()提供的示例实现,则还可以使用提供的vApplicationClearTimerInterrupt()的示例实现而无需任何修改。

实现中断服务例程(ISR)

实现ISR的函数是普通的C函数,但必须符合以下原型。
void ISRFunctionName(void * ISRParameter);

从ISR切换上下文

ISR通常会导致任务离开阻止状态。例如,考虑任务处理到达队列的数据的情况。当队列为空时,没有要处理的数据,并且任务可能选择进入阻止状态以等待更多数据变为可用。如果ISR随后将数据发送到队列,则任务将自动离开阻塞状态,因为队列将不再为空。
如果ISR导致任务离开阻塞状态,并且离开阻塞状态的任务的优先级高于或等于当前正在执行的任务(被中断的任务),则应执行上下文切换。 ISR确保ISR直接返回到新的未阻止的,更高优先级的任务。ISR将中断一项任务,但又返回另一项任务。

宏port_IELD_FROM_ISR()是taskYIELD()的中断安全版本。它需要一个参数,如果没有零,将间接导致上下文切换发生。下面是portYIELD_FROM_ISR()的示例用法,它取自官方演示应用程序中的serial.c文件:

/ *请注意,此函数是从UART中断处理程序调用的,而不是
本身就是一个中断处理程序,因此它的原型不必与之匹配
所有中断处理程序都需要。* /
static void prvRxHandler(void * pvUnused,UBaseType_t uxByteCount)
{
签名char cRxedChar;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    / *虽然有要处理的字符。* /
    while(XUartLite_IsReceiveEmpty(xUartLiteInstance.RegBaseAddress)== pdFALSE)
    {
        / *获取下一个字符。* /
        cRxedChar = XUartLite_ReadReg(xUartLiteInstance.RegBaseAddress,
                                       XUL_RX_FIFO_OFFSET);

        / *将收到的字符放在收到的队列中。如果写信给
        queue导致任务离开Blocked状态,并且任务有一个
        然后,优先级等于或高于被中断任务的优先级
        xHigherPriorityTaskWoken将自动设置为内部的pdTRUE
        xQueueSendFromISR()函数本身。* /
        xQueueSendFromISR(xRxedChars,&cRxedChar,&xHigherPriorityTaskWoken);
    }

    / *调用portYIELD_FROM_ISR(),传入xHigherPriorityTaskWoken。如果
    xHigherPriorityTaskWoken在xQueueSendFromISR()内设置为pdTRUE,然后
    在这里调用portYIELD_FROM_ISR()将导致ISR
    直接返回新解锁的任务。如果是xHigherPriorityTaskWoken
    保留了pdFALSE的初始值,然后调用
    portYIELD_FROM_ISR()这里没有任何效果。* /
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

安装和启用ISR

提供以下功能分别用于安装,启用和禁用中断(在中断控制器中)。不得使用具有类似功能的Xilinx BSP库函数。
vApplicationSetupTimerInterrupt()的实现中包含了如何使用这些函数的示例,该实现包含在main-full.c和main-blinky.c中。另一个例子包含在main-blinky.c中的prvSetupHardware()的实现中。

 

异常处理(仅限高级用户)

要启用FreeRTOS异常处理,首先必须将MicroBlaze本身配置为包含异常处理功能,并且必须在FreeRTOSConfig.h 中将第二个 configINSTALL_EXCEPTION_HANDLERS设置为1。将configINSTALL_EXCEPTION_HANDLERS设置为1将导致RTOS内核消耗的代码和数据空间都增加。
提供以下函数来安装FreeRTOS异常处理程序,并在发生异常时分别处理异常。FreeRTOS异常处理程序本身的功能在portmacro.h中的函数原型上面的注释中描述,并在下面复制。

main-full.c和main-blinky.c中都提供了vApplicationExceptionRegisterDump()的示例实现。

/ *
 * vPortExceptionsInstallHandlers()仅在MicroBlaze时可用
 *配置为包含异常功能,和
 * FreeRTOSConfig.h中的configINSTALL_EXCEPTION_HANDLERS设置为1。
 *
 * vPortExceptionsInstallHandlers()安装FreeRTOS异常处理程序
 *为每个可能的例外原因。
 *
 *可以从应用程序显式调用vPortExceptionsInstallHandlers()
 *代码。完成后,将使用默认的FreeRTOS异常处理程序
 *已安装可以替换任何特定的异常原因使用
 *标准的Xilinx库函数microblaze_register_exception_handler()。
 *
 *如果未明确调用vPortExceptionsInstallHandlers()
 *应用程序,第一次由RTOS内核自动调用
 *调用xPortInstallInterruptHandler()。那个时候,任何例外
 *将替换可能已安装的处理程序。
 *
 *有关信息,请参阅vApplicationExceptionRegisterDump()的说明
 *关于FreeRTOS异常处理程序执行的处理。
 * /
void vPortExceptionsInstallHandlers(void);

/ *
 * FreeRTOS异常处理程序填充xPortRegisterDump结构(已定义
 *在portmacro.h中使用MicroBlaze上下文,就像当时的那样
 *发生异常。然后异常处理程序调用
 * vApplicationExceptionRegisterDump(),传入对已完成的引用
 * xPortRegisterDump结构作为其参数。
 *
 * FreeRTOS内核提供了自己的实现
 * vApplicationExceptionRegisterDump(),但RTOS内核提供了实现
 *被宣称为“弱”。弱定义允许应用程序
 *作者提供自己的实现,应该如何使用
 *注册转储信息。例如,可以提供实现
 *将寄存器转储数据写入显示器或UART端口。
 * /
void vApplicationExceptionRegisterDump(xPortRegisterDump * xRegisterDump);

RTOS端口特定配置

可以使用FreeRTOS / Demo / MicroBlaze_Spartan-6_EthernetLite / SDKProjects / RTOSDemo / FreeRTOSConfig.h文件中包含的配置常量自定义RTOS内核和演示行为。大多数这些配置常量用于所有FreeRTOS端口,并在 本网站的“ 自定义”页面和“ FreeRTOS参考手册”中进行了描述。
以下常量特定于此端口:

 

内存分配

Source / Portable / MemMang / heap_3.c包含在MicroBlaze演示应用程序makefile中,用于提供RTOS内核所需的内存分配。有关完整信息,请参阅API文档的“ 内存管理”部分。
heap_3.c使用从RTOS调度程序锁定部分调用的标准malloc()和free()函数,使它们对线程安全。总可用堆大小设置在位于\ Demo \ MicroBlaze_Spartan-6_EthernetLite \ SDKProjects \ RTOSDemo \ src 目录中的链接描述文件的顶部 。

 


Nexys 4 DDR – Microblaze入门

nexys-4-ddr-0.png

概观

本指南将逐步介绍使用适用于Nexys 4 DDR FPGA板的Vivado IP Integrator创建基于Microblaze的硬件设计。

在本教程结束时,您将拥有:

在Xilinx Vivado中创建了基于Microblaze的硬件(HW)设计
在Xilinx Vivado SDK(软件开发工具包)中创建了一个.C项目,使用上一步中显示的硬件设计显示Hello World
在SDK控制台和Tera Term上显示最终输出
先决条件

硬件

Digilent Nexys 4 DDR FPGA板和Micro USB电缆,用于UART通信和JTAG编程

软件

Xilinx Vivado 2015.X与SDK包。

董事会支持文件

董事会支持文件
这些文件将描述电路板上的GPIO接口,使您可以更轻松地选择FPGA板并添加GPIO IP模块
关于如何为Vivado安装Board支持文件,请遵循此Wiki指南(适用于Digilent 7系列FPGA板的Vivado Board文件)

教程

Microblaze是Xilinx的软IP核,它将完全在Xilinx FPGA通用存储器和逻辑结构中实现微处理器。在本教程中,我们将使用Vivado IP Integrator工具添加Microblaze IP块。

除了Microblaze IP模块,我们还想在Nexys 4 DDR上使用DDR2 SDRAM组件。因此,我们的设计中将添加MIG(存储器接口生成器)IP模块。

最后,将添加UART(通用异步接收器/发送器)IP模块,以便在主机PC和运行在Nexys 4 DDR上的软核处理器核心之间进行通信。

一般设计流程

I. Vivado

打开Vivado并选择Nexys 4 DDR板
创建一个新的Vivado项目
在新项目中创建空块设计工作区
使用IP集成工具添加所需的IP块并构建硬件设计
验证并保存块设计
创建HDL系统包装器
运行设计综合与实现
生成位文件
导出硬件设计,包括生成的位流文件到SDK工具
启动SDK
现在,硬件设计将导出到SDK工具。Vivado到SDK的交接是通过Vivado在内部完成的。我们将使用SDK创建一个软件应用程序,该应用程序将通过从Vivado导入硬件设计信息来使用定制的板接口数据和FPGA硬件配置。

II。SDK

创建新的应用程序项目并选择默认的Hello World模板
程序FPGA
通过选择正确的UART COM端口和波特率来运行配置


1.创建一个新项目

当您第一次运行Vivado时,这将是您可以创建新项目或打开最近项目的主要启动窗口。

1.1)单击“ 创建新项目”。选择项目名称和位置,以便没有空格。这是项目名称,文件名和位置路径遵循的重要命名约定。Underscore是空白空间的绝佳替代品。优良作法是为Vivado Projects提供专用文件夹,最好具有尽可能小的路径长度。示例:C:/ Vivado_Projects。为您的项目命名并选择项目位置,然后单击下一步。
mig_1.jpg

1.2)选择项目类型作为RTL项目。离开不要指定源未选中状态,然后单击下一步。
mig_1-1.jpg

1.3)如果您已按照Board Support File Wiki指南进行操作,请单击“下一步”并选择“ 板”。从过滤器选项中为供应商,显示名称和电路板修订版本进行必要的选择。Nexys 4 DDR应显示在选择列表中。选择正确的电路板名称不匹配将导致错误。
mig_2.jpg

1.4)显示新项目设计源和目标设备的摘要。单击完成。
mig_3.jpg

2.创建新的块设计

2.1)这是主项目窗口,您可以在其中创建基于IP的块设计或添加基于RTL的设计源。左侧的流导航器面板提供了有关如何创建硬件设计,执行模拟,运行合成和实现以及生成位文件的多个选项。您还可以使用硬件管理器直接从Vivado使用生成的RTL项目位文件对电路板进行编程。对于我们的设计,我们将使用IP Integrator创建新的块设计。
mig_4.jpg

2.2)在左侧,您应该看到Flow Navigator。在IP Integrator下选择Create Block Design。为您的设计命名,没有任何空格。
mig_5.jpg

2.3)创建一个空的设计工作区,您可以在其中添加IP块。单击“ 添加IP”图标添加IP内核。这应该从Xilinx IP存储库打开预构建的IP块目录。搜索“Microblaze”并双击它以将IP块添加到空设计中。
mig_6.jpg

3.添加Microblaze IP和自定义

3.1)这是Xilinx Microblaze IP模块。添加新IP块后,用户可以通过单击Run Block Automation消息提示或双击块本身来自定义块属性。
mig_7.jpg

3.2)选择Run Block Automation,将使用默认设置打开自定义助手窗口。
mig_8.jpg

3.3)更改块选项中的默认设置,如下所示,然后单击“ 确定”。这将使用我们的新用户设置自定义块。
nexys4ddr-mb_blockauto.png

3.4)运行块自动化将自动生成一组额外的IP块,这些块将根据上一步中选择的选项自动添加到我们的硬件设计中。不要单击“运行连接自动化”。
nexys4ddr-mb_blockauto2.png

4.定制时钟向导IP块

4.1)双击时钟向导(clk_wiz_1)IP块。
nexys4ddr-clkwizard1.png

4.2)为CLK_IN1 选择系统时钟。
nexys4ddr-clkwizard2.png

4.3)选择Output Clocks选项卡。
nexys4ddr-clkwizard3.png

4.4)选择clk_out2输出频率为“200.000”(Mhz)并将Reset Type设置为Active Low。左侧面板显示块的GUI表示及其内部设置。观察到复位引脚现在将读为复位。这以图形方式表示低电平有效的内部设置。
nexys4ddr-clkwizard4.png

4.5)现在转到端口重命名选项卡。这将为您提供时钟向导IP 块的输入和输出的摘要。单击确定以完成时钟向导的块自动化。不要选择“运行连接自动化”。
nexys4ddr-clkwizard5.png

5.添加UART IP块

5.1)转到 添加IP并搜索“UART”。
mig_17.jpg

5.2)选择AXI Uartlite IP块。
mig_18.jpg

5.3)这将为现有设计添加UART块。我们需要一个UART控制器来在Host-PC上的终端窗口和Nexys 4 DDR硬件之间进行通信。
nexys4ddr-adduart.png

6.首次运行连接自动化

6.1)现在从Designer Assistance栏消息提示中选择Run Connection Automation。这将打开“运行连接自动化”窗口。选择ext_reset_in,如图所示。将显示该接口的说明以及可用的信号选项。选择reset作为板部件接口。
mig_20.jpg

6.3)现在选择所有可用连接,然后单击“ 确定”。完成此步骤将连接到目前为止已添加和自定义的所有IP块。除了执行可用IP块的自动连接之外,还将在我们的设计中添加名为microblaze_0_axi_periph的新IP块。两个信号引脚复位,并且还将添加sys_clock。引脚信号指向右侧,表示它们是时钟向导块(clk_wiz_1)和复位时钟向导块(rst_clk_wiz_1_100M)的输入。
nexys4ddr-connectionauto.png

注意,RESETN输入引脚和CLK_OUT2在输出销clk_wiz_1块未连接到任何有效信号。我们将手动仅将复位引脚连接到复位信号。该CLK_OUT2销稍后将手动连接。

此时不要选择“运行连接自动化”。

7.第一次手动连接

7.1)信号管脚手动连接复位到RESETN所述的输入clk_wiz_1块。将光标指针放在重置输入上,您应该看到光标变为笔的图形表示。拖放复位信号线上的任何位置。
7.2)将突出显示手动连接。此时不要选择“运行连接自动化”。
nexys4ddr-firstmancon1.png

8.添加和自定义内存接口生成器IP块

8.1)存储器接口生成器将是我们将在设计中添加的最终IP块。
nexys4ddr-addmig.png

8.2)添加MIG IP块后,单击Run Block Automation。
8.3)板部件接口将显示为DDR2_SDRAM。单击“ 确定”以运行块自动化。
mig_26.jpg

8.4)运行MIG块自动化时,您将看到此特定错误消息[BD 41-1273]。你现在可以忽略它。它不会以任何方式影响您的设计。MIG模块将根据为Nexys 4 DDR下载的电路板支持文件进行配置。单击“确定”关闭此消息。您会发现MIG IP模块现在有额外的输入和输出引脚,必须连接到有效信号。
nexys4ddr-error41-1273.png

9.第二次运行连接自动化

9.1)现在单击Designer Assistance栏上的Run Connection Automation消息提示。mig_28.jpg

9.2)仅选择连接自动化列表中的mig_7series_0。请勿在此步骤中选择Microblaze部分。单击确定。
mig_29.jpg

9.3)将建立并显示新的信号连接。
mig_30.jpg

10.第二次手动连接

10.1)手动连接CLK_OUT2在输出端口信号clk_wiz_1到sys_clk_i输入端口上mig_7series_0块。clk_out2信号是我们在时钟向导块自动化步骤中添加的200 Mhz时钟信号。
mig_31.jpg

10.2)选择以蓝色圈出的按钮。这是 Regenerate Layout选项,它将重新排列设计中的IP块。
nexys4ddr-secmancon2.png

11.使DDR2信号外部

11.1)MIG块应该读取mig_7series_0。
将光标放在此符号||上 在DDR2 +端口名称旁边。您的光标将变为看起来像铅笔。右键单击此处,在下拉列表中选择Make External或左键单击|| 并使用键盘快捷键“Ctrl + t”。
11.2)这将创建一个标记为DDR2的新输出端口连接。
nexys4ddr-mkddr3ext.png

11.3)再次重新生成布局。
nexys4ddr-mkddr3ext2.png

12.验证设计

12.1)选择 验证设计。这将检查设计和连接错误。
nexys4ddr-validdesign1.png

12.2)在设计验证步骤之后,我们将继续创建HDL系统包装器。
nexys4ddr-validdesign2.png

13.创建HDL系统包装器

13.1)如本步骤所示,右键单击design_1并选择Create HDL Wrapper。让Vivado管理包装器并选择OK。
nexys4ddr-wrapper.png

13.2)将生成一个系统包装文件,并在tcl控制台中显示一条消息,通知我们已生成wrapper.v文件。
nexys4ddr-wrapper2.png

14.生成位文件

14.2)在左侧的Flow Navigator面板中,在Program and Debug下选择Generate Bitstream选项。如果您尚未保存设计,则会提示您保存块设计。
nexys4ddr-genbit.png

14.3)将开始生成位文件。该工具将运行综合和实施。在成功完成综合和实现后,将创建实际的位文件。您将在项目窗口的右上角找到运行合成和实现的状态栏。
nexys4ddr-genbit2.png

14.4)生成比特流后,屏幕上可能会弹出一条消息提示。您无需为此演示打开Implemented Design。只需点击取消即可。
mig_42.jpg

15.将硬件设计导出到SDK

15.1)在窗口的左上角,从工具栏中单击“ 文件”,然后选择“ 导出硬件”。
这将使用软件开发工具 – Vivado SDK的系统包装器导出硬件设计。选中复选框,确保包含生成的比特流。
mig_43.jpg

15.2)将在Hello_World.SDK下创建一个类似于Vivado硬件设计项目名称的新文件目录。还创建了另外两个文件.sysdef和.hdf。此步骤实际上创建了一个新的SDK工作区。
如果浏览到创建Vivado项目的驱动器上的位置,您将看到已在SDK下创建了新文件夹。请参阅下面的屏幕截图中的TCL控制台消息。现在设计已导出到Software Development Kit(SDK)工具,下一步将是启动SDK工具。
mig_44.jpg

16.启动SDK

16.1)转到文件并选择启动SDK,然后单击确定。将启动在Vivado设计项目位置本地创建的SDK文件。从Vivado切换到SDK已经完成。
mig_45.jpg

17.适用于Vivado的SDK

17.1)将打开SDK的新窗口。硬件设计规范和包含的IP块显示在system.hdf文件中。SDK工具独立于Vivado,即从这一点开始,您可以在导出的HW设计之上使用C / C ++创建SW项目。如有必要,您还可以直接从主Vivado项目目录中创建的SDK文件夹启动SDK。
现在,如果您需要返回Vivado并更改硬件设计,则建议关闭SDK窗口并在Vivado中进行所需的硬件设计编辑。在此之后,您必须按照创建新HDL包装器的顺序,保存设计和位文件生成。然后必须将此新位文件和系统包装器导出到SDK。
由于此时我们没有任何硬件设计编辑,我们将继续创建一个软件应用程序来显示Hello World。
mig_46.jpg

17.2)在主SDK窗口的左下角,您将找到Project Explorer面板。请注意,名称为design_1_wrapper_hw_platform_0的主项目文件夹。
design_1是在Vivado中创建的块设计的名称。该硬件平台具有所有硬件设计定义,已添加的IP接口,外部输出信号信息和本地存储器地址信息。
如果此时,您已关闭SDK,对现有硬件设计进行了编辑,并将您的设计导出到SDK,那么在启动SDK工具后,您将找到一个新的硬件平台,名为:design_1_wrapper_hw_platform_1,除了旧的硬件设计,即design_1_wrapper_hw_platform_0。
mig_47.jpg

18.在SDK中创建新的应用程序项目

18.1)转到主工具栏中的File并选择New Application Project。将弹出一个新的项目窗口。为SDK项目指定一个没有空格的名称,如下所示。确保目标硬件是正确的硬件设计。在我们的例子中,它将是design_1_wrapper_hw_platform_0。
例如,如果在Project Explorer窗口中还有另一个硬件设计,那么您还将在Target Hardware下拉选择列表中看到此设计名称。
由于我们只有一个硬件设计 design_1_wrapper_hw_platform_0,这将是我们的目标硬件。选择Board Support Package下的Create New。该工具将自动填充Board Support Package名称以与给定项目名称匹配。
点击下一步。
mig_48.jpg

19.从可用模板中选择Hello World Application

19.1)在左侧面板的Available Templates下选择Hello World,然后单击Finish。
mig_49.jpg

19.2)完成上一步后,您将在Project Explorer面板中看到两个新文件夹:

  • display_hello_world,其中包含所有二进制文件,.C和.H(Header)文件
  • display_hello_world_bsp这是板支持文件夹

display_hello_world是我们的主要工作源文件夹。这里还包含一个重要的文件,它是lscript.ld。这是Xilinx自动生成的链接描述文件。双击此文件打开。
mig_50.jpg

20.验证内存区域映射的链接描述文件

20.1)在链接描述文件中,查看“ 部分到内存区域映射”框。如果您执行了Make DDR2 External步骤,则目标内存区域必须读取mig_7series_0。
向下滚动以检查这是否适用于所有行。如果对于任何区域,它不会说mig_7series_0,则单击Memory Region列下的行并选择mig_7series_0。
mig_51.jpg

20.2)返回Project Explorer,双击并打开src文件夹下的helloworld.c。src代表来源。 这是主要的.C文件,它将在执行时在控制台中打印hello world。
mig_52.jpg

21.用位文件编程FPGA

21.1)确保使用随附的micro USB线打开Nexys 4 DDR并连接到主机PC。
在快速选择工具栏中,您将找到带有红色箭头和三个绿色方框的符号。此可单击按钮实际位于主工具栏的“ 搜索”选项卡下。
单击此符号可打开Program FPGA窗口。
确保选择硬件平台为design_1_wrapper_hw_platform_0。
在软件配置框中,在Block RAM列中的ELF File to Initialize下,row选项必须读取bootloop。如果没有,请单击该行并选择bootloop。
现在点击Program。
mig_53.jpg

22.运行STDIO连接的配置设置

22.1)使用位文件成功编程FPGA后,在Project Explorer面板中,右键单击display_hello_world项目文件夹,该文件夹已在下面的屏幕截图中突出显示。
在下拉列表的底部,选择“运行方式”,然后选择“运行配置”。
“运行配置”窗口分为两个主要部分。在左侧面板中,在Xilinx C / C ++应用程序(GDB)下,选择display_hello_world.elf。

  • 注意:如果您在此步骤中看到display_hello_world Debug而不是display_hello_world.elf,您仍然可以毫无问题地运行它。
    在此窗口的右侧,您将看到五个主要选项卡。选择STDIO Connection选项卡。
    mig_54.jpg

23. STDIO连接的COM端口选择

23.1)将端口名称更改为正确的UART端口。您可以在设备管理器 → 端口(COM和LPT)下找到通信端口名称/编号。通信端口将显示为USB串行端口(COM X),其中X是PC的端口号。对我而言,它显示为COM4。选择波特率为9600。
选中Connect STDIO to Console框。如果您取消选中它,如下所示,则不会建立连接。确保选中此框。现在单击Apply and Run。
mig_58.jpg

24.在SDK内置控制台窗口中显示Hello World输出

24.1)Hello World将显示在Console选项卡上,如下所示。
nexys4ddr-disphelloworld.png

25.使用Tera Term终端仿真器的可选步骤

请参阅此链接http://en.wikipedia.org/wiki/Tera_Term以了解Tera Term是什么。您可以从此链接http://ttssh2.sourceforge.jp/index.html.en下载并安装Tera Term

25.1)在使用Tera Term建立串行连接之前,请确保在SDK中,未选中“运行配置”中“ STDIO连接”选项卡下的“ 连接STDIO”框。 使用Tera Term中正确的通信端口建立串行连接。 转到SDK运行配置 →应用并运行。 Tera Term将通过显示输出作为控制台。 请注意,在SDK的内置控制台窗口中,显示一条消息,显示端口COM4已在使用中,表明Tera Term正在使用COM4端口。

mig_61.jpg

请登录后发表评论