基于STM32MP157的异核间通信(续二)

前面讨论了STM32MP157异核间通信的实例及其基本原理,接下来看一下在A7端Linux下的设备树里和M4端的链接脚本里都是如何配置的。

远程协处理器的资源配置由3部分组成,分别是:外围设备、物理内存和资源表。外围设备的配置通过设备树(stm32mp157c.dtsi)下的m4_system_resources节点进行(一般通过stm32mp157c-m4-srm.dtsi文件进行追加);物理内存(SRAM1~SRAM4)的配置通过设备树(stm32mp157a-basic.dts)下的reserved-memory节点进行;资源表的配置通过OpenAMP库的rsc_table.h、rsc_table.c文件在IDE中进行。以上设备树文件是以野火提供的内核源码为例的,若是其他平台可能上述节点所在的设备树文件名称不一样,但节点名称是固定的,可以在源码dts目录下通过执行命令“grep -nr 节点名称”来查找具体所在的设备树文件。

先来看外围设备的配置,下面是stm32mp157c-m4-srm.dtsi文件中m4_system_resources节点的配置信息。

&m4_rproc {
    m4_system_resources {
        #address-cells = <1>;
        #size-cells = <0>;

        m4_timers2: timer@40000000 {
            compatible = "rproc-srm-dev";
            reg = <0x40000000>;
            clocks = <&rcc TIM2_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers3: timer@40001000 {
            compatible = "rproc-srm-dev";
            reg = <0x40001000>;
            clocks = <&rcc TIM3_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers4: timer@40002000 {
            compatible = "rproc-srm-dev";
            reg = <0x40002000>;
            clocks = <&rcc TIM4_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers5: timer@40003000 {
            compatible = "rproc-srm-dev";
            reg = <0x40003000>;
            clocks = <&rcc TIM5_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers6: timer@40004000 {
            compatible = "rproc-srm-dev";
            reg = <0x40004000>;
            clocks = <&rcc TIM6_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers7: timer@40005000 {
            compatible = "rproc-srm-dev";
            reg = <0x40005000>;
            clocks = <&rcc TIM7_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers12: timer@40006000 {
            compatible = "rproc-srm-dev";
            reg = <0x40006000>;
            clocks = <&rcc TIM12_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers13: timer@40007000 {
            compatible = "rproc-srm-dev";
            reg = <0x40007000>;
            clocks = <&rcc TIM13_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers14: timer@40008000 {
            compatible = "rproc-srm-dev";
            reg = <0x40008000>;
            clocks = <&rcc TIM14_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_lptimer1: timer@40009000 {
            compatible = "rproc-srm-dev";
            reg = <0x40009000>;
            clocks = <&rcc LPTIM1_K>;
            clock-names = "mux";
            status = "disabled";
        };
        m4_spi2: spi@4000b000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000b000>;
            clocks = <&rcc SPI2_K>;
            status = "disabled";
        };
        m4_i2s2: audio-controller@4000b000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000b000>;
            status = "disabled";
        };
        m4_spi3: spi@4000c000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000c000>;
            clocks = <&rcc SPI3_K>;
            status = "disabled";
        };
        m4_i2s3: audio-controller@4000c000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000c000>;
            status = "disabled";
        };
        m4_spdifrx: audio-controller@4000d000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000d000>;
            clocks = <&rcc SPDIF_K>;
            clock-names = "kclk";
            status = "disabled";
        };
        m4_usart2: serial@4000e000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000e000>;
            interrupt-parent = <&exti>;
            interrupts = <27 1>;
            clocks = <&rcc USART2_K>;
            status = "disabled";
        };
        m4_usart3: serial@4000f000 {
            compatible = "rproc-srm-dev";
            reg = <0x4000f000>;
            interrupt-parent = <&exti>;
            interrupts = <28 1>;
            clocks = <&rcc USART3_K>;
            status = "disabled";
        };
        m4_uart4: serial@40010000 {
            compatible = "rproc-srm-dev";
            reg = <0x40010000>;
            interrupt-parent = <&exti>;
            interrupts = <30 1>;
            clocks = <&rcc UART4_K>;
            status = "disabled";
        };
        m4_uart5: serial@40011000 {
            compatible = "rproc-srm-dev";
            reg = <0x40011000>;
            interrupt-parent = <&exti>;
            interrupts = <31 1>;
            clocks = <&rcc UART5_K>;
            status = "disabled";
        };
        m4_i2c1: i2c@40012000 {
            compatible = "rproc-srm-dev";
            reg = <0x40012000>;
            interrupt-parent = <&exti>;
            interrupts = <21 1>;
            clocks = <&rcc I2C1_K>;
            status = "disabled";
        };
        m4_i2c2: i2c@40013000 {
            compatible = "rproc-srm-dev";
            reg = <0x40013000>;
            interrupt-parent = <&exti>;
            interrupts = <22 1>;
            clocks = <&rcc I2C2_K>;
            status = "disabled";
        };
        m4_i2c3: i2c@40014000 {
            compatible = "rproc-srm-dev";
            reg = <0x40014000>;
            interrupt-parent = <&exti>;
            interrupts = <23 1>;
            clocks = <&rcc I2C3_K>;
            status = "disabled";
        };
        m4_i2c5: i2c@40015000 {
            compatible = "rproc-srm-dev";
            reg = <0x40015000>;
            interrupt-parent = <&exti>;
            interrupts = <25 1>;
            clocks = <&rcc I2C5_K>;
            status = "disabled";
        };
        m4_cec: cec@40016000 {
            compatible = "rproc-srm-dev";
            reg = <0x40016000>;
            interrupt-parent = <&exti>;
            interrupts = <69 1>;
            clocks = <&rcc CEC_K>, <&rcc CK_LSE>;
            clock-names = "cec", "hdmi-cec";
            status = "disabled";
        };
        m4_dac: dac@40017000 {
            compatible = "rproc-srm-dev";
            reg = <0x40017000>;
            clocks = <&rcc DAC12>;
            clock-names = "pclk";
            status = "disabled";
        };
        m4_uart7: serial@40018000 {
            compatible = "rproc-srm-dev";
            reg = <0x40018000>;
            interrupt-parent = <&exti>;
            interrupts = <32 1>;
            clocks = <&rcc UART7_K>;
            status = "disabled";
        };
        m4_uart8: serial@40019000 {
            compatible = "rproc-srm-dev";
            reg = <0x40019000>;
            interrupt-parent = <&exti>;
            interrupts = <33 1>;
            clocks = <&rcc UART8_K>;
            status = "disabled";
        };
        m4_timers1: timer@44000000 {
            compatible = "rproc-srm-dev";
            reg = <0x44000000>;
            clocks = <&rcc TIM1_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers8: timer@44001000 {
            compatible = "rproc-srm-dev";
            reg = <0x44001000>;
            clocks = <&rcc TIM8_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_usart6: serial@44003000 {
            compatible = "rproc-srm-dev";
            reg = <0x44003000>;
            interrupt-parent = <&exti>;
            interrupts = <29 1>;
            clocks = <&rcc USART6_K>;
            status = "disabled";
        };
        m4_spi1: spi@44004000 {
            compatible = "rproc-srm-dev";
            reg = <0x44004000>;
            clocks = <&rcc SPI1_K>;
            status = "disabled";
        };
        m4_i2s1: audio-controller@44004000 {
            compatible = "rproc-srm-dev";
            reg = <0x44004000>;
            status = "disabled";
        };
        m4_spi4: spi@44005000 {
            compatible = "rproc-srm-dev";
            reg = <0x44005000>;
            clocks = <&rcc SPI4_K>;
            status = "disabled";
        };
        m4_timers15: timer@44006000 {
            compatible = "rproc-srm-dev";
            reg = <0x44006000>;
            clocks = <&rcc TIM15_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers16: timer@44007000 {
            compatible = "rproc-srm-dev";
            reg = <0x44007000>;
            clocks = <&rcc TIM16_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_timers17: timer@44008000 {
            compatible = "rproc-srm-dev";
            reg = <0x44008000>;
            clocks = <&rcc TIM17_K>;
            clock-names = "int";
            status = "disabled";
        };
        m4_spi5: spi@44009000 {
            compatible = "rproc-srm-dev";
            reg = <0x44009000>;
            clocks = <&rcc SPI5_K>;
            status = "disabled";
        };
        m4_sai1: sai@4400a000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400a000>;
            clocks = <&rcc SAI1_K>;
            clock-names = "sai_ck";
            status = "disabled";
        };
        m4_sai2: sai@4400b000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400b000>;
            clocks = <&rcc SAI2_K>;
            clock-names = "sai_ck";
            status = "disabled";
        };
        m4_sai3: sai@4400c000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400c000>;
            clocks = <&rcc SAI3_K>;
            clock-names = "sai_ck";
            status = "disabled";
        };
        m4_dfsdm: dfsdm@4400d000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400d000>;
            clocks = <&rcc DFSDM_K>;
            clock-names = "dfsdm";
            status = "disabled";
        };
        m4_m_can1: can@4400e000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400e000>, <0x44011000>;
            clocks = <&rcc FDCAN>, <&rcc FDCAN_K>;
            clock-names = "hclk", "cclk";
            status = "disabled";
        };
        m4_m_can2: can@4400f000 {
            compatible = "rproc-srm-dev";
            reg = <0x4400f000>, <0x44011000>;
            clocks = <&rcc FDCAN>, <&rcc FDCAN_K>;
            clock-names = "hclk", "cclk";
            status = "disabled";
        };
        m4_dma1: dma@48000000 {
            compatible = "rproc-srm-dev";
            reg = <0x48000000>;
            clocks = <&rcc DMA1>;
            status = "disabled";
        };
        m4_dma2: dma@48001000 {
            compatible = "rproc-srm-dev";
            reg = <0x48001000>;
            clocks = <&rcc DMA2>;
            status = "disabled";
        };
        m4_dmamux1: dma-router@48002000 {
            compatible = "rproc-srm-dev";
            reg = <0x48002000>;
            clocks = <&rcc DMAMUX>;
            status = "disabled";
        };
        m4_adc: adc@48003000 {
            compatible = "rproc-srm-dev";
            reg = <0x48003000>;
            clocks = <&rcc ADC12>, <&rcc ADC12_K>;
            clock-names = "bus", "adc";
            status = "disabled";
        };
        m4_sdmmc3: sdmmc@48004000 {
            compatible = "rproc-srm-dev";
            reg = <0x48004000>, <0x48005000>;
            clocks = <&rcc SDMMC3_K>;
            status = "disabled";
        };
        m4_usbotg_hs: usb-otg@49000000 {
            compatible = "rproc-srm-dev";
            reg = <0x49000000>;
            clocks = <&rcc USBO_K>;
            clock-names = "otg";
            status = "disabled";
        };
        m4_hash2: hash@4c002000 {
            compatible = "rproc-srm-dev";
            reg = <0x4c002000>;
            clocks = <&rcc HASH2>;
            status = "disabled";
        };
        m4_rng2: rng@4c003000 {
            compatible = "rproc-srm-dev";
            reg = <0x4c003000>;
            clocks = <&rcc RNG2_K>;
            status = "disabled";
        };
        m4_crc2: crc@4c004000 {
            compatible = "rproc-srm-dev";
            reg = <0x4c004000>;
            clocks = <&rcc CRC2>;
            status = "disabled";
        };
        m4_cryp2: cryp@4c005000 {
            compatible = "rproc-srm-dev";
            reg = <0x4c005000>;
            clocks = <&rcc CRYP2>;
            status = "disabled";
        };
        m4_dcmi: dcmi@4c006000 {
            compatible = "rproc-srm-dev";
            reg = <0x4c006000>;
            clocks = <&rcc DCMI>;
            clock-names = "mclk";
            status = "disabled";
        };
        m4_lptimer2: timer@50021000 {
            compatible = "rproc-srm-dev";
            reg = <0x50021000>;
            clocks = <&rcc LPTIM2_K>;
            clock-names = "mux";
            status = "disabled";
        };
        m4_lptimer3: timer@50022000 {
            compatible = "rproc-srm-dev";
            reg = <0x50022000>;
            clocks = <&rcc LPTIM3_K>;
            clock-names = "mux";
            status = "disabled";
        };
        m4_lptimer4: timer@50023000 {
            compatible = "rproc-srm-dev";
            reg = <0x50023000>;
            clocks = <&rcc LPTIM4_K>;
            clock-names = "mux";
            status = "disabled";
        };
        m4_lptimer5: timer@50024000 {
            compatible = "rproc-srm-dev";
            reg = <0x50024000>;
            clocks = <&rcc LPTIM5_K>;
            clock-names = "mux";
            status = "disabled";
        };
        m4_sai4: sai@50027000 {
            compatible = "rproc-srm-dev";
            reg = <0x50027000>;
            clocks = <&rcc SAI4_K>;
            clock-names = "sai_ck";
            status = "disabled";
        };
        m4_qspi: qspi@58003000 {
            compatible = "rproc-srm-dev";
            reg = <0x58003000>, <0x70000000>;
            clocks = <&rcc QSPI_K>;
            status = "disabled";
        };
        m4_ethernet0: ethernet@5800a000 {
            compatible = "rproc-srm-dev";
            reg = <0x5800a000>;
            clock-names = "stmmaceth",
                      "mac-clk-tx",
                      "mac-clk-rx",
                      "ethstp",
                      "syscfg-clk";
            clocks = <&rcc ETHMAC>,
                 <&rcc ETHTX>,
                 <&rcc ETHRX>,
                 <&rcc ETHSTP>,
                 <&rcc SYSCFG>;
            status = "disabled";
        };
    };
};

从以上可以看出,该节点描述了远程协处理器M4的所有可用外围设备,但它们默认状态是禁用的。要使能某个外设不需要更改设备树,只需要在IDE中进行相关的配置即可, 在通过Remoteproc框架加载M4固件时会自动激活该外设。所以这部分节点内容一般不需要去动它。

接下来看物理内存的配置,下面是stm32mp157a-basic.dts文件中reserved-memory节点的配置信息。

        reserved-memory {
                #address-cells = <1>;
                #size-cells = <1>;
                ranges;

                retram: retram@0x38000000 {
                        compatible = "shared-dma-pool";
                        reg = <0x38000000 0x10000>;
                        no-map;
                };

                mcuram: mcuram@0x30000000 {
                        compatible = "shared-dma-pool";
                        reg = <0x30000000 0x40000>;
                        no-map;
                };

                mcuram2: mcuram2@0x10000000 {
                        compatible = "shared-dma-pool";
                        reg = <0x10000000 0x40000>;
                        no-map;
                };

                vdev0vring0: vdev0vring0@10040000 {
                        compatible = "shared-dma-pool";
                        reg = <0x10040000 0x2000>;
                        no-map;
                };

                vdev0vring1: vdev0vring1@10042000 {
                        compatible = "shared-dma-pool";
                        reg = <0x10042000 0x2000>;
                        no-map;
                };

                vdev0buffer: vdev0buffer@10044000 {
                        compatible = "shared-dma-pool";
                        reg = <0x10044000 0x4000>;
                        no-map;
                };

                gpu_reserved: gpu@d4000000 {
                        reg = <0xd4000000 0x4000000>;
                        no-map;
                };
        };

以上就是SRAM1~SRAM4内存区域的具体配置,这要与IDE的链接脚本中配置(见后面)要一致。关于这部分内存的具体描述可见“基于STM32MP157的异核间通信(续一)”中的相关介绍。

通过上面的配置,物理内存区域被划分成如下形式。

aaa

最后来看资源表的配置,这部分在IDE端进行。先看文件rsc_table.c,在其中定义了vring要个数和VirtIO RPMSG的设备ID,如下图所示。

d

特别要注意,VIRTIO_ID_RPMSG的数值一定要与Linux中有一致才能匹配,该项在内核源码的include/uapi/linux/virtio_ids.h文件中,如下图所示。

e

接下来看文件openamp_conf.h,在其中定义了收发vring的地址和vring_buffer的地址,并定义了vring的对齐方式和buffer的数量,还定义了两个vring的ID,如下图所示。

f

上面的定义中,值为-1的表示由A7端(Linux系统)来定义。对齐方式为16位对齐,vring_buffer数量为16个,接收vring为VRING0_ID,发送vring为VRING1_ID。

最后来看物理内存的定义,它位于链接脚本文件STM32MP157AACX_RAM.ld中。这部分要与前面设备树中的定义一致,如下图所示。

aa

在上面的配置中,第一行(RETRAM_interrupts)是M4的中断向量区,这部分一般不动它,第二行(FLASH_text)是固件的代码段部分,即SRAM1部分,第三行(RAM1_data)是固件的数据段部分,即SRAM2部分,这两部分相加刚好等前面配置的256KB,第四行(RAM2_ipc_shm)就是用于通信的共享内存区域,即SRAM3部分,这里只用了32KB。默认配置下,M4并没有使用SRAM4,它被分配给了A7用作DMA的buffer了。

在开发板上加载好M4固件并启动后,可以在目录/sys/kernel/debug/remoteproc/remoteproc0下查看文件carveout_memories和resource_table,就可以看到前面的配置信息了。如下图所示。

aaa

到此关于STM32MP157异核间通信的设备树配置和IDE端配置就讨论完了,一般使用默认配置即可,只有在特殊需要时才根据实际情况更改。

下面来看一下异核通信在内核源码中是如何配置的。在内核源码中,进入到Device Drivers一项下,可以找到两项相关配置,如下图所示。

aaa

进入Remoteproc drivers下,勾选所有选项,如下图所示。

aaa

进入Rpmsg drivers下,勾选最后两项,如下图所示。

aaa

上图中的第一项是用于生成rpmsg的字符设备节点的,在前面的例子中,rpmsg设备节点是自定义的,所以这里不要勾选,以免产生冲突。

至此,有关STM32MP157异核通信的技术原理就全部讨论完了。

posted @ 2026-09-06 22:00  fxzq  阅读(10)  评论(0)    收藏  举报