2020-10-24

IPC通信

  1. IPC的基本概念
    处理器间通信(IPC)提供了一个与处理器无关的API,可用于多处理器环境中处理器之间的通信(内核间)、与同一处理器上的其他线程的通信(进程间)和与外围设备(设备间)的通信。API支持消息传递、流和链接列表。IPC可用于与以下方面进行通信:
    同一处理器上的其他线程
    运行SYS/BIOS的其他处理器上的线程
    运行HLOS的其他处理器上的线程(例如Linux、QNX、Android)
    2020-10-24

处理器间/处理器内部通信(IPC)是一种产品,用于在多处理器环境中实现处理器之间的通信。IPC的特点包括消息传递、多处理器门、共享内存原语等.
IPC被设计用于与运行SYS/BIOS应用程序的处理器一起使用。这通常是ARM或DSP。IPC包括支持高级操作系统(HLOS),如Linux,以及SYS/BIOS RTOS。在HLOS环境中支持的IPC特征的宽度被减少,以便简化产品。
IPC通常分布并安装在更大的SDK中。在这些情况下,不需要安装。
在SDK之外,IPC可以在这里下载,并作为zip文件发布。要安装,只需提取文件即可…这将在目录中提取IPC产品及其产品名称和版本信息(例如。c:/ti/ipc_)。
IPC产品提供多个处理器之间的软件连接。每个处理器可以运行HLOS(例如
Linux、QNX)或RTOS(例如,SYS/BIOS)。IPC是一个开源的项目, 你可以在这里找到它http://git.ti.com/ipc/ipcdev.

处理器SDKInstaller(ti-processor-sdk-linux-[platformName]-evm-xx.xx-Linux-x86-Install.bin)将安装必要的组件,以便在TI微处理器上启动您的开发。SDK由MatrixAppLauncher起始点应用程序的源代码、一个开发文件系统、一个目标文件系统、示例应用程序、工具链和板支持包、易用性脚本和文档组成。处理器SDK现在包括ARM GCC工具链。处理器SDK是根据特定的Linux发行版名称和版本Ubuntu16.04和18.04构建和测试的。注意,这并不妨碍用户在其他Linux发行版上安装SDK。
最后一步是下载并安装处理器-SDKRTOS。要获取本软件的最新版本,请参见设备的“软件产品”页。
示例的二进制图像位于主机和各个内核的相应目录中。可以通过使用通过JTAG的CCS加载和运行二进制文件来运行示例。
本文面向在Cortex A 15上运行Linux的AM57xx用户。其目标是帮助用户了解如何获得AM57xx的DSP(C66x)和IPU (Cortex M4)子系统的权限。
AM572x设备有两个IPU (IPUSS),每个子系统有两个核心。IPU 2被用作多媒体应用程序中的控制器,所以如果您在运行处理器SDK Linux,那么IPU 2很可能已经加载了固件。但是,IPU 1是开放的,用于通用编程来卸载ARM任务。
这个任务有很多方面:构建、加载、调试、MMU、内存共享等等。本文打算采取渐进的步骤来理解所有这些部分。

  1. IPC for AM57xx
    AM57xxSOC“S”有多个处理器内核-CortexA15、C66xDSP和ARMM4内核。A15通常运行诸如Linux/QNX/Android之类的HLOS,而RemoteCore(DSP)S和M4)运行RTOS。在正常操作中,引导加载器(U-boot/SPL)引导并加载带有HLOS的A15。A15启动DSP和M4内核。
    2020-10-24

在这个序列中,电源复位与远程设备(即DSP和M4)之间的间隔取决于HLOS初始化时间。

下图说明ARMLinux内核的远程proc/rpMsg驱动程序如何与运行RTOS的从处理器(如DSP、IPU等)上的IPC驱动程序通信。
2020-10-24

为了在从内核上设置IPC,我们在IPC包中提供了一些可从ARMLinux运行的预先构建的示例。接下来的章节描述了如何构建和运行此示例,并将其用作此工作的起点。

CMEM
To view the allocation at run-time:
[email protected]:~# cat /proc/cmem

这表明我们在0xA0000000的物理基地址上定义了一个CMEM块,其总大小为0xc 000000(192 MB)。此块包含由1个缓冲区组成的缓冲池。池中的每个缓冲区(本例中只有一个)被定义为大小为0xc000000(192 MB)。

更改DSP内存映射
首先,重要的是要理解,存在一对位于DSP子系统和L3互连之间的存储器管理单元(MMUS)。其中一个MMUUS用于DSP核心,另一个是针对其本地EDMA。它们都用于将虚拟地址(即,由DSP子系统观看的地址)转换为物理地址(即,从L3互连观看的地址)的相同目的。

DSP物理地址DSP代码/数据实际驻留的物理位置由CMA carveouts进行定义。要更改此位置,您必须更改香芹的定义。在LinuxDTS文件中定义了DSP carveouts。例如对于AM57xxEVM:

您可以同时更改大小和位置。小心不要重叠任何其他carveouts!

此外,当您更改分出位置时,必须对资源表进行相应的更改。首先,如果您正在进行内存更改,则需要一个自定义资源表。资源表是一个大型结构,是物理内存和虚拟内存之间的“桥梁”。此结构用于配置位于DSP子系统前面的MMU。IPCResourceCustomTable一文中提供了详细的信息。
创建自定义资源表后,必须将phys_mem_IPC_VRING的地址更新为与相应的CMA相同的基址。

DSP虚拟地址
这些地址是DSP子系统看到的地址,也就是链接器命令文件中的地址,等等。您必须确保节的大小与资源表中的相应定义一致。您应该创建自己的资源表,以修改内存映射。这是在页IPC资源自定义表中描述的。您可以查看IPC中的现有资源表:
换句话说,由于我们使用了身份映射,所以可以在它们的物理地址处访问外围设备。
运行时检查DSPIOMMU页面表
可以使用以下命令转储DSPIOMMU页表:
一般来说,MMU 0和MMU 1的编程方式是相同的,所以您只需要查看其中一个或另一个就可以理解给定DSP的映射。
“da”(“设备地址”)列反映虚拟地址。它是从索引中派生的,即在页表中不存在“da”寄存器或字段。地址空间中的每个MB映射到表中的条目。显示“da”,使其易于找到感兴趣的虚拟地址。
“pte”(“页表项”)列可以根据上述表20-4进行解码。例如:

1: 0x4a000000 0x4a040002
0x4a040002向我们表明,它是一个基地址0x4A000000的超值。这给了我们一个16 MB的内存页面。注意后面重复的条目。这是MMU的要求。
为了充分理解CortexM4IPU子系统的内存映射,认识到存在两种不同/独立的内存转换级别很有帮助。以下是TRM中的片段以说明:

CortexM4 IPU物理地址
M4代码/数据实际所在的物理位置由CMA carveout进行定义。要更改此位置,您必须更改香芹的定义。M4 carveout在LinuxDTS文件中定义。例如对于AM57xxEVM:

此外,当您更改 carveout的位置时,必须对资源表进行相应的更改。首先,如果您正在进行内存更改,您需要自定义资源表。资源表是一个大型结构,是物理内存和虚拟内存之间的“桥”。此结构用于配置IPUxMMU(不是UniCacheMMU)。在文章IPC资源定制表中提供了详细信息。创建自定义资源表时,必须将physmemIPCvring的地址更新为与相应CMA相同的基地址。

CortexM4IPU虚拟地址
UniCacheMMU,
UniCacheMMU最接近CortexM4。它提供了一级地址翻译。UniCacheMMU实际上是由CortexM4“自行编程”的。UniCacheMMU也被称为属性MMU(AMMU)。有固定数量的小、中和大页面。以下是显示一些关键映射的片段:

这3页是“身份”映射,对关联的地址范围执行请求通过。这些中间地址在下一级翻译(IOMMU)中被映射到它们的物理地址。用于代码和数据的AMMU范围需要是标识映射,因为否则RemoteProc加载器将无法与相关联的IOMMU映射从ELF文件中匹配这些部分。这些映射应足以满足任何应用,即无需调整这些映射。修改的更可能区域是下一节中的资源表。AMMU映射主要用于理解关于CortexM4存储器映射的完整图像。

IOMMU
IOMMU位于离L3互连最近的地方。它获取来自AmMu的中间地址输出,并将其转换为L3互连所使用的物理地址。IOMMU是由ARM基于相关资源表编写的。如果您正在计划任何内存更改,那么您将需要创建一个自定义资源表,如页面IPC资源自定义表中所描述的那样。

来自资源表的3个条目都来自相关联的IPUCMA池(即,如由类型_CARSOUT所指示的)。第二参数表示虚拟地址(即对IOMMU的输入地址)。这些地址必须与AMMU映射以及链接器命令文件一致。来自IPC的EX02_MessageQ示例在文件示例/Dra7xx_Linux_ELF/EX02_MessageQ/共享/config.bld.中定义了这些内存部分您可以使用以下命令卸载IPUIOMMU页面表:

示例:从IPU访问UART5在本例中,假定引导加载程序中已经设置了PIN-MUXED。如果不是这样,你就得在这做。UART5模块需要通过CM_L4PER_UART5_CLKCTRL寄存器使能。这位于物理地址0x4A009870。因此,从M4,我们将在虚拟地址0x6A009870上对该寄存器进行编程。将值2写入此寄存器将启用外围设备。在完成上一个步骤后,UART5寄存器将变为可访问的。通常UART5可在物理基础地址0x48066000处访问。这将相应地从IPU在0x68066000处访问。
默认情况下,IPU和DSP自动空闲。这可以防止您能够使用JTAG连接到设备,也无法通过devme 2访问本地内存。在sysfs中有一些选项是必要的,以强制这些子系统运行,有时这是开发和调试目的所需要的。这些操作需要一些源自设备树(dra7.dtsi)的硬编码设备名称:
2020-10-24

要将这些系统FS名称映射到关联的RemoteProc条目,您可以运行以下命令:
[email protected]:~# ls -l /sys/kernel/debug/remoteproc/
[email protected]:~# cat /sys/kernel/debug/remoteproc/remoteproc*/name
命令的结果将是一对一的映射。例如,58820000.ipu对应于remoteproc0。
类似地,要查看每个核心的电源状态:
[email protected]:~# cat /sys/class/remoteproc/remoteproc*/state
状态可以挂起、运行、脱机等。只有当状态“运行”时,才能附加JTAG。如果它显示为“暂停”,则必须强制它运行。例如,假设DSP 0被“挂起”。可以运行以下命令强制执行:
[email protected]:~# echo on > /sys/bus/platform/devices/40800000.dsp/power/control
任何核心都是如此,但是用上面图表中关联的系统FS名称替换40800000.dsp。

  1. 将IPC添加到从内核上的现有TI-RTOS
    应用程序将IPC添加到DSP上现有的TIRTOS应用程序上
    人们想要做的一个常见的事情是采用现有的DSP应用程序,并将IPC添加到它。当从DSP迁移到带有ARM+DSP的异构SoC时,这很常见。这是本部分的重点。为了描述这个过程,我们需要一个示例测试用例来处理。为此,我们将使用GPIO_LEDBLINK_EVMAM572X_C66XExample项目示例,该示例是PDK的一部分(作为处理器SDKRTOS的一部分安装)。您可以在C:TiPDK_AM57xx_1_0_4PackageMyExample_GPIO_LEDBLINK_EVMAM572X_C66XExample项目中找到它。此示例使用SYS/BIOS并将用户0闪烁在AM572XGPEVM上,它在EVM丝印屏幕上标记为D4,恰好位于蓝色重置按钮的右侧。

有几个步骤进行整个过程工作,每个步骤将在下面的章节中进行描述,并使用代码编写器Studio(CCS)在EVM上运行“开箱即用”LED闪烁示例,从IPC软件包获取EX02_消息示例,并将其转换为CCS项目。建立它并修改Linux启动代码以使用此新映像。这只是一个明智的检查步骤,以确保我们可以在CCS中构建IPC示例,并让它们在EVM启动时运行。在CCS中,进行开箱即用的LED示例的克隆,并将其重命名为“S”示例的IPC版本。然后,使用EX02_MessageQ示例作为参考,在IPC块中添加到LED示例。从CCS构建然后将其添加到Linux固件文件夹中。

将IPC添加到LED闪烁示例第一步是克隆出开箱即用的LED闪烁CCS项目,并将其重命名为使用IPC表示它。执行此操作的最简单方法是使用CCS。下面是步骤……在“编辑”(Edit)透视图中,进入“项目浏览器”(ProjectExplorer)窗口,右键单击GPIO_LEDBLINK_EVMAN572XC66XExampleProject项目,然后从弹出式菜单中选择“复制”(Copy)。Maske确定项目不是关闭状态。Rick单击项目浏览器窗口的“In”和“空”区域,然后选择“过去”。弹出对话框,修改名称以表示它使用IPC。一个好的名称是GPIO_LEDBLINK_EVMAM572XC66XExamplejec_with_IPC。

右键单击GPIO_LedBlink_evmAM572x c66xExampleProjec_With_IPC项目并在左侧窗格中选择Properties,单击CCS General。在右侧,单击RTSC选项卡上的XDCtools版本:在产品和存储库列表中选择3.32.0.06_core,检查以下.IPC 3.43.2.04 SYS/BIOS 6.45.1.29 am57xx PDK 1.0.4 for Target,选择ti.Target ts.elf.C66作为平台,选择ti.platforms.evmDRA7XX,在平台被选中后,编辑其名称BueHand并追加:dsp 1到末尾。在此之后,应该是ti.platforms.evmDRA7XX:dsp 1,然后将构建配置文件设置为DEBUG。按下OK按钮。现在,我们希望将EX02_MessageQIPC示例的配置和源文件复制到我们的项目中。IPC示例位于C:TiIPC_3_43_02_04ExampleDra7xx_Linux_ELFEX02_MessageQ。要将文件复制到CCS项目中,您可以简单地选择Windows资源管理器中所需的文件,然后将它们拖放到CCS中的项目中。将这些文件复制到CCS项目中……

人们想要做的一件常见的事情就是使用一个现有的IPU应用程序,它可以控制串行或控制接口,并将IPC添加到其中,这样固件就可以从ARM加载。当从唯一的IPU解决方案迁移到具有MPUSS(ARM)和IPUSS的异构SoC时,这种情况很常见。这是本节的重点。为了描述这个过程,我们需要一个TI RTOS测试用例来处理。为此,我们将使用属于PDK(安装为处理器SDKRTOS的一部分)的UART_BasicExgrom_evmAM572x_m4ExampleProject示例。此示例使用TI RTOS并在AM572xGP EVM上使用UART 3端口执行串行IO操作,它在EVM屏幕上被标记为SerialDebug。

为使整个过程工作采取了若干步骤,每个步骤将在下面的章节中进行描述使用代码ComposerStudio(CCS)构建并运行EVM上的开箱即用UARTM4示例从IPC软件包构建并运行EX02_MessageQ示例,并将其转换为CCS项目。建立它并修改Linux启动代码以使用此新映像。这只是一个明智的检查步骤,以确保我们可以在CCS中构建IPC示例,并让它们在EVM启动时运行。在CCS中,进行开箱即用UARTM4示例的克隆,并将其重命名为该示例的IPC版本。然后使用EX02_MessageQ示例作为参考,在IPC块中添加到UART示例代码。从CCS构建然后将其添加到Linux固件文件夹中。

Linux内核启用所有配置所需的SOCHW模块。适当的驱动程序配置所需的时钟并初始化HW寄存器。对于所有未使用的IP,没有配置时钟。 使用设备树在内核中禁用uart3节点。此外,这限制了内核将这些IP放到睡眠模式。
在每个IPU 1和IPU 2子系统中都有两个MMU。L1 MMU称为IPU_UNICACHE_MMU或AmMu和L2 MMU。关于如何在IPC-Remoteproc中配置这一点的说明已在Changing_Cortex_M4_ IPU _Memory_Map一节中进行了描述。IPC处理L1和L2 MMU不同于PDK驱动程序示例如何使用这些MMU设置内存访问,用户在集成组件时需要管理这些MMU。这种差异突出如下:

PDK示例将地址(0x4X000000)用于外围寄存器,并使用以下MMU设置L2 MMU使用默认1:1映射Ammu Configuration将物理0x4X000000访问转换为逻辑0x4X000000
IPC远程proc ARM M4要求IPU使用逻辑地址(0x6X000000),并使用以下MMU设置L2 MMU,使MMU将0x6X000000访问地址转换为地址0x4X000000(配置为1:1映射和0x6X000000)

因此,在将IPC与PDK驱动程序集成之后,建议使用别名地址来访问外围设备和PRCM寄存器。这需要更改PDK驱动程序和应用程序代码中使用的地址。然后对IPU应用程序源代码进行以下更改:
将UART_SOC.C文件添加到项目中,并修改UART_HATTRS中所有IPUUART寄存器实例的基本地址,以使用别名地址:

添加自定义SOC配置还意味着您应该使用通用的UART驱动程序,而不是内置在SOC设置中的驱动程序。要执行此注释,请在.cfg中使用以下行:

在应用代码中也有一个实例,在该实例中,我们将指针添加到需要改变如下的PRCM寄存器。现在,您已经准备好构建固件。构建.out之后,将扩展名更改为.xem 4,并将其复制到用于加载M4固件的文件系统中的位置。

  1. IPC模块的子系统
    IPC模块初始化IPC的各个子系统,并同步多个处理器。
    MessageQ模块支持可变长度消息的结构化发送和接收。
    ListMP模块是一个基于链表的模块,旨在提供不同处理器之间的通信方式。它使用共享内存为多个处理器提供共享、传递或存储数据缓冲区、消息或状态信息的方法。
    HeapMP模块提供3种类型的内存管理、固定大小的缓冲区、多个不同的固定大小缓冲区和可变大小的缓冲区.
    GateMP模块通过其实例执行本地和远程上下文保护。通知模块通过硬件中断管理软件中断的复用/解复用。
    SharedRegion模块设计用于多处理器环境中,其中存在跨不同处理器共享和访问的内存区域。列表模块支持创建双链接的对象列表,MultiProc模块在多处理器环境中将处理器ID管理集中到一个模块中。
    NameServerModule管理本地名称/值对,这使得应用程序和其他模块能够基于名称来调整和检索值。