Hello,
I have some question about different RAM sections.
My setup:
S32E288-975EVB
S32 Design Studio 3.6.4
S32 Debug Probe
I have created an S32E288 project, where I have marked that I would like to use multiple cores and set my boot core as the M33. It then created multiple sub-projects for me, one for each core, with a total of 5 (M33, R52_0_0, R52_0_1, R52_1_0, R52_1_1), since I'm running them all in lockstep mode. I am able to generate and flash my boot core binaries as a BLOB to flash and run my boot code non-volatile.
I am now trying to bring up all the other cores for non-volatile use and I think I have managed to turn the cores on, but I am missing the runnable code from RAM.
I can see from the linker file, that there are multiple memory section like TCM-A, -B, -C, AXIM CRAM sections, AXIF CRAM section and so on:
* Target device: This linker is demo and it is using for device S32Z2xx and S32E2xx only
* Target core: core 0 cluster 0 (RTU0)
* Linker support for application running on RTU0 core0 only. It need to align with MPU default setup in core.c as well.
* Memory setting: Local ram of RTU0 (CRAM and DRAM)
*/
/*
* GCC Linker Command File:
* 0x30000000 0x3000FFFF 65536 ; RTU0_R52_0_TCM_A
* 0x30100000 0x30103FFF 16384 ; RTU0_R52_0_TCM_B
* 0x30200000 0x30203FFF 16384 ; RTU0_R52_0_TCM_C
* 0x31780000 0x317BFFFF 262144 ; RTU0_DRAM_0 (Fast Data 0)
* 0x317C0000 0x317FFFFF 262144 ; RTU0_DRAM_1 (Fast Data 1)
* 0x31800000 0x3187FFFF 524288 ; RTU0_DRAM_2 (Fast Data 2)
* 0x32100000 0x321FFFFF 1048575 ; RTU0_CRAM_0 (Code ram 0)
* 0x32200000 0x322FFFFF 1048575 ; RTU0_CRAM_1 (Code ram 1)
* 0x32300000 0x323FFFFF 1048575 ; RTU0_CRAM_2 (Code ram 2)
* 0x32400000 0x324FFFFF 1048575 ; RTU0_CRAM_3 (Code ram 3)
* 0x32500000 0x325FFFFF 1048575 ; RTU0_CRAM_4 (Code ram 4)
* 0x32600000 0x326FFFFF 1048575 ; RTU0_CRAM_5 (Code ram 5)
* 0x32700000 0x327FFFFF 1048575 ; RTU0_CRAM_6 (Code ram 6)
* 0x79900000 0x799FFFFF 1048575 ; RTU0_CRAM_0_AXIF (Code ram 0 AXIF)
* 0x79A00000 0x79AFFFFF 1048575 ; RTU0_CRAM_1_AXIF (Code ram 1 AXIF)
* 0x79B00000 0x79BFFFFF 1048575 ; RTU0_CRAM_2_AXIF (Code ram 2 AXIF)
* 0x79C00000 0x79CFFFFF 1048575 ; RTU0_CRAM_3_AXIF (Code ram 3 AXIF)
* 0x79D00000 0x79DFFFFF 1048575 ; RTU0_CRAM_4_AXIF (Code ram 4 AXIF)
* 0x79E00000 0x79EFFFFF 1048575 ; RTU0_CRAM_5_AXIF (Code ram 5 AXIF)
* 0x79F00000 0x79FFFFFF 1048575 ; RTU0_CRAM_6_AXIF (Code ram 6 AXIF)
* 0x4E400000 0x4E400FFF 4096 ; AE_SRAM
*/
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00001000;
ENTRY(Reset_Handler)
MEMORY
{
int_sram_no_cacheable_smu_m33 : ORIGIN = 0x250C0000, LENGTH = 0x0003C000 /* 240KB, needs to include int_results */
/*RTU0 ram section */
int_atcm_c0_0 : ORIGIN = 0x30000000, LENGTH = 0x00010000 /* 64K */
int_btcm_c0_0 : ORIGIN = 0x30100000, LENGTH = 0x00004000 /* 16K */
int_ctcm_c0_0 : ORIGIN = 0x30200000, LENGTH = 0x00004000 /* 16K */
int_atcm_c0_1 : ORIGIN = 0x30400000, LENGTH = 0x00010000 /* 64K */
int_btcm_c0_1 : ORIGIN = 0x30500000, LENGTH = 0x00004000 /* 16K */
int_ctcm_c0_1 : ORIGIN = 0x30600000, LENGTH = 0x00004000 /* 16K */
int_atcm_c0_2 : ORIGIN = 0x30800000, LENGTH = 0x00010000 /* 64K */
int_btcm_c0_2 : ORIGIN = 0x30900000, LENGTH = 0x00004000 /* 16K */
int_ctcm_c0_2 : ORIGIN = 0x30A00000, LENGTH = 0x00004000 /* 16K */
int_atcm_c0_3 : ORIGIN = 0x30C00000, LENGTH = 0x00010000 /* 64K */
int_btcm_c0_3 : ORIGIN = 0x30D00000, LENGTH = 0x00004000 /* 16K */
int_ctcm_c0_3 : ORIGIN = 0x30E00000, LENGTH = 0x00004000 /* 16K */
int_sram_dram_c0_0 : ORIGIN = 0x31780000, LENGTH = 0x00020000 /* 128KB DRAM0 */
int_sram_dram_c0_1 : ORIGIN = 0x317A0000, LENGTH = 0x00020000 /* 128KB DRAM0 */
int_sram_dram_c0_2 : ORIGIN = 0x317C0000, LENGTH = 0x00020000 /* 128KB DRAM1 */
int_sram_dram_c0_3 : ORIGIN = 0x317E0000, LENGTH = 0x00020000 /* 128KB DRAM1 */
int_sram_no_cacheable_c0_0 : ORIGIN = 0x31800000, LENGTH = 0x00010000 /* 64KB DRAM2, needs to include int_results */
int_sram_no_cacheable_c0_1 : ORIGIN = 0x31810000, LENGTH = 0x00010000 /* 64KB DRAM2, needs to include int_results */
int_sram_no_cacheable_c0_2 : ORIGIN = 0x31820000, LENGTH = 0x00010000 /* 64KB DRAM2, needs to include int_results */
int_sram_no_cacheable_c0_3 : ORIGIN = 0x31830000, LENGTH = 0x00010000 /* 64KB DRAM2, needs to include int_results */
int_sram_rtu0_shareable : ORIGIN = 0x31840000, LENGTH = 0x00040000 /* 256KB DRAM2 */
/* For code section there are 2 interface: AXI-M: Global port-bus which can use for loading image, access from inside/outside sub-system AXI-F: Read-only port-bus, faster interface for code access. For this demo we're using AXI-M to load image and AXI-F for code execution. */
int_sram_c0_0 : ORIGIN = 0x32100000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_0 : ORIGIN = 0x322C0000, LENGTH = 0x00000000 /* End of core 0_0 */
int_sram_c0_0_axif : ORIGIN = 0x79900000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_0_axif : ORIGIN = 0x79AC0000, LENGTH = 0x00000000 /* End of core 0_0 */
int_sram_c0_1 : ORIGIN = 0x322C0000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_1 : ORIGIN = 0x32480000, LENGTH = 0x00000000 /* End of core 0_1 */
int_sram_c0_1_axif : ORIGIN = 0x79AC0000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_1_axif : ORIGIN = 0x79C80000, LENGTH = 0x00000000 /* End of core 0_1 */
int_sram_c0_2 : ORIGIN = 0x32480000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_2 : ORIGIN = 0x32640000, LENGTH = 0x00000000 /* End of core 0_2 */
int_sram_c0_2_axif : ORIGIN = 0x79C80000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_2_axif : ORIGIN = 0x79E40000, LENGTH = 0x00000000 /* End of core 0_2 */
int_sram_c0_3 : ORIGIN = 0x32640000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_3 : ORIGIN = 0x32800000, LENGTH = 0x00000000 /* End of core 0_3 */
int_sram_c0_3_axif : ORIGIN = 0x79E40000, LENGTH = 0x001C0000 /* ~1.8MB */
ram_end_c0_3_axif : ORIGIN = 0x7A000000, LENGTH = 0x00000000 /* End of core 0_3 */
I understand that Tightly Coupled Memory is a part of RAM and it is even highly recommended to run code from TCM as it only takes one cycle to retrieve data from it.
Therefore:
- What is the difference between TCM-A, -B and -C and what are the usecases for each?
- Why wouldn't I or why doesn't the demo use TCM to run code?
- Can the SMU core even write TCM?
Additionally I can see from my M33 project Project_Settings -> Startup_Code -> system.c, that turning on the used cores is actually implemented through SystemInit() with:
Sys_StartSecondaryCores()
/*================================================================================================*/
/**
* @brief Sys_StartSecondaryCores
* @details Function used to start the secondary cores
*/
/*================================================================================================*/
static void Sys_StartSecondaryCores(void)
{
/* Turn on partitions */
Sys_PartitionsTurnOn();
/* Configure Split-lock RTU0 if M33 core is boot core */
#if (defined(CORE_M33_0) && \
(defined(START_CR52_0_0) || defined(START_CR52_0_1) || defined(START_CR52_0_2) || defined(START_CR52_0_3)) \
)
#ifndef RTU0_R52_LOCKSTEP_MODE
IP_RTU0__GPR->CFG_CORE |= RTU_GPR_CFG_CORE_SPLT_LCK_MASK;
#endif
#endif
/* Configure Split-lock RTU1 */
#if (defined(START_CR52_1_0) || defined(START_CR52_1_1) || defined(START_CR52_1_2) || defined(START_CR52_1_3))
#ifndef RTU1_R52_LOCKSTEP_MODE
IP_RTU1__GPR->CFG_CORE |= RTU_GPR_CFG_CORE_SPLT_LCK_MASK;
#endif
#endif
/* Release secondary cores to exit reset */
#ifdef START_CR52_0_0
extern const uint32 __CORE_R52_0_0_START_ADDRESS;
IP_MC_ME->PRTN1_CORE0_ADDR = (uint32)&__CORE_R52_0_0_START_ADDRESS;
IP_MC_ME->PRTN1_CORE0_PCONF = 1;
IP_MC_ME->PRTN1_CORE0_PUPD = 1;
IP_MC_ME->CTL_KEY = 0x5AF0;
IP_MC_ME->CTL_KEY = 0xA50F;
while (!(IP_MC_ME->PRTN1_CORE0_STAT & MC_ME_PRTN1_CORE0_STAT_CCS_MASK)) {};
IP_MC_RGM->PRST_0[1].PRST_0 &= ~MC_RGM_PRST_0_PERIPH_65_RST_MASK;
while(IP_MC_RGM->PSTAT_0[1].PSTAT_0 & MC_RGM_PRST_0_PERIPH_65_RST_MASK);
#endif /*START_CR52_0_0*/
...
and Sys_PartitionsTurnOn()
/**
* @brief Sys_PartitionsTurnOn
* @details Function used to turn on partitions
*/
/*================================================================================================*/
#if (defined(START_CR52_0_0) || defined(START_CR52_0_1) || defined(START_CR52_0_2) || defined(START_CR52_0_3) || \
defined(START_CR52_1_0) || defined(START_CR52_1_1) || defined(START_CR52_1_2) || defined(START_CR52_1_3) || defined(START_CM33_0) \
)
static void Sys_PartitionsTurnOn(void)
{
/* Turn on RTU0 partition if M33 core is boot core */
#if (defined(CORE_M33_0) && \
(defined(START_CR52_0_0) || defined(START_CR52_0_1) || defined(START_CR52_0_2) || defined(START_CR52_0_3)) \
)
/* Enable partition clock */
IP_MC_ME->PRTN1_PCONF |= MC_ME_PRTN1_PCONF_PCE_MASK;
IP_MC_ME->PRTN1_PUPD |= MC_ME_PRTN1_PUPD_PCUD_MASK;
IP_MC_ME->CTL_KEY = 0x5AF0;
IP_MC_ME->CTL_KEY = 0xA50F;
while (!(IP_MC_ME->PRTN1_STAT & MC_ME_PRTN1_STAT_PCS_MASK));
/* Release partition to exit reset */
IP_MC_RGM->PRST_0[1].PRST_0 &= ~MC_RGM_PRST_0_PERIPH_64_RST_MASK;
/* Disable OSS */
IP_MC_ME->PRTN1_PCONF &= ~MC_ME_PRTN1_PCONF_OSSE_MASK;
IP_MC_ME->PRTN1_PUPD |= MC_ME_PRTN1_PUPD_OSSUD_MASK;
IP_MC_ME->CTL_KEY = 0x5AF0;
IP_MC_ME->CTL_KEY = 0xA50F;
while(IP_MC_RGM->PSTAT_0[1].PSTAT_0 & MC_RGM_PRST_0_PERIPH_64_RST_MASK);
while(IP_MC_ME->PRTN1_STAT & MC_ME_PRTN1_STAT_OSSS_MASK);
/* Deactivate RTU0 fencing logic and enable SRAM interface */
IP_GPR3->RTU0FDC = 0U;
IP_RDC_0->RD1_CTRL_REG |= RDC_RD1_CTRL_REG_RD1_CTRL_UNLOCK_MASK;
IP_RDC_0->RD1_CTRL_REG &= ~RDC_RD1_CTRL_REG_RD1_INTERCONNECT_INTERFACE_DISABLE_MASK;
while(IP_RDC_0->RD1_STAT_REG & RDC_RD1_STAT_REG_RD1_INTERCONNECT_INTERFACE_DISABLE_STAT_MASK);
#endif
/* Turn on RTU1 partition */
#if (defined(START_CR52_1_0) || defined(START_CR52_1_1) || defined(START_CR52_1_2) || defined(START_CR52_1_3))
/* Enable partition clock */
IP_MC_ME->PRTN2_PCONF |= MC_ME_PRTN2_PCONF_PCE_MASK;
IP_MC_ME->PRTN2_PUPD |= MC_ME_PRTN2_PUPD_PCUD_MASK;
IP_MC_ME->CTL_KEY = 0x5AF0;
IP_MC_ME->CTL_KEY = 0xA50F;
while (!(IP_MC_ME->PRTN2_STAT & MC_ME_PRTN2_STAT_PCS_MASK));
/* Release partition to exit reset */
IP_MC_RGM->PRST_0[2].PRST_0 &= ~MC_RGM_PRST_0_PERIPH_128_RST_MASK;
/* Disable OSS */
IP_MC_ME->PRTN2_PCONF &= ~MC_ME_PRTN2_PCONF_OSSE_MASK;
IP_MC_ME->PRTN2_PUPD |= MC_ME_PRTN2_PUPD_OSSUD_MASK;
IP_MC_ME->CTL_KEY = 0x5AF0;
IP_MC_ME->CTL_KEY = 0xA50F;
while(IP_MC_RGM->PSTAT_0[2].PSTAT_0 & MC_RGM_PRST_0_PERIPH_128_RST_MASK);
while(IP_MC_ME->PRTN2_STAT & MC_ME_PRTN2_STAT_OSSS_MASK);
/* Deactivate RTU1 fencing logic and enable SRAM interface */
IP_GPR3->RTU1FDC = 0U;
IP_RDC_1->RD1_CTRL_REG |= RDC_RD1_CTRL_REG_RD1_CTRL_UNLOCK_MASK;
IP_RDC_1->RD1_CTRL_REG &= ~RDC_RD1_CTRL_REG_RD1_INTERCONNECT_INTERFACE_DISABLE_MASK;
while(IP_RDC_1->RD1_STAT_REG & RDC_RD1_STAT_REG_RD1_INTERCONNECT_INTERFACE_DISABLE_STAT_MASK);
/* Configure REMAP for NICs */
IP_RTU1__RTUM_NIC_D->REMAP = 0x02U;
IP_RTU1__RTUF_NIC_D->REMAP = 0x02U;
IP_RTU1__RTUP_NIC_B->REMAP = 0x02U;
IP_RTU1__RTUE_NIC_D->REMAP = 0x02U;
#endif
}
But I can't find where the all the START_CR... defines are defined for actually turning the cores on. Is that some boot magic by the S32 Design Studio?
When the memory map marks "Slave Addressed by Each of the Masters" with colour codes for SMU, RTU0 Master, RTU1 Master:
Does it mean that only the marked colour Master can access this part of memory? So for example, when R0-CPU0_ATCM is grey at 0x3000_0000, does that mean, that when SMU tries to read/write 0x3000_0000, an error is generated or what happens or what exactly does it mean?