第十八节 多核异构核间通信–ipcc

这篇具有很好参考价值的文章主要介绍了第十八节 多核异构核间通信–ipcc。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

由于MP157 是一款多核异构的芯片,其中既包含的高性能的A7 核及实时性强的M4 内核,那么这两种处理器在工作时,怎么互相协调配合呢?这就涉及到了核间通信的概念了。

IPCC (inter-processor communication controller) 用于处理器间的数据交换的通知。它提供了一种非阻塞的信号机制,并提供原子的方式进行信号发布和信息检索。注意,核间通信的共享内存缓冲区是在MCU 的SRAM 中分配的,它不是IPCC 外设的一部分。

外设简述

IPCC 外设提供了硬件支持,来管理两个处理器实例之间的处理器间通信。每个处理器拥有特定的寄存器区域和中断。有点像硬件信号量的功能。

IPCC 提供了六个双向通道信号。每个通道分为两个子通道,每个子通道提供从“发送方”处理器到“接收方”处理器的单向信号:

  • P1_TO_P2 子通道(从P1 发到P2)
  • P2_TO_P1 子通道(从P2 发到P1)

子通道中包括如下功能:

  • 一个标志位,用于标识通道正在被占用和空闲的两种状态,这个标志被“发送方”处理器设置为被占用,并被“接收方”处理器清除。
  • 两个相关的中断(所有通道都共享):
    – RXO: RX 通道被占用,连接到“接收器”处理器。
    – TXF: TX 通道空闲,连接到“发送”处理器。
  • 带多路复用的中断掩码功能。

IPCC 支持以下信道的操作模式:
- 单工通信方式:
– 仅使用一个子信道。
– 单向消息:“发送者”处理器将通信数据发布到内存中后,它将通道状态标志设置为已占用。当消息被处理时,“接收者”处理器清除该标志。

  • 半双工通讯方式:
    – 仅使用一个子信道。
    – 双向消息:“发送者”处理器将通信数据发布到内存中后,它将通道状态标志设置为已占用。当消息被处理并且响应在共享内存中可用时,“接收器”处理器将清除该标志。
  • 全双工通讯方式:
    – 子通道用于异步模式。
    – 通过将子通道状态标志设置为占用,任何处理器都可以异步发布消息。当消息被处理时,“接收者”处理器清除该标志。可以将这种模式视为给定通道上两个单工模式的组合。

核间通信的模型如下:

第十八节 多核异构核间通信–ipcc

框架简述

IPCC 作为核间通信的桥梁,它仅承担着通知的角色,负责消息的分发、中断的处理等。

实际上,IPCC 外设这个角色只是多核异构核间通信中的一块,在我们使用多核异构核间通信时,往往不仅希望使用到核间的消息通知,还希望能在不同的核心中进行数据的交互(比如M4 核进行实时的AD 数据采集处理,完成后,M4 核可通过异构的框架将数据呈递给A7 核,A7 核再进行更复杂的应用)。那么在这个需求的驱动下,就出现了一些框架相互配合使用的情况了,下面我们就给大家介绍这些内核框架。

RemoteProc framework

远程处理器框架(RPROC、RemoteProc)允许不同的平台/体系结构控制(打开电源,加载固件,关闭电源)远程处理器,同时抽象出硬件差异。此外,它还提供监视和调试远程协处理器的服务。

以MP157 为例,其RemoteProc 可分为两块,分别是A7 核端、M4 核端:

remoteproc:这是远程处理器框架的通用部分(在MP157 中为A7 核端)。

它的作用是:

- 将ELF 固件加载到远程处理器内存中。
- 解析固件资源表以设置关联的资源(例如IPC,内存分割和跟踪)。
- 控制远程处理器的执行(启动,停止⋯)。
- 提供监视和调试远程固件的服务。

stm32_rproc:这是远程处理器平台驱动程序(在MP157 中为M4 核端)。

它的作用是:

- 将stm32 特定的功能(回调)注册到RPROC 框架。
- 处理与远程处理器关联的平台资源(例如寄存器,看门狗,复位,时钟和存储器)。
- 通过邮箱框架将通知(通知)转发到远程处理器。

ST 官方参考资料:
https://wiki.stmicroelectronics.cn/stm32mpu/wiki/Linux_RPMsg_framework_overview

RPMsg framework

此小节为大家简述有关Linux RPMsg 框架的内容。RPMsg 框架是一个基于virtio 的消息总线,它允许本地处理器与系统上可用的远程处理器通信。

此框架在多核异构中承担的角色如下图:

第十八节 多核异构核间通信–ipcc

Linux RPMsg 框架是在virtio 框架顶层上实现的消息传送框架,其用于主机和远程处理器进行通信。它基于virtio vring,可通过共享内存向远程CPU 发送消息或从远程CPU 接收消息。

这些vring 是单向的,一个vring 专用于发送到远程处理器的消息,另一个vring 用于从远程处理器接收的消息。此外,共享缓冲区需要在两个处理器都可见的内存空间中创建。

当新消息在共享缓冲区中等待时,会使用到另一个框架Linux Mailbox framework ,该框架将用于通知对应的Core。

依靠这些框架,RPMsg 框架实现了基于不同通道的通信。通道可被文本名称标识,并有一个本地(“源”) 的RPMsg 地址和一个远程(“目的”) 的RPMsg 地址。

在远程处理器端(MP157 则为M4 核),也必须使用RPMSG 框架。RPMSG 框架的实现存在几种解决方案,ST 建议使用OpenAMP 方案,并在SDK 中给出了示例。

Github OpenAMP 框架.

简单来说,MP157 的A7 核与M4 核,通过一个标准的RPMsg 框架来建立起联系,完成数据传递。

第十八节 多核异构核间通信–ipcc

具体原理可以参考:

RPMsg-Messaging-Protocol .
RPMsg-Communication-Flow .

Linux 内核源码目录给出的rpmsg client 的示例代码位置如下:

samples/rpmsg/rpmsg_client_sample.c

rpmsg 框架Linux 内核驱动源码位于:

drivers/rpmsg

ST 官方参考资料:

https://wiki.stmicroelectronics.cn/stm32mpu/wiki/Linux_remoteproc_framework_overview

Mailbox framework

此小节为大家简述有关Linux 邮箱框架的内容。邮箱框架涉及异构多核系统的处理器间通信。

此框架的结构如下图:

第十八节 多核异构核间通信–ipcc

邮箱框架被用于内核间进行消息或信号的交换,常用于主机和协处理器间。邮箱由以下模块组成:

  • 一个邮箱控制器(mailbox controller),依赖于硬件平台实现,比如MP157 的IPCC 外设:
    – 它负责配置和处理来自IPCC 外围设备的IRQ。
    – 它为邮箱客户端提供了通用API。

  • 一个邮箱客户端(mailbox client),负责发送或接收消息。

关于此框架的权威描述,在内核文档中的如下目录:

Documentation/mailbox.txt

一般而言mailbox controller 和client 都由芯片厂商来负责实现,因为这依赖于外设。我们更常关注的,则是mailbox client 的创建和使用。

ST 实现的mailbox client 代码位置如下:

drivers/remoteproc/stm32_rproc.c

在内核中还给出了一份mailbox client 的示例驱动代码,代码通过debugfs 子系统,将mailbox 的操作暴露给了用户空间,用户可以直接通过debugfs 来使用mailbox,进行消息在不同内核中的传递。

mailbox 框架的设备树描述可参考内核源码文档:

Documentation/devicetree/bindings/mailbox/mailbox.txt

一个简单的mailbox client 设备树节点,可以参考内核源码目录:

Documentation/devicetree/bindings/mailbox/sti-mailbox.txt

内核源码目录给出的mailbox client 的示例代码位置如下:

drivers/mailbox/mailbox-test.c

ST 官方参考资料:

https://wiki.stmicroelectronics.cn/stm32mpu/wiki/Linux_Mailbox_framework_overview

框架小结

前面介绍了三个框架,它们并不是独立工作的,而是相互协调的,彼此关联。我们可以通过两张图来查看它们之间的关系。

以RemoteProc 框架为主视角出发:

第十八节 多核异构核间通信–ipcc

可以理清三个框架的关系,RemoteProc 可以说是骨架,关联到了RPMsg 框架、Mailbox 框架。

设备树插件描述

IPCC 设备树节点

设备树节点位于arch/arm/boot/dts/stm32mp157c.dtsi

列表1: IPCC 设备树节点

ipcc: mailbox@4c001000 {
	compatible = "st,stm32mp1-ipcc";
	#mbox-cells = <1>;
	reg = <0x4c001000 0x400>;
	st,proc-id = <0>;
	interrupts-extended =
		<&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
		<&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
		<&exti 61 1>;
	interrupt-names = "rx", "tx", "wakeup";
	clocks = <&rcc IPCC>;
	wakeup-source;
	power-domains = <&pd_core>;
	status = "disabled";
};

使用节点位于arch/arm/boot/dts/stm32mp157a-basic.dts

列表2: 使用IPCC 设备树节点

&ipcc {
	status = "okay";
};

设备树中的compatible =“st,stm32mp1-ipcc”属性,会匹配到drivers/mailbox/stm32-ipcc.c 驱动程序,驱动程序中会创建一个mbox controller。

A7<–>M4 rproc 设备树节点

设备树节点位于arch/arm/boot/dts/stm32mp157c.dtsi

列表3: rproc 设备树节点

m4_rproc: m4@0 {
	compatible = "st,stm32mp1-rproc";
	#address-cells = <1>;
	#size-cells = <1>;

	ranges = <0x00000000 0x38000000 0x10000>,
			<0x30000000 0x30000000 0x60000>,
			<0x10000000 0x10000000 0x60000>;
	resets = <&rcc MCU_R>;
	reset-names = "mcu_rst";
	st,syscfg-pdds = <&pwr 0x014 0x1>;
	st,syscfg-holdboot = <&rcc 0x10C 0x1>;
	st,syscfg-tz = <&rcc 0x000 0x1>;
	st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
	status = "disabled";

	m4_system_resources {
		compatible = "rproc-srm-core";
		status = "disabled";
	};
};

使用节点位于arch/arm/boot/dts/stm32mp157a-basic.dts

列表4: 使用rproc 设备树节点

&m4_rproc {
	memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
				<&vdev0vring1>, <&vdev0buffer>;
	mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
	mbox-names = "vq0", "vq1", "shutdown";
	interrupt-parent = <&exti>;
	interrupts = <68 1>;
	interrupt-names = "wdg";
	wakeup-source;
	recovery;
	status = "okay";
};

设备树中的compatible = “st,stm32mp1-rproc” 属性, 会匹配到drivers/remoteproc/stm32_rproc.c 驱动程序,驱动程序中会创建一个mbox client,并基于RemoteProc、RPMsg框架与mbox client 进行关联。

实验代码简述

这里我们就简单讲解一下M4 核端的代码和一些概念,更详细的内容则需大家自己研究了。

rpmsg 框架下有通信端点的概念,数据在两个端点间传输。端点间的数据传输是rpmsg 框架下数据传输最原始的形式,我们可以在原始的数据传输形式上再做一层封装,抽象出一些特定类型的设备。

每个端点注册的底层实现,就是一个内核设备的注册(使用的是平台总线模型),故注册的端点设备,可以利用到驱动的Probe 功能(具体实现详见drivers/rpmsg/rpmsg_core.c 300 行后内容)。

在M4 端,通过调用openamp 库中的OPENAMP_create_endpoint 函数,并在调用时指定参数name(即为设备名称),即可在内核中注册一个对应的rpmsg 框架平台设备,该设备最终可以通过name(设备名称)来匹配到相应的A7 端内核驱动:

第十八节 多核异构核间通信–ipcc

所以Linux rpmsg 框架下使用平台总线模型与端点通讯的方式结合,给一些需要有特殊操作的自定设备,提供了支持的可能。比如异构间的通讯,可以封装成串口通讯模型。

在我们提供的M4 内核固件的代码中,注册了两种Linux 内核自带的rpmsg 框架下,原生支持的设备模型,这两种设备类型是rpmsg-tty-channel、rpmsg-client-sample:

  • rpmsg-tty-channel:tty 终端设备,对应内核驱动源码drivers/rpmsg/rpmsg_tty.c,此
    驱动模块默认被编译进内核。
  • rpmsg-client-sample:框架原生的通讯方式测试设备(放在内核里作为演示该框架的Demo提供的),对应内核驱动源码samples/rpmsg/rpmsg_client_sample.c,此驱动默认被编译成模块,并放置在文件系统/lib/modules/4.19.94-stm-r1/kernel/samples/rpmsg/rpmsg_client_sample.ko 中,当设备与驱动发生匹配时,系统会
    自动insmod 该驱动模块。
  • 还有一种字符设备模型,rpmsg_chrdev,源码位于drivers/rpmsg/rpmsg_char.c ,我
    们的代码中未实验,可自行研究。

在M4 核的代码中,还初始化了usart3 作为M4 内核的Log 输出串口,我们可以通过串口模块接入开发板上的usart3,来查看M4 内核输出的Log。最终工程代码会被用于生成ELF 固件,ELF固件即为程序,会运行在MP157 的M4 内核上。

综上,通过原生的rpmsg 框架设备、/dev/ttyRPMSGx 节点以及M4 内核使用的usart3 资源,我们就可以进行简单的实验了。本实验的代码也比较简单,这里就讲解这么多。

实验准备

由于多核异构的框架是与处理器的架构紧密联系在一起的,所以一般这些框架驱动会由芯片厂商为我们提供好。野火MP157 开发板默认开启了这些驱动支持,并且开启了对应的设备树,我们直接进行使用就可以了。

在前面我们提到了,M4 内核要与A7 内核通讯需要共用一个框架,那么M4 内核的运行的程序里,就需要有对应的框架代码,这个为大家提供的工程中已经包含。最终我们将代码生成的ELF固件,通过A7 内核的remoteproc 子系统加载到M4 内核上,即可做好前期的准备工作。

生成ELF 固件的工程代码位于\linux_driver\framework_ipcc\STM32Cube_FW_MP1_V1.2.0\Projects\STM32MP157C-EV1\Applications\OpenAMP\OpenAMP_raw 目录下,感兴趣可自行研究,工程可用MDK 或CubeIDE 打开(在工程目录中由对应文件夹)。


重要: 在M4 核的代码中,还初始化了usart3,实验前请务必将usart3 的设备树插件关闭。


实验操作

M4 核的固件我们已经成功编译并放在了/linux_driver/framework_ipcc 目录下,我们将M4 核的固件OpenAMP_raw_CM4.elf 上传至Linux 文件系统的/lib/firmware/ 目录。此目录存放着Linux 系统中会使用到的各种固件。

执行如下命令指定M4 内核加载的固件,默认在root 用户下操作:

# 进入remoteproc 子系统目录
cd /sys/class/remoteproc/remoteproc0
# 导入M4 内核固件名称
echo OpenAMP_raw_CM4.elf > firmware

在同一目录下,执行如下命令可启动停止M4 内核:

# 启动M4 内核
echo start > state
# 停止M4 内核
echo stop > state

启动M4 内核后信息如下:

第十八节 多核异构核间通信–ipcc

M4 内核加载固件并启动后,在串口终端中打印出了一些信息,我们通过串口模块接入usart3引脚,再打开串口调试助手设置波特率为115200,可以看到M4 固件初始化的usart3 作为串口printf 出来的信息,为[INFO ]M4 send to A7 : hello world! ,并且A7 端的驱动也打印出了rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: incomingmsg 1 (src: 0x0) 说明M4 核及A7 核驱动正常工作了。

此外, 输入lsmod, 我们还可以看到演示设备创建后, 对应被动态加载的驱动模块,rpmsg_client_sample :

第十八节 多核异构核间通信–ipcc

下面,我们进行第二个设备测试,通过前面现象中的LOG,我们可以看到被枚举出的tty 设备节点/dev/ttyRPMSG0 节点,我们就通过该节点测试tty 设备的功能,输入如下命令:

echo "hello M4 core , i'm A7!" > /dev/ttyRPMSG0

实验现象如下所示:

第十八节 多核异构核间通信–ipcc

上图为A7 通过虚拟的tty 终端设备,转发到M4 内核的消息内容,最终通过M4 核固件的串口Log 功能打印出来对应信息。

自此,所有实验结束。


参考资料:嵌入式Linux 驱动开发实战指南-基于STM32MP1 系列文章来源地址https://www.toymoban.com/news/detail-494564.html

到了这里,关于第十八节 多核异构核间通信–ipcc的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详细教程 - 进阶版 鸿蒙harmonyOS应用 第十八节——鸿蒙OS应用性能优化指南

    性能优化是提升鸿蒙OS应用质量的重要手段。优化的角度包括加载速度、CPU使用率、内存占用、电量消耗、网络流量等多个方面。 本文将通俗解释性能表现的影响因素,并结合实例提供有效的检测分析方法与优化策略建议,帮助开发者系统地提升应用性能与用户体验。 2.1 加载时

    2024年01月16日
    浏览(41)
  • 【第十八节:微信小程序 常用功能-登录】微信小程序入门,以思维导图的方式展开18

    若图片看不清,可私信给五木大大要高清大图哈。      效果               wxml页面         view class=\\\"login-container\\\"nn    view class=\\\"login\\\" wx:if=\\\"{{ !logged }}\\\"nn        view class=\\\"app-info\\\"nn            image class=\\\"app-logo\\\" src=\\\"../../images/logo.png\\\" /nn            text class

    2024年01月17日
    浏览(46)
  • 同构多核架构(SMP)和异构多核架构(AMP)

    同构多核架构(SMP)和异构多核架构(AMP)主要在两个角度上有区别: 处理器架构:在同构多核架构中,系统中的处理器在架构上是相同的,而异构多核架构则包含不同架构的处理器。 运行模式:在同构多核架构中,多个核心运行一个操作系统,该操作系统同等的管理多个

    2024年02月14日
    浏览(30)
  • 【资料分享】基于NXP i.MX 8M Plus的异构多核核心板规格书

      创龙科技SOM-TLIMX8MP是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 + 单核ARM Cortex-M7异构多核处理器设计的高端工业核心板,ARM Cortex-A53(64-bit)主处理单元主频高达1.6GHz,ARM Cortex-M7实时处理单元主频高达800MHz。处理器采用14nm最新工艺,内置2.3TOPS算力NPU神经网络处理单元、双路独立

    2024年02月10日
    浏览(29)
  • 第十八章 Unity 协程

    我们知道脚本都是继承自MonoBehaviour类,而其中的Update方法里面放置了大部分的游戏逻辑处理代码。Update方法是游戏循环的每一帧都去执行,这就要求我们的代码“无时无刻”不在处理所有的可能发生的情况,并做出相应的处理。如果我们想要完成“一段时间”的逻辑代码,例

    2024年02月05日
    浏览(32)
  • 每日三问-前端(第十八期)

    先来回顾一下上期的问题及答案: 2023年6月7日 1. 组件间通信是指在 Vue.js 中,不同组件之间进行数据或事件的传递和交互的过程。常用的组件通信方式包括: 父子组件通信:通过 props 属性将数据从父组件传递给子组件,子组件通过监听 props 的变化来获取父组件传递的数据。

    2024年02月08日
    浏览(27)
  • 第十八章 ObjectScript - 使用例程

    可以将例程视为 ObjectScript 程序。例程可以从头开始编写,也可以在编译类时自动生成。 在 ObjectScript 例程中,标签定义以下代码单元之一的起点: Procedures 过程(可选地返回一个值)。过程中定义的变量是该过程私有的,这意味着它们不可用于其他代码。对于函数和子例程

    2024年02月10日
    浏览(34)
  • C++学习第十八天(函数模板)

    模板 1.1 模板的概念 模板就是 建立通用的模具,大大提高复用性,特点:模板不可以直接使用,他只是一个框架;模板的通用并不是万能的。 1.2 函数模板语法 函数模板的作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体定制,用一个虚拟的类型来代表。

    2024年02月13日
    浏览(26)
  • 第十八课、Qt 下载、安装与配置

    功能描述:介绍了 Qt 的下载、安装和配置的全部过程,并对关键页面选项进行了详细说明 Qt 官方下载地址:https://www.qt.io/zh-cn/download https://download.qt.io/ https://download.qt.io/ https://www.qt.io/zh-cn/download进入下载地址后的页面如下图所示:  对目录结构的说明 snapshots         预览

    2024年02月09日
    浏览(45)
  • 《TCP IP网络编程》第十八章

    线程背景:         第 10 章介绍了多进程服务端的实现方法。多进程模型与 select 和 epoll 相比的确有自身的优点,但同时也有问题。如前所述, 创建(复制)进程的工作本身会给操作系统带来相当沉重的负担。而且,每个进程都具有独立的内存空间,所以进程间通信的实

    2024年02月12日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包