Using NonCached Memory on i.MXRT

cancel
Showing results for 
Search instead for 
Did you mean: 

Using NonCached Memory on i.MXRT

No ratings

Using NonCached Memory on i.MXRT

Symptoms

 

Some of us may have experienced the issue that when we put the heap to DTCM, everything is OK. That’s the default settings for MCUXpresso SDK demos. But when we put the heap on cached memory like OCRAM or SDRAM, much of the middleware does not function correctly. This issue happens on USB stack, LwIP and SDcard. USB enumeration failed,  ethernet drop packets, the application no longer writes to SD card, system hanging indefinitely on uninitialized semaphores…

 

Diagnosis

 

To understanding this issue, we need to understand the i.MXRT L1 Cache. AN12042 describes the technology of the i.MXRT cache system.

 
 

cache-struc.png

 

The i.MXRT series implement a CPU core platform described in Figure1. The L1 I/D-Cache is embedded in the core platform.

The data cache is 4-way set-associate and instruction cache is 2-way set-associate with cache line size of 32 bytes. It connects with the SIM_M7 bus fabric master port by AXI bus. The subsystem of internal/external memory like OCRAM(FlexRAM banks configured as OCRAM), FlexSPI (Serial NOR, NAND Flash and Hyper Flash/RAM etc) and SEMC(SDRAM, PNOR Flash, NAND Flash etc.) are connected to the bus fabric slave port. CPU core access the subsystem through this bus fabric by L1 cache. The ITCM/DTCM is accessed directly by CPU core, bypass the L1 cache.

 

OCRAM and SDRAM is cacheable by default. 

The cache brings a great performance boost, but the user must pay attention to the cache maintenance for data coherency.  To avoid data coherency issue, the easiest way is to use non-cacheable buffers.

 DTCM/ITCM is Tightly-Coupled Memories, core can access it directly (cache is not involved). That can explain why all SDK demos work correctly by default.

 

Solution

 

Put critical code and data into TCM, it is non-cacheable, which is the fastest way for CPU to access the code and data.  But forcing all global data into 128KB DTCM is constraining in many cases. Users can split a non-cache memory region from OCRAM or SDRAM, and put the buffers into this region by the linker of toolchain.

 

Next I will take evkmimxrt1060_host_msd_command_freertos demo for example to illustrate how to make USB HOST stack to run on OCRAM.  MCUxpresso IDE 11.2.1 is used for this demo.

 1    Buffer definition

 In USB stack, some important data structures are defined with macros USB_GLOBAL, USB_DMA_DATA_NONINIT_SUB, USB_DMA_DATA_INIT_SUB and USB_CONTROLLER_DATA;

These structures are defined in the usb stack by default.

We can see these structures in usb_device_ehci.c and usb_host_ehci.c (take usb host as an example). 

 In usb_device_ehci.c

/* Apply for QH buffer, 2048-byte alignment */

USB_RAM_ADDRESS_ALIGNMENT(2048)

USB_CONTROLLER_DATA static uint8_t qh_buffer[(USB_DEVICE_CONFIG_EHCI - 1) * 2048 +   2 * USB_DEVICE_CONFIG_ENDPOINTS * 2 * sizeof(usb_device_ehci_qh_struct_t)];

/* Apply for DTD buffer, 32-byte alignment */

USB_RAM_ADDRESS_ALIGNMENT(32)

USB_CONTROLLER_DATA static usb_device_ehci_dtd_struct_t s_UsbDeviceEhciDtd[USB_DEVICE_CONFIG_EHCI]                                                                        [USB_DEVICE_CONFIG_EHCI_MAX_DTD];

 In usb_host_ehci.c

 /* EHCI controller driver instances. */

#if (USB_HOST_CONFIG_EHCI == 1U)

USB_RAM_ADDRESS_ALIGNMENT(4096)

USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];

static uint8_t usbHostEhciFramListStatus[1] = {0};

 

USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1;

#elif (USB_HOST_CONFIG_EHCI == 2U)

USB_RAM_ADDRESS_ALIGNMENT(4096)

USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];

USB_RAM_ADDRESS_ALIGNMENT(4096)

USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList2[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4];

static uint8_t usbHostEhciFramListStatus[2] = {0, 0};

USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1;

USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData2;

#else

#error "Please increase the instance count."

#endif

 

 

2    Linker file : partition a RAM block from OCRAM for non-cacheable buffers

 
 
 
 

memory.png

Using managed linker script to configure memory RAM2 as a non-cacheable area.

linkerscript.png

 

3    MPU configuratins   ( board.c )

 MPU divides the memory map into a few regions, and defines the memory attributes of each region.

In this step, we need to configure the SRAM_OC_NCACHE_128(RAM2) as non-cacheable

     /* Region 13 setting: Memory with  non-cacheable */

    MPU->RBAR = ARM_MPU_RBAR(13, 0x202a0000);

    MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_128KB);

 

Now, SRAM_OC_NCACHE_128 (RAM2) is a non-cacheable section.

Variables in  *(NonCacheable.init) and  *( NonCacheable) will be put to SRAM_OC_NCACHE_128.

 

4   Put USB variables into SRAM_OC_NCACHE_128(RAM2)

 This is done by the following macros.

 #define USB_LINK_NONCACHE_NONINIT_DATA  _Pragma("location = \"NonCacheable\"")

 Relative source code is in file usb_misc.h

 

#if (defined(DATA_SECTION_IS_CACHEABLE) && (DATA_SECTION_IS_CACHEABLE))

#define USB_GLOBAL USB_LINK_NONCACHE_NONINIT_DATA

#define USB_BDT USB_LINK_NONCACHE_NONINIT_DATA

#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA

#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(NonCacheable.init)

#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA

#else

#define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS

#define USB_BDT USB_LINK_USB_BDT_BSS

#define USB_DMA_DATA_NONINIT_SUB

#define USB_DMA_DATA_INIT_SUB

#define USB_CONTROLLER_DATA

#endif

 

Please put macro “DATA_SECTION_IS_CACHEABLE=1” in the preprocessor define.

 preprocessor.png

 

5    build and run project  evkmimxrt1060_host_msd_command_freertos, success!

console output.png

 Reference:

Using the i.MXRT L1 Cache

https://www.nxp.com.cn/docs/en/application-note/AN12042.pdf

  

 

 

 

 

 

Version history
Revision #:
3 of 3
Last update:
‎11-16-2020 06:03 AM
Updated by: