瑞萨RZ/T2H平台多核异构的应用场景分析

描述

本文以RZ/T2H多轴控制/驱动的实例,介绍RZ/T2H平台的多核异构应用场景。分为:

示例软件基本框架;

使用RemoteProc启动R核;

程序启动后,R核之间通过数据共享来传递数据;

RZ/T2H的启动流程。

该例程运行于RZ/T2H平台,该平台由两个CR52核和四个CA55核构成。其中,CA55核跑Linux  OS+EtherCAT主站软件;CR52_1运行EtherCAT从站,与主站实现9轴的控制/状态数据实时交互;CR52_2运行9轴的电机驱动程序。

01基本框架

ethercat

图一 多核异构的软硬件框架

EtherCAT Controller(CiA402)位于CA55 Linux 侧,负责上位通信控制。包括EtherCAT主站通信、电机控制指令下发和现场数据收集等等。

EtherCAT Slave device(CiA402)位于CR52_1上,运行EtherCAT从站协议栈,执行EtherCAT数据帧处理与设备对象管理,运行在裸机环境中,保证实时性。

CA55端的ECAT主站和CR52_1端的ECAT从站,通过内部端口连接,EtherCAT数据流直接在2个域之间流动,不需要从外部端口回环;

9-axis motor drive位于CR52_0,负责伺服电机驱动(多轴机器人控制)。功能包括:PWM计算和输出,编码器反馈数据采集,电流环/速度环/位置环计算和数据反馈,运行在裸机环境。

运行于CA55的CODESYS RUNTIME(EtherCAT Master),通过EtherCAT协议向CR52_1发送控制数据,CR52_1通过共享内存向CR52_0转发解析后的数据,CR52_0控制外设来控制电机。

同理,电机的实时状态数据由CR52_0采集,通过共享内存机制传递到CR52_1,CR52_1再通过EtherCAT协议把数据传回主站。

02CA55端采用OpenAMP的RemoteProc来启动CR52_0和CR52_1

ethercat

图二 remoteProc启动CR52_0和CR52_1

Remoteproc代码位于/sources/linux-renesas/drivers/remoteproc/rz_rproc.c

2.1 操作结构体

ethercat

rz_rproc_ops是一个struct rproc_ops类型的结构体,它定义了远程处理器(remoteproc)的操作函数集。这个结构体在`rz_rproc_probe`函数中被使用,具体是在创建新的remoteproc实例时作为参数传递给devm_rproc_alloc函数:

左右滑动查看完整内容

 

rproc = devm_rproc_alloc(dev, np->name, &rz_rproc_ops, NULL, sizeof(*pdata));

 

该操作包含以下操作函数:

prepare:准备远程处理器的资源

start:启动远程处理器,当系统需要启动远程处理器时会调用

stop:停止远程处理器,当需要停止远程处理器时会调用

da_to_va:设备地址到虚拟地址的转换,见源码中的A55核和R52核之间的地址访问转换关系

parse_fw:解析固件,当需要加载固件时,会调用 parse_fw 和相关的 ELF 操作函数

2.2 probe的驱动框架层次:

左右滑动查看完整内容

 

module_platform_driver(rz_rproc_driver)
    |-- 设备树匹配 "renesas,rz-cr52"
    |-- rz_rproc_probe()
        |-- devm_kzalloc() 分配私有数据
        |-- devm_rproc_alloc() 分配 remoteproc 结构
        |   |-- 关联 rz_rproc_ops 操作函数集
        |-- 读取设备树属性
        |   |-- renesas,rz-core
        |   |-- renesas,rz-swint
        |   |-- renesas,rz-start_address
        |   |-- renesas,rz-autoboot
        |-- pm_runtime_enable() 启用电源管理
        |-- rproc_add() 注册远程处理器
            |-- 创建 sysfs 接口
            |-- 初始化远程处理器状态

 

当执行echo gcc_rzn2h_cr52_0_rpmsg_linux_baremetal_demo.elf> /sys/class/remoteproc/remoteproc0/firmware时,会调用firmware_store修改firmware的名字。

当执行echo start > /sys/class/remoteproc/remoteproc0/state,会产生state_store->rproc_boot->request_firmware->rproc_fw_boot->rproc_start,此时调用rz_rporc.c中的rproc->ops->start

左右滑动查看完整内容

 

rproc_boot()
    |-- rproc_prepare_device()
    |   |-- rz_rproc_prepare()  // 我们驱动中的准备函数
    |-- request_firmware()      // 从文件系统加载固件
    |-- rproc_fw_sanity_check()
    |   |-- rz_rproc_ops.sanity_check()
    |-- rproc_parse_fw()
    |   |-- rz_rproc_parse_fw()  // 解析固件内容
    |-- rproc_load_segments()
    |   |-- rproc_elf_load_segments()
    |-- rproc_start()
        |-- rz_rproc_start()   // 启动远程处理器

 

2.3 设备树节点分析

ethercat

ethercat

设备树节点的compatible="renesas,rz-cr52"会匹配到驱动中的:

左右滑动查看完整内容

 

staticconststructof_device_idrz_rproc_of_match[] = {
    { .compatible = "renesas,rz-cr52" },
    { /* end of list */ },
};

 

从而找到该驱动。

资源初始化流程:

`reg`属性定义了两个内存区域:

cr52_sram:0x10000000-0x101FFFFF (SRAM区域)

cr52_ddr:0x3E0000000-0x3E9000000(DDR区域)

`memory-region`指向三个预留内存区域:

`vdev0vring0`:虚拟设备环形缓冲区0

`vdev0vring1:虚拟设备环形缓冲区1

`vdev0buffer`:虚拟设备共享缓冲区

左右滑动查看完整内容

 

renesas,rz-core = <0x0>;        // CR52核编号
renesas,rz-swint = <10>;        // 软中断通道
renesas,rz-start_address = <0x00000000>;  // 启动地址
   

 

注意CR52_0:

启动地址0x00000000,CR52_1:启动地址0x10061000。这两个地址需要与firmware编译后的地址一致。

2.4 remoteProc的start本地实现

我们提取其中的static int rz_rproc_start(struct rproc*rproc)来做一下简单介绍:

 

prcrs_base = ioremap(PRCRS, 0x4);
prcrn_base = ioremap(PRCRN, 0x4);

 

设置PRCRS和PRCRN,用于使能GPIO写功能。

接下来建立CA55视角的地址空间:

左右滑动查看完整内容

 

atcm_base_0 = ioremap(BSP_PRV_ATCM_AXIS_CR520_ADDRESS,
(CR52_ATCM_END - CR52_ATCM_START));

 

同理得到:atcm_base_1,btcm_base_0,sysram_base。

从T2H的用户手册上,也可以查到A55核访问异构核的对应地址。

ethercat

图三 A55访问ATCM/BTCM/SRAM的物理地址

接下来是拷贝CR52_1的firmware

ethercat

拷贝完成后Reset CR52_0,通过设置SWRCPU0为0x4321A502来release和reset,便开始执行该firmware。

启动脚本为:

左右滑动查看完整内容

 

# 将存在的固件名写入remoteproc sysfs 入口
echo CR52_0_motor.elf > /sys/class/remoteproc/remoteproc0/firmware
echoCR52_1_ECAT.elf > /sys/class/remoteproc/remoteproc1/firmware
#启动远端处理器
echostart > /sys/class/remoteproc/remoteproc0/state
echostart > /sys/class/remoteproc/remoteproc1/state

 

03CR52_0与CR52_1之间的共享数据

CR52_0和CR52_1之间通过核间通信(基于共享内存机制),交换电机控制参数和状态信息。使用 Shared Memory驱动(r_shared_memory,通过瑞萨FSP生成)和核间中断机制,实现核间数据交换,同时通过硬件信号量和软件标志位来保证数据完整性和互斥访问。

ethercat

图四 CR52_0与CR52_1之间的数据共享

ethercat

图五 数据共享的消息序列图

数据传输

CR52_1使用SHARED_MEMORY API将数据结构写入到2个CPU的共享内存区域。写入操作仅在数据发生变化时进行,从而避免不必要的访问,写入完成,CR52_1产生一个核间中断通知CR52_2。

数据接收

CR52_2收到CR52_1发来的中断,开始从共享内存区读取数据,同时在回调函数会设置一个标志位,以标志数据读取过程完成。

T2H自带2MB的SRAM,将CR52_0和CR52_1之间的1.5KB数据共享放到了如下地址:

ethercat

图六 数据共享地址

04T2H的启动顺序

ethercat

图七 T2H多核启动顺序

BL2表示引导加载程序的第2阶段(Boot Loader stage 2),BL3表示引导加载程序的第3阶段(Boot Loader stage 3),WFI表示Wait For Interrupt。

T2H上电后,始终从CR52_0启动,BOOTROM根据BL2的加载地址决定是从CR52_0继续启动还是跳转到CA55启动;

上图的启动流程:

系统上电后,Boot function将BL2加载到 SystemRAM中,并跳转到其入口地址执行。

BL2将BL3和U-Boot加载到DDR SDRAM中,并跳转到BL3的入口地址执行。

BL3为U-Boot做一些初始化准备工作,然后跳转到U-Boot的入口地址执行。

U-Boot加载Linux并启动它。

通过remoteproc加载并启动Cortex-R52 CPU0 的固件。

Cortex-R52 CPU0开始执行其固件。

通过remoteproc加载并启动Cortex-R52 CPU1 的固件。

Cortex-R52 CPU1开始执行其固件。

以上完成多核的启动,再配合CA55端的CODESYS RUNTIME,可以完成驱控一体的系统搭建。9轴驱控视频请见:

RZ T2H完整的软硬件设计规范、参考例程、工具等,请登录以下网址获取更多资料。

RZ/T2H - Advanced High-End MPU with Integrated Powerful Application Processing and High-Precision Real-Time Control for 9-Axis Motor Control | Renesas

https://www.renesas.com/en/products/microcontrollers-microprocessors/rz-mpus/rzt2h-advanced-high-end-mpu-integrated-powerful-application-processing-and-high-precision-real-time

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分