实战经验 | 如何扩大MP2的A35核和M33核共享内存

前言

STM32MP2x系列芯片都有两个相互独立的异构核,一个是Cortex-M33核,一个是Cortex-A35核,两个独立的核在同一个DDR内存运行的时候,就需要配置好各自的DDR内存映射,即要保证各自访问内存不能越界,又要保证两个核数据交互时能访问同一块内存。目前ST只提供一种默认的内存映射,有时候不能满足各种不同客户的需求,所以这篇文章主要讲解

如何自由的配置Cortex-M33核和Cortex-A35核的内存映射。

1. 概括

STM32MP2x系列MPU芯片比上一代STM32MP15x系列芯片在DDR内存的访问上有很大的区别。STM32MP2x系列的芯片异构核都能直接来访问DDR内存,所以在内存配置的时候要特别注意内存映射表一定要配置清楚。默认的内存配置可以参考这个wiki,DDR前面64MByte的内存空间是预留给OPTEE和Cortex-M33使用的。但是在有些情况下,这个内存配置没法满足客人的需求,例如客人希望扩大CortexM33的数据内存,或者扩大CortexM33和CortexA35的共享内存,就需要扩大DDR前面的64M内存,下面就讲解如何来扩大前面预留的64MDDR内存。

2. 工作原理

2.1 Linux启动时内存的动态规划

MPU标准的linux启动过程是,先ROM Code运行,然后ROM Code通过启动外设加载第二级启动程序,也就是TF-A BL2,然后TF-A通过FIP文件来加载OP-TEE和U-boot,U-boot起来后再加载kernel并最终运行Linux系统。具体的可以参考这个wiki。TF-A先被加载到MPU内部的SRAM,然后TF-A负责初始化一些基本的电源和DDR内存,然后再把FIP文件中的OP-TEE和Uboot加载到对应的内存中运行,Uboot运行后又需要把kernel加载到对应的DDR内存中,然后运行。所以如果希望修改默认的DDR内存映射表,就需要修改TF-A,Uboot,OP-TEE,kernel的加载地址,防止内存冲突。默认的A35住启动时候,不同启动阶段DDR内存映射如下:

Image
实战经验 | 如何扩大MP2的A35核和M33核共享内存

2.2 如何修改TF-A BL2运行后的内存映射表

TF-A加载FIP文件并运行,是通过FCONF文件,也就是通过stm32mp25-fw-config.dtsi这个设备树,这个设备树中引用的STM32MP_HW_CONFIG_BASE和STM32MP_BL33_BASE是在stm32mp2_def.h这个文件中定义的,所以如果希望修改DDR内存映射,只需要修改stm32mp2_def.h这个配置文件。例如下是基于OSTL6.0的BSP,把预留DDR内存再扩大32M的patch:

diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index e26ccbd..51975c4 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -290,7 +290,7 @@ enum ddr_type {
#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE
#define STM32MP_FW_CONFIG_BASE 
STM32MP_SYSRAM_BASE
-#define STM32MP_BL33_BASE 
(STM32MP_DDR_BASE + U(0x04000000))
+#define STM32MP_BL33_BASE 
(STM32MP_DDR_BASE + U(0x06000000))
#define STM32MP_BL33_MAX_SIZE 
U(0x400000)
#define STM32MP_HW_CONFIG_BASE 
(STM32MP_BL33_BASE + \STM32MP_BL33_MAX_SIZE)

当然这里还需要修改stm32mp257f-ev-ca35tdcid-fw-config.dtsi设备树配置文件,例如下列配置

/ {
dtb-registry {
soc_fw-config {
load-address = <0x0 0x83fc0000>;
max-size = <0x40000>;
};
tos_fw {
load-address = <0x0 0x84000000>;
max-size = <0x2000000>;
};
};
st-mem-firewall {
bl31_context: bl31-context@83fc0000 {
reg = <0x0 0x83fc0000 0x0 0x40000>;
st,protreg = <RISAFPROT(RISAF_REG_ID(7), RIF_CID0_BF|RIF_CID1_BF, 
RIF_CID0_BF|RIF_CID1_BF, 0, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
};
op_tee: op-tee@84000000 {
reg = <0x0 0x84000000 0x0 0x2000000>;
st,protreg = <RISAFPROT(RISAF_REG_ID(8), RIF_CID0_BF|RIF_CID1_BF, 
RIF_CID0_BF|RIF_CID1_BF, 0, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
};
};
};

2.3 如何修改OP-TEE的内存配置

因为OP-TEE在TF-A运行后,加载到固定地址,后面整个Linux运行这个地址一直不变,这样才能保证U-boot和Kernel能正确访问OP-TEE的服务程序。如下是基于OSTL6.0修改的OP-TEE的补丁文件内容,也是扩大32M内存:

2.4 如何修改U-boot运行的内存配置

U-boot是TF-A加载运行的,所以他本身即要告诉TF-A自己要运行的内存地址,又要保证U-Boot运行后,需要加载kernel和不能访问optee预留地址,当然所以这边需要修改如下的

文件:

diff --git a/arch/arm/mach-stm32mp/Kconfig.25x b/arch/arm/mach-stm32mp/Kconfig.25x
index 2c0f691f..285eee06 100644
--- a/arch/arm/mach-stm32mp/Kconfig.25x
+++ b/arch/arm/mach-stm32mp/Kconfig.25x
@@ -16,16 +16,16 @@ config TARGET_ST_STM32MP25X
endchoice
config TEXT_BASE
- 
default 0x84000000
+ 
default 0x86000000
config PRE_CON_BUF_ADDR
- 
default 0x84800000
+ 
default 0x86800000
config PRE_CON_BUF_SZ
default 4096
config BOOTSTAGE_STASH_ADDR
- 
default 0x87000000
+ 
default 0x89000000
if DEBUG_UART
diff --git a/configs/stm32mp25_defconfig b/configs/stm32mp25_defconfig
index 5b8aab47..f1703db9 100644
--- a/configs/stm32mp25_defconfig
+++ b/configs/stm32mp25_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
CONFIG_USE_ARCH_MEMCPY=y
CONFIG_ARCH_STM32MP=y
CONFIG_SYS_MALLOC_F_LEN=0x500000
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x90000000
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x92000000
CONFIG_ENV_OFFSET=0x900000
CONFIG_ENV_SECT_SIZE=0x40000
CONFIG_DEFAULT_DEVICE_TREE="stm32mp257f-ev1"
@@ -11,12 +11,12 @@ CONFIG_CMD_STM32KEY=y
CONFIG_ENV_OFFSET_REDUND=0x940000
CONFIG_TARGET_ST_STM32MP25X=y
CONFIG_CMD_STM32PROG=y
-CONFIG_SYS_LOAD_ADDR=0x84000000
+CONFIG_SYS_LOAD_ADDR=0x86000000
CONFIG_ENV_ADDR=0x60900000
CONFIG_FWU_NUM_IMAGES_PER_BANK=1
CONFIG_OF_BOARD_FIXUP=y
-CONFIG_SYS_MEMTEST_START=0x84000000
-CONFIG_SYS_MEMTEST_END=0x88000000
+CONFIG_SYS_MEMTEST_START=0x86000000
+CONFIG_SYS_MEMTEST_END=0x8A000000
CONFIG_API=y
CONFIG_SYS_MMC_MAX_DEVICE=3
CONFIG_FIT=y
@@ -80,7 +80,7 @@ CONFIG_BUTTON=y
CONFIG_BUTTON_GPIO=y
CONFIG_DFU_TFTP=y
CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_FASTBOOT_BUF_ADDR=0x84000000
+CONFIG_FASTBOOT_BUF_ADDR=0x86000000
CONFIG_FASTBOOT_BUF_SIZE=0x2000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=1
diff --git a/include/configs/stm32mp25_common.h b/include/configs/stm32mp25_common.h
index 711b8243..f23896b0 100644
--- a/include/configs/stm32mp25_common.h
+++ b/include/configs/stm32mp25_common.h
@@ -98,14 +98,14 @@

            
* 1M fdt, 1M script, 1M pxe and 1M for overlay

            
* and the ramdisk at the end.

            
*/
-#define __KERNEL_COMP_ADDR_R __stringify(0x84000000)
+#define __KERNEL_COMP_ADDR_R __stringify(0x86000000)
#define __KERNEL_COMP_SIZE_R __stringify(0x04000000)
-#define __KERNEL_ADDR_R __stringify(0x8a000000)
-#define __FDT_ADDR_R __stringify(0x90000000)
-#define __SCRIPT_ADDR_R __stringify(0x90100000)
-#define __PXEFILE_ADDR_R __stringify(0x90200000)
-#define __FDTOVERLAY_ADDR_R __stringify(0x90300000)
-#define __RAMDISK_ADDR_R __stringify(0x90400000)
+#define __KERNEL_ADDR_R __stringify(0x8c000000)
+#define __FDT_ADDR_R __stringify(0x92000000)
+#define __SCRIPT_ADDR_R __stringify(0x92100000)
+#define __PXEFILE_ADDR_R __stringify(0x92200000)
+#define __FDTOVERLAY_ADDR_R __stringify(0x92300000)
+#define __RAMDISK_ADDR_R __stringify(0x92400000)

2.5 如何修改Kernel运行的DDR内存配置

Kernel就稍微简单一些,只需要修改DDR的预留地址,就可以了,当然这里面要注意,OP-TEE,U-boot都需要修改设备树的预留地址,保持内存预留地址一致。

3. 总结

因为STM32MP2x系列的芯片Cortex-M核和Cortex-A核对外设的访问和DDR的访问几乎一样没有限制,所以如果默认的内存配置不能满足需求,可以参考这个例子来对内存重新配置。

来源:STM32

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

👍 点赞 · 0