Multicore Project setup of an additional MPU region I've been working on making a project that is essentially a combination of 2 SDK examples. I've been using the RT1170-EVKB SDK, version 26.09.00. The idea of the project is to take a multicore example and an LVGL example to have the M7 core run the graphics then communicate with the M4 core running the program. To do this I have taken the SDK examples: freertos_message_buffers (both primary and secondary) as my base project. I then slowly add in the graphics by copying and pasting the code and driver files from the lvgl_guider_cm7 project. I keep lvgl_guider_cm7 mcux_config.h file the same so that it does use PXP and VGLite. In order to do this, framebuffers need to placed in non-cache. The shared memory used in the SDK example also needs to be placed in non-cache. When this happens, I get artifacts on the display (little lines through objects that shouldn't be there). I can fix this by removing the __USE_SHMEM preprocessor, obviously this causes the multicore communication to fail. I believe it is because of the BOARD_EarlyConfigMPU function. Inside the function there is a section that goes like: #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 In this section it defines non-cache for either the shared memory or regular non-cache based on the __USE_SHMEM preprocessor. Further down in the function it declares the MPU region like so: 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);
} Now I want to be able to define both regions in the MPU to have both LVGL working without artifacts and the rpmsg message buffers be able to communicate. My memory regions can be found below: What I tried to do was modify the code above to perform both MPU region definitions, like so: #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 This way the regular non-cache region is always defined and the shared memory region is only defined if used. I modified the MPU region definition like so: 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 In doing this I created a macro for the additional MPU region inside board.h like so: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ Performing the modifications allowed LVGL to draw without artifacts but the multicore communication still fails. I put a breakpoint in the M4 thread running the multicore communication. Sometimes it'll trigger at the start, notifying that it received a message, but the message data is incorrect so it will not execute the code associated with the message's data. After a couple triggers of the breakpoint it will never trigger again. Is there anything I'm missing to be able to get this project running, the MPU region defines, etc...? Re: Multicore Project setup of an additional MPU region The changes were only applied to the primary core, as the primary core runs BOARD_EarlyConfigMPU and the secondary core runs BOARD_ConfigMPU, in the secondary core's function it already has the behaviour that I changed the primary core to have. Below are snippets from the what the secondary core runs on hardware init. #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 And then later in the function: 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 Both projects have __USE_SHMEM defined in the preprocessor. Below is the memory config for the secondary core: Am I missing something else, or perhaps are my modifications wrong? Do I need to add something extra to the "Manage Linker Script" section of the primary project's settings? When I get the chance I'll upload a .zip of the projects that run on the EVK-B board so that you may see/replicate the issue. Re: Multicore Project setup of an additional MPU region Hi @CMoran,
Your understanding makes sense, but it wasn't clear if that changed you mention were applied to both CM7 and CM4 cores. Each core has a definition of board.h, where they use their respective configuration of the MPU to setup during the initial hardware initialization. If the changes you mention were only made for the primary core, it's likely that the cores don't treat the memory regions equally, resulting in these unexpected behaviors.
Please verify that the changes are applied to both cores to ensure they coincide on MPU setup, as well as ensuring that __USE_SHMEM was setup for both project's preprocessor definitions.
View full article