Reallocating the FlexRAM

cancel
Showing results for 
Search instead for 
Did you mean: 

Reallocating the FlexRAM

100% helpful (2/2)

Reallocating the FlexRAM

Introduction 

This document is an extension of section 3.1.3, “Software implementation” from the application note AN12077, using the i.MX RT FlexRAM. It's important that before continue reading this document, you read this application note carefully. 

Link to the application note. 

Section 3.1.3 of the application note explains how to reallocate the FlexRAM through software within the startup code of your application. This document will go into further detail on all the implications of making these modifications and what is the best way to do it. 

Prerequisites

Internal SRAM 

The amount of internal SRAM varies depending on the RT. In some cases, not all the internal SRAM can be reallocated with the FlexRAM. 

RT  Internal SRAM FlexRAM
RT1010 Up to 128 KB Up to 128 KB
RT1015 Up to 128 KB Up to 128 KB
RT1020 Up to 256 KB Up to 256 KB
RT1050 Up to 512 KB Up to 512 KB
RT1060 Up to 1MB  Up to 512 KB
RT1064 Up to 1MB Up to 512 KB

 

In the case of the RT106x, only 512 KB out of the 1MB of internal SRAM can be reallocated through the FlexRAM as DTCM, ITCM, and OCRAM. The remaining 512 KB are from OCRAM and cannot be reallocated. For all the other RT10xx you can reallocate the whole internal SRAM either as DTCM, ITCM, and OCRAM. Section 3.1.3.1 of the application note explains the limitations of the size when reallocating the FlexRAM. One thing that's important to mention is that the ROM in all the RT10xx parts uses 32KB of OCRAM, hence you should keep at least 32KB of OCRAM when reallocating the FlexRAM, this doesn't apply to the RT106x since you will always have the 512 KB of OCRAM that cannot be reallocated. 

Implementation in MCUXpresso IDE

First, you need to import any of the SDK examples into your MCUXpresso IDE workspace. In my case, I imported the igpio_led_output example for the RT1050-EVKB. If you compile this project, you will see that the default configuration for the FlexRAM on the RT1050-EVKB is the following: 

SRAM_DTC

128 KB
SRAM_ITC 128 KB
SRAM_OC 256 KB

 

Now we need to go to the Reset handler located in the file startup_mimxrt1052.c. Reallocating the FlexRAM has to be done before the FlexRAM is configured, this is why it's done inside the Reset Handler. 

The registers that we need to modify to reallocate the FlexRAM are IOMUXC_GPR_GPR14, IOMUXC_GPR_GPR16, and IOMUXC_GPR_GPR17. So first we need to have in hand the addresses of these three registers.

Register Address
IOMUXC_GPR_GPR14 0x400AC038
IOMUXC_GPR_GPR16 0x400AC040
IOMUXC_GPR_GPR17 0x400AC044

 

Now, we need to determine how we want to reallocate the FlexRAM to see the value that we need to load into register IOMUXC_GPR_GPR17. In my case, I want to have the following configuration: 

SRAM_DTC

256 KB
SRAM_ITC 128 KB
SRAM_OC 128 KB

 

When choosing the new sizes of the FlexRAM be sure that you choose a configuration that you can also apply through the FlexRAM fuses, I will explain the reason for this later. The configurations that you can achieve through the fuses are shown in the Fusemap chapter of the reference manual in the table named "Fusemap Descriptions", the fuse name is "Default_FlexRAM_Part". 

Based on the following explanation of the IOMUXC_GPR_GPR17 register:

pastedImage_5.png

The value that I need to load to the register is 0xAAAAFF55. Where the first  4 banks correspond to the 128KB of SRAM_OC, the next 4 banks correspond to the 128KB of SRAM_ITC and the last 8 banks are the 256KB of SRAM_DTC. 

Now, in the register IOMUXC_GPR_GPR14, we will configure the new sizes of the SRAM_DTC and SRAM_ITC. If we look at the description of this register we will find that 128KB corresponds to 0x8 and 256KB to 0x9. If the final size of your memory is not one of the values shown below, you need to choose the next greater number. For example, if the size of SRAM_ITC is 192 in the field CM7_CFGITCMSZ you will need to select 256KB. 

pastedImage_7.png

Now, that we have all the addresses and the values that we need we can start writing the code in the Reset handler. The first thing to do is loading the new value into the register IOMUXC_GPR_GPR17. After, we need to configure register IOMUXC_GPR_GPR16 to specify that the FlexRAM bank configuration should be taken from register IOMUXC_GPR_GPR17 instead of the fuses. Then if in your new configuration of the FlexRAM either the SRAM_DTC or SRAM_ITC are of size 0, you need to disable these memories in the register IOMUXC_GPR_GPR16. Finally, you need to set the new size of SRAM_DTC and SRAM_ITC in the register IOMUXC_GPR_GPR14. At the end your code should look like the following: 

void ResetISR(void) {

 // Disable interrupts
 __asm volatile ("cpsid i");

 /* Reallocating the FlexRAM */
 __asm (".syntax unified\n"

 "LDR R0, =0x400ac044\n"//Address of register IOMUXC_GPR_GPR17
 "LDR R1, =0xaaaaff55\n"//FlexRAM configuration DTC = 265KB, ITC = 128KB, OC = 128KB
 "STR R1,[R0]\n"

 "LDR R0,=0x400ac040\n"//Address of register IOMUXC_GPR_GPR16
 "LDR R1,[R0]\n"
 "ORR R1,R1,#4\n"//The 4 corresponds to setting the FLEXRAM_BANK_CFG_SEL bit in register IOMUXC_GPR_GPR16
 "STR R1,[R0]\n"

#ifdef FLEXRAM_ITCM_ZERO_SIZE
 "LDR R0,=0x400ac040\n"//Address of register IOMUXC_GPR_GPR16
 "LDR R1,[R0]\n"
 "AND R1,R1,#0xfffffffe\n"//Disabling SRAM_ITC in register IOMUXC_GPR_GPR16
 "STR R1,[R0]\n"
#endif

#ifdef FLEXRAM_DTCM_ZERO_SIZE
 "LDR R0,=0x400ac040\n"//Address of register IOMUXC_GPR_GPR16
 "LDR R1,[R0]\n"
 "AND R1,R1,#0xfffffffd\n"//Disabling SRAM_DTC in register IOMUXC_GPR_GPR16
 "STR R1,[R0]\n"
#endif

 "LDR R0, =0x400ac038\n"//Address of register IOMUXC_GPR_GPR14
 "LDR R1, =0x980000\n"//New size configuration for the IOMUXC_GPR_GPR14 register
 "STR R1,[R0]\n"

 ".syntax divided\n");

#if defined (__USE_CMSIS)
// If __USE_CMSIS defined, then call CMSIS SystemInit code
 SystemInit();

...‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

If you compile your project you will see the memory distribution that appears on the console is still the default configuration. 

pastedImage_5.png

This is because we did modify the Reset handler to reallocate the FlexRAM but we haven't modified the linker file to match these new sizes. To do this you need to go to the properties of your project. Once in the properties, you need to go to C/C++ Build -> MCU settings. Once you are in the MCU settings you need to modify the sizes of the SRAM memories to match the new configuration. 

pastedImage_10.png

When you make these changes click Apply and Close. After making these changes if you compile the project you will see the memory distribution that appears in the console is now matching the new sizes. 

pastedImage_11.png

Now we need to modify the Memory Protection Unit (MPU) to match these new sizes of the memories. To do this you need to go to the function BOARD_ConfigMPU inside the file board.c. Inside this function, you need to locate regions 5, 6, and 7 which correspond to SRAM_ITC, SRAM_DTC, and SRAM_OC respectively. Same as for register IOMUXC_GPR_GPR14, if the new size of your memory is not 32, 64, 128, 256, or 512 you need to choose the next greater number. Your configuration should look like the following: 

/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
 MPU->RBAR = ARM_MPU_RBAR(5, 0x00000000U);
 MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);

 /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
 MPU->RBAR = ARM_MPU_RBAR(6, 0x20000000U);
 MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);

 /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
 MPU->RBAR = ARM_MPU_RBAR(7, 0x20200000U);
 MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Now, the last change that we need to make is changing the image entry address to the Reset handler. To do this you need to go to the file fsl_flexspi_nor_boot.c inside the xip folder. You need to declare the ResetISR and change the entry address in the image vector table. 

pastedImage_1.png

That's it, these are all the changes that you need to make to reallocate the FlexRAM during the startup. 

Debug Session 

To verify that all the modifications that we just did were correct we will launch the debug session. As soon as we reach the main, before running the application, we will go to the peripheral view to see registers IOMUXC_GPR_GPR14, IOMUXC_GPR_GPR16, and IOMUXC_GPR_GPR17 and verify that the values are the correct ones. First, we verify that the new size of the memories is reflected in register IOMUXC_GPR_GPR14. As shown in the below image we can see that the size of the ITCM is 8 which corresponds to 128 KB and the size of the DTCM is 9 which corresponds to 256KB. 

pastedImage_2.png

Now, in register IOMUXC_GPR_GPR16 as shown in the image below we configure the FLEXRAM_BANK_CFG_SEL as 1 to use the use register IOMUXC_GPR_GPR17 to configure the FlexRAM. 

pastedImage_4.png

Finally, in register IOMUXC_GPR_GPR17 we can see the value 0xAAAAFF55 that corresponds to the new configuration. 

pastedImage_5.png

Reallocating the FlexRAM through the Fuses 

We just saw how to reallocate the FlexRAM through software by writing some code in the Reset Handler. This procedure works fine, however, it's recommended that you use this approach to test the different sizes that you can configure but once you find the correct configuration for your application we highly recommend that you configure these new sizes through the fuses instead of using the register IOMUXC_GPR_GPR17. There are lots of dangerous areas in reconfiguring the FlexRAM in code. It pretty much all boils down to the fact that any code/data/stack information written to the RAM can end up changing location during the reallocation.  This is the reason why once you find the correct configuration, you should apply it through the fuses. If you use the fuses to configure the FlexRAM, then you don't have the same concerns about moving around code and data, as the fuse settings are applied as a hardware default. 

Keep in mind that once you burn the fuses there's no way back! This is why it's important that you first try the configuration through the software method.

Once you burn the fuses you won't need to modify the Reset handler, you only need to modify the MPU to change the size of regions as we saw before and the MCU settings of your project to match the new memory sizes that you configured through the fuses. 

The fuse in charge of the FlexRAM configuration is Default_FlexRAM_Part, the address of this fuse is 0x6D0[15:13]. You can find more information about this fuse and the different configurations in the Fusemap chapter of the reference manual. 

To burn the fuses I recommend using either the blhost or the MCUBootUtility. 

Link to download the blhost. 

Link to the MCUBootUtility webpage. 

 

I hope you find this document helpful! 
Víctor Jiménez 

Version history
Revision #:
5 of 5
Last update:
3 weeks ago
Updated by:
 
Contributors