多核项目设置额外的 MPU 区域 我一直在开发一个项目,该项目本质上是两个 SDK 示例的结合体。我一直在使用 RT1170-EVKB SDK,版本为 26.09.00。该项目的想法是采用多核示例和 LVGL 示例,让 M7 核心运行图形,然后与运行程序的 M4 核心进行通信。为此,我采用了 SDK 示例: 我的基础项目是 freertos_message_buffers(包括主缓冲区和辅助缓冲区)。然后我通过从 lvgl_guider_cm7 项目中复制和粘贴代码和驱动程序文件,慢慢地添加图形。 我保留了 lvgl_guider_cm7 mcux_config.h文件内容相同,以便它能够使用 PXP 和 VGLite。为了实现这一点,需要将帧缓冲区放置在非缓存位置。SDK 示例中使用的共享内存也需要放置在非缓存中。发生这种情况时,屏幕上会出现瑕疵(不应该出现在那里的物体上出现细线)。 我可以通过移除 __USE_SHMEM 预处理器来解决这个问题,但显然这会导致多核通信失败。我认为这是由于 BOARD_EarlyConfigMPU 函数引起的。函数内部有一个部分的内容如下: #elif defined(__MCUXPRESSO)
#if defined(__USE_SHMEM)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t nonCacheStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t size = (uint32_t)(&__top_rpmsg_sh_mem) - nonCacheStart;
#else
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t size = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#endif 本节根据 __USE_SHMEM 预处理器定义了共享内存或常规非缓存的非缓存。函数后面部分对 MPU 区域进行了如下声明: volatile uint32_t i = 0;
...
while ((size >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(nonCacheStart % size));
BOARD_EARLY_ASSERT(size == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
} 现在我希望能够在 MPU 中定义这两个区域,以便 LVGL 能够正常工作而不会出现瑕疵,并且 rpmsg 消息缓冲区能够进行通信。我的记忆区域如下: 我尝试修改上面的代码,使其能够同时定义两个 MPU 区域,如下所示: #elif defined(__MCUXPRESSO)
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#if defined(__USE_SHMEM)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart;
#endif 这样一来,常规的非缓存区域始终会被定义,而共享内存区域仅在需要时才会被定义。我按如下方式修改了 MPU 区域定义: volatile uint32_t i = 0;
...
while ((nonCacheSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(nonCacheStart % nonCacheSize));
BOARD_EARLY_ASSERT(nonCacheSize == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
}
#if (__USE_SHMEM)
i = 0;
while ((rpmsgShmemSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(rpmsgShmemStart % rpmsgShmemSize));
BOARD_EARLY_ASSERT(rpmsgShmemSize == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 16 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_SHMEM, rpmsgShmemStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
}
#endif 为此,我在 board.h 中为额外的 MPU 区域创建了一个宏。就像这样: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ 进行这些修改后,LVGL 可以无瑕疵地绘制图形,但多核通信仍然失败。我在运行多核通信的 M4 线程中设置了一个断点。有时它会在启动时触发信号,通知它已收到消息,但消息数据不正确,因此不会执行与消息数据关联的代码。断点触发信号几次后,将不再触发。 我是否遗漏了什么才能让这个项目运行起来,例如 MPU 区域定义等等……? Re: Multicore Project setup of an additional MPU region 这些更改仅应用于主核心,因为主核心运行 BOARD_EarlyConfigMPU,而辅助核心运行 BOARD_ConfigMPU,辅助核心的函数已经具有我更改主核心的行为。以下是辅助核心在硬件初始化时运行的部分代码片段。 #elif __CORTEX_M == 4
void BOARD_ConfigMPU(void)
{
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
...
#elif defined(__MCUXPRESSO)
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#elif defined(__ICCARM__) || defined(__GNUC__)
...
#endif
#if defined(__USE_SHMEM)
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
...
#elif defined(__MCUXPRESSO)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart;
#elif defined(__ICCARM__) || defined(__GNUC__)
...
#endif
#endif 然后在函数的后面部分: uint32_t i = 0;
/* Only config non-cacheable region on system bus */
assert(nonCacheStart >= 0x20000000);
...
while ((nonCacheSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
assert(!(nonCacheStart % nonCacheSize));
assert(nonCacheSize == (uint32_t)(1 << i));
assert(i >= 5);
/* Region 0 setting: Memory with device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1);
}
#if defined(__USE_SHMEM)
i = 0;
while ((rpmsgShmemSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
assert(!(rpmsgShmemStart % rpmsgShmemSize));
assert(rpmsgShmemSize == (uint32_t)(1 << i));
assert(i >= 5);
/* Region 1 setting: Memory with device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_RPMSG_SHMEM, rpmsgShmemStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1);
}
#endif 这两个项目的预处理器中都定义了 __USE_SHMEM。以下是辅助核心的内存配置: 我是否遗漏了什么,或者我的修改是否错误?我是否需要在主项目设置的“管理链接器脚本”部分添加一些额外的内容?有机会的话,我会上传一个包含 EVK-B 板上运行的项目的 .zip 文件,以便您可以查看/重现该问题。 Re: Multicore Project setup of an additional MPU region 嗨@CMoran ,
你的理解很有道理,但是你提到的变化是否同时适用于 CM7 和 CM4 内核,这一点还不清楚。每个核心都有 board.h 的定义,它们使用各自的 MPU 配置在初始硬件初始化期间进行设置。如果您提到的更改仅针对主核心进行,则核心对内存区域的处理方式可能不一致,从而导致这些意外行为。
请验证更改是否已应用于两个核心,以确保 MPU 设置一致,并确保已为两个项目的预处理器定义设置 __USE_SHMEM。 Re: Multicore Project setup of an additional MPU region 这是 .zip 文件。其中包含 m7 和 m4 项目。我保留了修改前的样子,因为修改后也没起作用。在这个例子中,如果你打开一个终端并按下中间的按钮,m7 和 m4 内核都会打印一条消息。如前所述,屏幕上移动的设置图标包含许多瑕疵。 从 m7 项目中移除 __USE_SHMEM 预处理器将修复设置图标中的瑕疵,但多核通信将会失败。 添加我上面应用的修改后,设置图标也会修复,但多核通信将会失败。 本演示中使用的屏幕是 RK055HDMIPI4MA0。 Re: Multicore Project setup of an additional MPU region 遗憾的是,在创建新的内存区域定义之前: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ 我只是重复使用了预定义的非缓存内存区域: #define BOARD_MPU_REGION_NONCACHE (10) /* Noncacheable space in application */ 我的结果也一样。我已经将新的内存区域定义更改为10 ,以匹配非缓存区域。核心之间始终无法通信。 我用断点检查了两个核心上 rpmsg 共享内存的起始位置和大小,它们的起始位置 (0x20340000) 和大小 (0x10000) 都正确。我已将两个核心上的 ARM_MPU_RASR() 函数的第 4 个参数更改为1 ,以表明该区域是“可共享的”。还是没找到办法。当您或团队成员有空时,我会在另一个回复中发布我的项目代码。我已经想不出还能尝试什么了。 Re: Multicore Project setup of an additional MPU region 嗨@CMoran ,
知道了。不过,回到你最初的回复:
您提到您创建了一个新的内存区域定义:
#define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */
但是 ARM_MPU_RBAR() 的定义使用了 MPU_RBAR_REGION_Msk,其定义为 15:
#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/)
CM7 将区域数量定义为 16 个,编号为 0-15。
因此,这样做实际上是将区域 0 设置到该区域。 Re: Multicore Project setup of an additional MPU region @CMoran ,你好!
项目构建完成后,请分析生成的 .ld 文件中的内存区域。从文件中可以看出,LVGL 帧缓冲区和多核消息缓冲区位于不同的内存区域,由于它们是不连续的物理内存,因此无法合并:
LVGL 帧缓冲区的 NCACHE_REGION 位于 0x81000000(16 MB,位于 同步动态随机存取存储器(SDRAM) 中)
rpmsg_sh_mem 位于 0x20340000(64 KB,OCRAM),用于多核消息缓冲区
也就是说,MPU 区域 7 目前覆盖 0x20300000–0x2037FFFF (512 KB) 作为可缓存的普通内存,该范围包括 rpmsg_sh_mem 区域,这意味着共享内存最终可能是可缓存的,从而导致您看到的内核间通信错误。减小 Region 7 的大小,以确保 rpmsg_sh_mem 降级到 Region 3(该区域本身不可缓存),这可能是一个简单的修复方法,可以确保消息缓冲区的正常功能,而无需对现有驱动程序进行 MPU 驱动程序级别的更改。 Re: Multicore Project setup of an additional MPU region 嗨@EdwinHz 我花了一点时间测试了一下你的建议。我将 MPU 区域 7 (OCRAM2) 的值从 512 KB 改为 256 KB,如下所示: /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_OCRAM_B, 0x20300000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); 移除 __USE_SHMEM 预处理器后,rpmsg_sh_mem 将降级到 MPU 区域 3,而该区域已被定义为不可缓存。我创建的演示程序现在已经按预期运行了。
View full article