【ZynqMP】在Cotex-R5上使用FreeRTOS并配置为SYSTICK至1000Hz

【一】ZynqMp的资源
ZynqMP资源配置
根据Xilinx官方选型文档克知:CG系列具有两个A53核+2个R5F核,而EV系列拥有过4个A53核+2个R5核,这个资源情况要视你板子的情况而定,本博客是基于Zu5EV来进行描述的,并且在R5核中也仅使用第一个核心。
【二】系统的架构
系统架构
这里简单描述了当前的系统架构,A53大核运行Linux系统,R5小核运行FreeRTOS,PS与PL之间交互一般可以通过AXI 来读取DDR、使用SPI(共享中断)等方式,而A53和R5的交互也是可以使用共享DDR以及IPI中断等。值得注意的是,A53和R5不能同时操作同一个外设,假如我有系统资源UART0,A53默认使用了它之后,那么R5就无法使用UART0了,这倒不是因为R5无法调用它,而是调用它可能会使得原本的A53系统产生崩溃。所以,在两个系统架构同时存在的情况下,尽量将硬件资源【包括PL端给的共享中断】划分好。
这里有一个问题,那就是为什么需要R5核。根据Xilinx的应用手册中描述,R5核心指(Real Time Process Unit->RPU)即实时处理核心。A53虽然主核的主频较高,但是由于搭载了Linux系统,在运行应用时不得不由于系统开销导致系统的实时性较差,在一些对于实时性要求非常高的应用下(例如电机控制),反而有点不适用,但如果将A53单纯作为一个实时核去使用的话,可能又有点杀鸡用牛刀的感觉。在这种情况下,其实一些MCU会更为适合,而R5核就相当于在这个系统中替代了MCU的位置。另外,A53在运行Linux系统的情况下,同时配合R5进行实时处理(无论是算法实时处理,还是硬件实时处理),可以对各种应用进行更为高阶的开发体验。例如,我需要做一个电机控制,但是传统MCU在做电机控制的同时,顶多支持到PHY芯片以太网传输信息。但无法支持到建立复杂的WebServer服务器以及屏幕显示功能。屏幕显示功能需要大量的RAM以及运算力要求,WebServer服务器的建立则需要文件系统与网络系统的支撑,在这种情况下,搭载有Linux系统的A53核心就遥遥领先了。
【三】实操介绍
前期准备:Vivado、Vitis、Ubuntu(安装好pentalinux)
(1)Vivado建立platform
这里需要注意的一点,就是在Block Design中需要勾选TTC0,或者TTC0~TTC3全勾,原因是在使用Vitis中FreeRTOS的例程时,无一例外都使用TTC0作为SYSTICK的来源,如果没有勾选的话,在使用xsa建立工程时就会进行报错。其实这也很好理解,FreeRTOS作为一个时间轮转片类的小型RTOS,它需要SYSTICK来进行系统节拍的生成。但是我不能理解的是,其实R5核内部也有一个CPU的计时器,在使用裸机程序的时候,通过追溯Sleep函数发现了它的存在,所以因此它应该是有自身的SYSTICK之类的时钟的,为什么这里的例程不使用这个时钟就不得而知了,如果要改的话,会相当麻烦,所以个人建议还是将TTC0勾选。
(2)A53 Linux方面需要修改的点
A.设备树

  reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        rpu0vdev0vring0: rpu0vdev0vring0@3ca00000 {
            no-map;
            reg = <0x0 0x3ca00000 0x0 0x4000>;                /* 用于 核间通讯 */
        };
        rpu0vdev0vring1: rpu0vdev0vring1@3ca04000 {
            no-map;
            reg = <0x0 0x3ca04000 0x0 0x4000>;                /* 用于 核间通讯 */
        };
        rpu0vdev0buffer: rpu0vdev0buffer@3ca08000 {
            no-map;
            reg = <0x0 0x3ca08000 0x0 0x100000>;            /* 用于 核间通讯 */
        };
        rproc_0_reserved: rproc@3c000000 {
            no-map;
            reg = <0x0 0x3c000000 0x0 0xa00000>;
             /* 用于R5-0程序运行需要, 基地址 更改需要测试(有些地址会异常,具体需要测试), size根据需要调整  */
            /* 该地址和 R5-0 裸机程序需要匹配 */
        };
    };

    zynqmp-rpu {
        compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        core_conf = "split";
        reg = <0x0 0xFF9A0000 0x0 0x10000>;
        r5_0: r5@0 {
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            memory-region = <&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
            pnode-id = <0x7>;
            mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
            mbox-names = "tx", "rx";
            tcm_0_a: tcm_0@0 {
                reg = <0x0 0xFFE00000 0x0 0x10000>;            /* 参考UG1085   */
                pnode-id = <0xf>;
            };
            tcm_0_b: tcm_0@1 {
                reg = <0x0 0xFFE20000 0x0 0x10000>;            /* 参考UG1085   */
                pnode-id = <0x10>;
            };
        };
    };

    zynqmp_ipi1 {
        compatible = "xlnx,zynqmp-ipi-mailbox";
        interrupt-parent = <&gic>;
        interrupts = <0 29 4>;
        xlnx,ipi-id = <7>;
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;

        ipi_mailbox_rpu0: mailbox@ff990600 {
            reg = <0xff990600 0x20>,
                  <0xff990620 0x20>,
                  <0xff9900c0 0x20>,
                  <0xff9900e0 0x20>;
            reg-names = "local_request_region",
                    "local_response_region",
                    "remote_request_region",
                    "remote_response_region";
            #mbox-cells = <1>;
            xlnx,ipi-id = <1>;
        };
    };

这里 zynqmp-rpu是用于R5核的设备节点,并且也指明了使用的内存区域:<&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>,zynqmp_ipi1则是为了支持IPI中断而攥写的设备节点,虽然本工程没用,但如果以后需要用,就不必再加了,详情可以查看Xilinx OpenAMP相关信息。这里比较重要的就是这四个预留内存,其中rproc_0_reserved是留给R5引导程序的,程序就放置在这个地址,这个地址非常重要,后面Vitis编程中的引导文件lscript.ld需要用。其余三个都是用于核间通讯,当然如果PL需要和R5通讯的话,也可以自己划一片内存区,格式和以上一致就行。这里讲一个比较特殊的地方,就是这个内存区域的划分是需要与系统占用的区域岔开的,不要有所冲突。否则,你的R5程序可能会无法运行。
如何避免冲突呢?很简单,在A53引导至UBOOT阶段时,按下enter打断,并输入bdinfo命令来查看目前一些地址的占用与分配。如果想要一次成功,也可以直接使用以上的设备树,一般是可行的。
这里梳理一下内存的分配情况:
程序:10Mb 3C000000~3CA00000
ring0:16Kb 3CA00000~3CA04000
ring1:16Kb 3CA04000~3CA08000
devbuffer: 64Kb 3CA08000~3CA18000
B.内核配置petalinux-config -c kernel

[*] Enable loadable module support  --->

Device Drivers  --->
    Remoteproc drivers  --->
        [*] Support for Remote Processor subsystem
        <*>   ZynqMP_r5 remoteproc support
        
Rpmsg drivers  --->
    <*> RPMSG device interface

按照以上方法启动A53核心进入Linux后,查找文件系统中是否包含这个目录“/sys/class/remoteproc/remoteproc0/”,如果包含则已经设置成功。
(3)使用Vitis建立工程
Step1.选定XSA建立platform,这里需要注意取消勾选Generate boot components,因为目前R5的应用并不是单独运行,而是在A53 Linux启动之后引导的,所以无需Boot。如果你需要单独运行R5程序,则需要勾选。
Step2.勾选R5核心,并对程序项目进行命名。如果你在这个页面中没有发现任何有用的核心,说明你的Vitis安装有问题,部分Vitis版本在Windows下会存在这个BUG,想要一劳永逸就在Ubuntu下安装Linux版本的Vivado以及Vitis吧。
Step3.在Operating System中从Stand Alone(裸机)替换为freertos10_xilix,最后选择FreeRTOS Hello World模板,当然视你的实际应用情况而定,也可以使用OpenAMP Demo进行双核通讯实验。
Step4.在生成的工程中,第一时间更改lscript.ld这个文件中psu_r5_ddr_0_MEM_0的数值,与设备树种的值保持一致。如下图:
在这里插入图片描述
好,现在开始步入正题,如何配置SYSTICK至1000Hz呢,学习过FreeRTOS的都知道,它针对于系统节拍的设置是由宏定义 configTICK_RATE_HZ 决定的,在一般情况下,将它设置为1000即将系统的节拍频率设置为1000Hz。但是!在Xilinx的这个官方库中,并不是如此!
全局搜索这个宏定义可以在portZynqUltrascale.c中FreeRTOS_SetupTickInterrupt函数找到关于这个宏定义的使用,其中:

XTimer_SetInterval(configTICK_RATE_HZ/10)

表明了官方库使用这个宏定义来设置定时器定时间隔的功能。官方预设的configTICK_RATE_HZ为100即100Hz,那么这个语句的使用方式是否有误呢?其实是有方法的错误,但得出了正确的结果。
跟踪至XTimer_SetInterval函数:

/****************************************************************************/
/**
*
* This API sets the elapse interval for the timer instance.
*
* @param            delay - delay time in milli seconds
*
* @return           none
*
* @note             none
*
*****************************************************************************/
void XTimer_SetInterval(unsigned long delay)
{
	XTimer *InstancePtr;

	InstancePtr = &TimerInst;
	if (InstancePtr->XTimer_TickInterval)
		InstancePtr->XTimer_TickInterval(InstancePtr, delay);
}

函数的注释写明了delay是以ms作为单位来计算间隔的,官方的输入方法为:100/10 = 10ms,那么自然是100Hz,这没有错误,但如果你将configTICK_RATE_HZ设置为1000,则得到:1000/10 = 100ms,那么系统的节拍将是10Hz,而绝非1000Hz!所以,在portZynqUltrascale.c中,我们需要将这个地方稍微更改一下:

XTimer_SetInterval(1000/configTICK_RATE_HZ)

这样的话,configTICK_RATE_HZ填入小于等于1000以下的值即可完成对于FreeRtos对于任意1000Hz以下频率的SYSTICK的配置。当然,一般的实时系统也不会将系统节拍设置于1000Hz以上,否则这样对于系统节拍的中断开销有点过大了。
Step5.生成elf,并传输至开发板的 /lib/firmware 目录下,如果没有该目录可以手动创建。
(4)输入指令运行R5 APP
cd /lib/firmware
echo app.elf > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state
此时 linux 会打印信息提示,但是打印等级有点低,需要连接串口才能看到,一般的SSH网络连接进去是看不到的,除了应用本身的printf以外,调用信息会在内核日志中显示,可以使用dmesg看到。
应用关闭:
echo stop > /sys/class/remoteproc/remoteproc0/stat

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
有关如何以操作系统感知的方式调试在Avnet MiniZed板上运行的Embedded FreeRTOS应用程序的指南。 介绍在操作系统之上编写嵌入式软件应用程序时,通常很难检测某些时序问题或解释某些奇怪的行为。到底出了什么问题?另一件事是,在研究嵌入式操作系统时,以可视方式呈现系统的运行行为会很有用。了解任务优先级,调度程序设置,队列管理,... 我发现Percepio Tracealyzer是解决这类问题的理想工具。Tracealyzer可以通过两种方式工作:在快照模式下(这是本教程的内容)或在流模式下。 对于本指南,您需要一个Avnet MiniZed开发板(基于Xilinx Zynq),Xilinx vivado工具和Percepio tracealyzer 4(其网站上的评估版)。 让我们开始开发本指南的硬件部分(FPGA设计)。如果您不熟悉FPGA设计,则可以打开我的硬件设计。否则,从下面开始构建基于ZYNQ7的设计: 基于zynq7的设计 在程序框图上放置以下组件: ZYNQ7 P rocessing 小号ystem 具有2个通道的AXI GPIO 连接到pl_led_g 和pl_led_r 1个通道的AXI GPIO 连接到pl_sw_1bit 您可以对ZYNQ7处理系统使用自动配置使用预设),但是随后必须手动添加M_AXI_GP0_ACLK 端口以连接AXI从设备外围设备。 使用“自动连接”功能将AXI_GPIO模块连接到AXI总线。 不要忘记在“模块设计”的顶部添加HDL包装器。生成比特流,并将您的硬件设计导出到Vivado SDK(包括比特流)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值