Issue with MIMXRT1050-EVK, FreeRTOS and SDRAM for data storage

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Issue with MIMXRT1050-EVK, FreeRTOS and SDRAM for data storage

3,600 Views
edw8
Contributor III

I started out with an MCUXpresso SDK 2.3 sample project for using FreeRTOS and I customized it to create three tasks and an event queue for dispatching requests from two of the tasks into the third. (freertos_queue example) The initial SDK example project ran out of SRAM, so I converted the project to run out of hyperflash on the MIMXRT1050-EVK.

This step was performed using notes from Overview of using the MIMXRT1050-EVK with MCUXpresso IDE to convert a RAM project to XIP from flash (doc v104, page 17).

At this point, the project builds and runs well, however the heap used by FreeRTOS along with all other data memory resources come from SRAM_DTC. This area maxes out at 128KB and the project that I am preparing for will use several hundred KB of heap space. For this reason I am attempting to use the MIMXRT1050-EVK SDRAM (32 MB) device. 

I changed the project config for memory details to include an SDRAM section and positioned it immediately below the hyperflash section. 

2018-02-22_17-49-19.png

I then edited FreeRTOSConfig.h and increased my heap allocation:

/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE ((size_t)(500 * 1024))
#define configAPPLICATION_ALLOCATED_HEAP 0

The build completed error/warning free, but I get a hard fault thrown at runtime. 

pastedImage_8.png

By decreasing the heap size to 30 * 1024, I no longer get the hard fault, but rather my second of 3 tasks fails to create (pvPortMalloc call returns NULL). My queue and task that uses the queue create without problems.

I searched for similar issues posted to the community and found Jack King's thread:

Does debug init SDRAM for xip app on MIMXRT1052? 

as well as a thread describing similar hard fault issues with FreeRTOS for the LPC1778:

hard fault when FreeRTOS heap is in external SDRAM 

The takeaway from one of Jack King's comments:

2. When using xip to execute a project from flash, SDRAM is not needed, but *is* initialized (for some reason?) This is done by configuring the project to use xip: adding the xip sdk components, adjusting the linker, adding flash memory definition and setting the XIP_EXTERNAL_FLASH symbol.  The SDRAM configuration is performed by the flash bootloader using an array defined in fsl_flexspi_nor_boot.c

was that I didn't need anything else for SDRAM init other than the memory config I have above since I could see the dcd_sdram[] space initialized in my project via constant def in fsl_flexspi_nor_boot.c.

The hard fault thread mentioned a corrective action for EMCDLYCTL for that processor:

LPC_SC->EMCDLYCTL = 0x1410;
LPC_EMC->DynamicReadConfig = EMC_DynamicReadConfig_RD(1);

however I could not find references to these settings in my project. The closest thing was the config of fsl_semc driver, but I don't have a good understanding whether that is even needed for what I'm trying to do. 

I tried setting the heap to match the configuration that was running on the SRAM_DTC setup (10 x 1024) however that resulted in the same problem as the 30 x 1024 heap size. 

I looked in the project linker definition for heap and stack placement and redefined the region for both to SDRAM and size to a ridiculous value (0xF4240) for each heap and stack, just in case this affects FreeRTOS usage, but my problem persisted. 

I believe I'm dealing with a misconfiguration in this setup for dynamically allocating memory resources out of SDRAM, but I am not sure what to try next. Any hints are appreciated.

0 Kudos
9 Replies

2,425 Views
lpcxpresso_supp
NXP Employee
NXP Employee

I've not been able to replicate this behaviour. When I reorder memory, the heap/stack settings remain mapped to the SDRAM (as long as I have referenced it by name rather than alias name).

I can only think that the specific order you are making changes is exposing a "hole" in when the IDE will force the regeneration of the linker script.

Try doing a clean, then rebuild - this will force a linker script regeneration. Then check what is shown in the linker output for the memory region usage (towards the bottom of the build console), as well as looking at in the linker map file and the generated linker script in the "Debug" (or "Release") folder of your project.

Regards,

MCUXpresso IDE Support

0 Kudos

2,425 Views
edw8
Contributor III

I always clean first before build. I don't believe that to be a problem. Similar to your experience, I switched my memory configuration where the SDRAM bank was not the first RAM bank, and I could not reproduce the problem. SP originated in the SDRAM region as did heap allocations with some basic test code. I tried several memory bank sequences and they all worked correctly.

So I went back to the drawing board. There are two ways I created starter bases for my project. The first is by creating a new project using the SDK facilities. That project was based on freertos (not baremetal) and included the default set of drivers and utilities with exception of the assert utility (addon). No middleware. Going thru the MCUXpresso IDE prompted screens for creating the project, I realized that it comes up with an invalid memory configuration. An extra SDRAM bank is added to the memory config list.

2018-03-29_11-38-13.png

At this point, I create the project with the default config. After project is created, I edit the config and take out the SDRAM bank, leaving the BOARD_SDRAM bank in place. When I click on the SDRAM entry, the dialog shows an invalid configuration error until I remove the redundant SDRAM entry.

2018-03-29_11-41-59.png

I then edit project settings again and change stack and heap regions to BOARD_SDRAM.

I clean, build, and debug. I set a breakpoint at the entry of the while loop and run. After hitting the breakpoint I check the SP and notice it is correctly placed in BOARD_SDRAM space.

2018-03-29_11-50-17.png

The second method I used to create a project base was to import a demo SDK example. I selected the FreeRTOS queue example. For both this method and the previous method I set the SDK debug console to UART and set the library type to Newlib (nohost).

This method presents a memory config block with a single SDRAM bank, however this project is set to run out of RAM. 

2018-03-29_11-54-10.png

I create the project and change project settings to have the project run out of FLASH, while setting Heap and Stack regions to BOARD_SDRAM. I add xip project driver source and add the XIP_EXTERNAL_FLASH preprocessor include.

I add a breakpoint at the log_init() call, clean, build and debug. When I hit the breakpoint I check the stack pointer and sure enough it is in SDRAM space.

I ran thru these two setups a few times with mixed results. With stack and heap regions set to BOARD_SDRAM I was able to see the stack pointer in the SRAM_DTC memory space. I don't have the exact trigger sequence and obviously it is not repeatable each time thru the procedure I described above, however I've seen it several times.

Currently my workaround is to ensure the BOARD_SDRAM region is the first RAM region.

0 Kudos

2,425 Views
lpcxpresso_supp
NXP Employee
NXP Employee

Information on MCUXpresso IDE's memory configuration, including placement of stack and the "standard" heap can be found in chapter 14, "Memory Configuration and Linker Scripts", of the MCUXpresso IDE v10.1 User Guide.

One thing to watch is that the heap referred to in the MCUXpresso IDE memory configuration is that used by the standard C library. This is generally not the heap that is used by FreeRTOS [in calls to pvPortMalloc() rather than the standard C malloc() routine].

For information on FreeRTOS own heap allocation, please see the FreeRTOS documentation :

Regards,

MCUXpresso IDE Support

0 Kudos

2,425 Views
edw8
Contributor III

Thank you for clarifying the difference in stack selection between standard malloc() calls and pvPortMalloc() calls. This makes total sense and after editing the project's FreeRTOSConfig.h settings for configTOTAL_HEAP_SIZE I was able to define larger task stacks and larger queues. This resolved an issue outside the context of what I had observed in my previous reply. 

I read the MCUXpresso IDE User Guide for 10.1.0 (Nov 14, 2017), specifically section 14.9.1 as it most closely resembles my configuration.

If I understand this correctly, when I change the Stack and Heap region to use my SDRAM bank, the memory bank order in the configuration editor should be disregarded.

2018-03-26_10-52-56.png

However when I reorder my memory banks so that SDRAM is not the first RAM bank listed,

2018-03-26_10-56-52.png

2018-03-26_10-57-11.png

The project uses Stack (standard and FreeRTOS) and Heap from SRAM, not from SDRAM. Setting aside FreeRTOS stack location for now, why would the above config result in either standard Stack or Heap to be SRAM specific (ie: 0x2020xxxx range instead of 0x8000xxxx range)?

0 Kudos

2,425 Views
edw8
Contributor III

Continuing saga with some optimistic results.

With the above init for SDRAM via the SEMC driver performing poorly (single bit errors for up to 34 words across the entire 32MB space on readback), we went back to basics.

1. Dumped the contents of the SEMC config register block (0x402F00xx space) and confirmed that the settings for some of the registers did not match.

SEMC reg dump and validation against values provided by Weidong Sun's scripts in this thread:

Does debug init SDRAM for xip app on MIMXRT1052? 

 -- MCR -- 0x10000004 --  confirmed OK!  -- IOCR -- 0x       8 --  MISMATCH! expecting: 0x    79A8  -- BMCR0 -- 0x   30524 --  confirmed OK!  -- BMCR1 -- 0x 6030524 --  confirmed OK!  -- BR[0] -- 0x8000001B --  confirmed OK!  -- BR[1] -- 0x       0 --  MISMATCH! expecting: 0x8200001B  -- BR[2] -- 0x       0 --  MISMATCH! expecting: 0x8400001B  -- BR[3] -- 0x       0 --  MISMATCH! expecting: 0x8600001B  -- BR[4] -- 0x       0 --  MISMATCH! expecting: 0x90000021  -- BR[5] -- 0x       0 --  MISMATCH! expecting: 0xA0000019  -- BR[6] -- 0x       0 --  MISMATCH! expecting: 0xA8000017  -- BR[7] -- 0x       0 --  MISMATCH! expecting: 0xA900001B  -- BR[8] -- 0x       0 --  MISMATCH! expecting: 0x      21  -- RESERVED_0 -- 0x       0 --  not evaluated ...   -- INTEN -- 0x       0 --  not evaluated ...   -- INTR -- 0x       1 --  not evaluated ...   -- SDRAMCR0 -- 0x     F31 --  confirmed OK!  -- SDRAMCR1 -- 0x  652922 --  confirmed OK!  -- SDRAMCR2 -- 0x   10920 --  confirmed OK!  -- SDRAMCR3 -- 0x50210A09 --  MISMATCH! expecting: 0x50210A08  -- NANDCR0 -- 0x       0 --  not evaluated ...   -- NANDCR1 -- 0x       0 --  not evaluated ...   -- NANDCR2 -- 0x   10410 --  not evaluated ...   -- NANDCR3 -- 0x       0 --  not evaluated ...   -- NORCR0 -- 0x       0 --  not evaluated ...   -- NORCR1 -- 0x       0 --  not evaluated ...   -- NORCR2 -- 0x       0 --  not evaluated ...   -- NORCR3 -- 0x       0 --  not evaluated ...   -- SRAMCR0 -- 0x       0 --  not evaluated ...   -- SRAMCR1 -- 0x  652922 --  not evaluated ...   -- SRAMCR2 -- 0x   10920 --  not evaluated ...   -- SRAMCR3 -- 0x50210A08 --  not evaluated ...   -- DBICR0 -- 0x      21 --  confirmed OK!  -- DBICR1 -- 0x  888888 --  confirmed OK!  -- RESERVED_1a -- 0x       0 --  not evaluated ...   -- RESERVED_1b -- 0x       0 --  not evaluated ...   -- IPCR0 -- 0x80000000 --  confirmed OK!  -- IPCR1 -- 0x       2 --  confirmed OK!  -- IPCR2 -- 0x       0 --  confirmed OK!  -- IPCMD -- 0x       A --  MISMATCH! expecting: 0xA55A000F  -- IPTXDAT -- 0x      33 --  confirmed OK!

2. Created a raw register write method to update the correct(?) values into the SEMC config reg block.

static void WaitIpCmdDone_SDRAM(void) {    SEMC_Type *pSemcBase = SEMC;    uint32_t intrReg;    do {        intrReg = pSemcBase->INTR;             } while ((intrReg & 0x3) == 0);}static void initSDRAMregs(void) {    SEMC_Type *pSemcBase = SEMC;    pSemcBase->MCR = 0x10000004;    pSemcBase->BMCR0 = 0x00030524;    pSemcBase->BMCR1 = 0x06030524;    pSemcBase->SDRAMCR0 = 0x00000F31;    pSemcBase->SDRAMCR1 = 0x00652922;    pSemcBase->SDRAMCR2 = 0x00010920;    pSemcBase->SDRAMCR3 = 0x50210A08;    // ===============================    // latching procedure    pSemcBase->IPCR0 = 0x80000000;    pSemcBase->IPCMD = 0xA55A000F;    WaitIpCmdDone_SDRAM();    pSemcBase->IPCR0 = 0x80000000;    pSemcBase->IPCMD = 0xA55A000C;    WaitIpCmdDone_SDRAM();    pSemcBase->IPCR0 = 0x80000000;    pSemcBase->IPCMD = 0xA55A000C;    WaitIpCmdDone_SDRAM();    pSemcBase->IPTXDAT = 0x00000033;    pSemcBase->IPCR0 = 0x80000000;    pSemcBase->IPCMD = 0xA55A000A;    WaitIpCmdDone_SDRAM();    pSemcBase->SDRAMCR3 = 0x50210A09;    // ===============================
}

This register config that got called from main runtime context initialized SDRAM operation allowing the entire SDRAM space to correctly write, read, and verify (see attached sdram_verified_ok.log).

Despite the proper SEMC register config, the project boots and runs with stack and heap configured in SRAM_DTC:

2018-03-07_16-18-35.png

2018-03-07_16-23-58.png

Changing the SDRAM memory segment to be located above SRAM_DTC results in a hard fault. Understandably this should be the case as there is no provision for configuring heap and stack to run from SDRAM. Making that change requires for SEMC config regs to be properly configured before any stack or heap is used by the project. 

I tried adding the SEMC block config with discrete register settings in the resetISR() handler. That along with customizing the SDRAM segment to follow hyperflash and relocating heap and stack in SDRAM failed to load the debug project on the MIMXRT1050-EVK

2018-03-07_16-41-01.png

I removed the resetISR() handler extra code, left SDRAM memory segment to follow Hyperflash and left heap/stack pointing to SDRAM. I then tried modifying the dcd_sdram[] config block in fsl_flexspi_nor_boot.c to get the SEMC config registers properly initialized before the project main runs. My understanding is that the DCD block (contents of dcd_sdram[]) is evaluated by the ROM based bootloader prior to the application's resetISR() handler running, however that assumption may be flawed. Either way, changing the SDRAM memory segment order, heap and stack region to SDRAM and executing the SEMC init out of the DCD block resulted in a launch error.

2018-03-07_16-47-20.png 

After this point nothing restored the project back to a running state. I restarted the MCUXpresso IDE several times and disconnected and reconnected the eval kit. Had to go thru a hyperflash mass erase procedure in order to redetect the DAPlink probe and reestablish a debug session.

After the mass erase, the DAPlink probe was identified again and the debug session resumed. I changed the order of the memory segment to have SDRAM follow hyperflash and changed stack/heap back to SDRAM. Entering debug mode did not cause a probe detect problem, but the main thread entered a SIGSTOP state.

2018-03-07_17-22-18.png

I'm guessing that there exists some anomalous startup behavior between evk reset after entering debug mode and availability of stack resources from SDRAM implying that the dcd_sdram[] block contents have not configured SEMC as intended. 

Will try further experimentation with relocation of stack pointer to reference SDRAM space manually after reset, while using SRAM_DTC for initial SEMC configuration.

0 Kudos

2,425 Views
thefallguy
Contributor IV

Out of reset, the stack will be setup to whatever value is placed in the vector table (address 0x0). As the external RAM is not configured, placing the stack in there will result in a Hard Fault. So, you need to boot with the stack placed into on-chip SRAM, configure the external RAM and then switch the stack pointer (remembering that after doing this, you will have no way to 'return' from the function doing this). As you will be doing this very early in ResetISR(), you will not be using an C library calls, so it is safe to place the heap in external RAM.

0 Kudos

2,426 Views
edw8
Contributor III

Fall Guy, thanks for your note. It seems I had to be a little more patient and wait for NXP to release their SDK v2.3 again in 2018-Mar-06 (it was originally released in 2017-Dec). This new SDK v2.3 included both project demo code and new project creation using a very different set of data in the dcd_sdram[] block instance. My understanding is that the boot loader reads out the device config data from this block and initializes processor registers for SDRAM configuration.

The new data set definitely allows the SDRAM to perform well for the validation test I described in one of my previous comments in this post. Even better news. One of my colleagues configured the stack location to SDRAM via MCUXpresso IDE project configuration:

2018-03-23_17-23-37.png

2018-03-23_17-24-11.png

And just like that, the project comes up with SDRAM device configuration working and with the stack functioning as expected from SDRAM space.

Unfortunately that did not fully resolve my problem. As you can see the heap is also configured to operate out of SDRAM, however after building the project we observed that the SRAM was used for heap allocation. As we stepped thru project initialization, we realized that our tasks, queues and buffer pools that were created via pvPortMalloc() were really located within SRAM space (0x2020xxxx region). This was unexpected given the Heap and Stack placement config shown above. 

Rearranging the memory sections within the project config to ensure that the SDRAM section followed the hyperflash section helped (assuming MCUXpresso IDE designers are paying attention to this and planning a fix for the next MCUXpresso IDE release):

2018-03-23_17-32-49.png

With the above configuration, running thru the project we encountered a hard fault. At first I incorrectly assumed this was another stack issue that was preventing allocation into SDRAM space, but single stepping thru project initialization confirmed that the hard fault came from a memcpy() call. The intent was to transfer a specific number of bytes from a const char * (flash string) into a global variable char array (also located in SDRAM). This same call worked fine when the SRAM sections resided between flash and SDRAM.

I changed the memcpy() call to a manual char transfer loop and that resolved the hard fault allowing the project to run completely from SDRAM resources. This is the code change:

2018-03-23_18-42-26.png

where the name member of the buffPoolDesc[] structure is

2018-03-23_18-44-02.png

and

2018-03-23_18-44-51.png

I don't see the flaw in the memcpy() call syntax, and can't really see where memory type matters (ie: why FLASH to SRAM copy works, but FLASH to SDRAM copy throws a hard fault).

Either way, I now have a workaround for operating strictly out of SDRAM.

0 Kudos

2,426 Views
edw8
Contributor III

Some more progress wrt SDRAM configuration on the MIMXRT1050-EVK. 

Followed additional bread crumbs (below)

Demo SEMC driver app for MIMXRT1052-EVK? 

EVK-MIMXRT1050 SDK middleware projects not available 

That led to examining the unofficial project archive:

<sdk-path>\SDK_2.3.0_EVK-MIMXRT1050.zip\boards\evkmimxrt1050\driver_examples\semc\sdram

where semc_sdram.c contains an SDRAM init method BOARD_InitSEMC() with contents matching the SDRAM IC available on the MIMXRT1050-EVK.

The code in BOARD_InitSEMC() was ported into the ResetISR() method in startup_mimxrt1052.c within my test project. The code block was placed immediately after the SystemInit() call at the top of the ResetISR() method.

The dependencies for this port included some local macros as well as the fsl_semc.c and fsl_semc.h driver source and header files.

These changes appear to be sufficient to provide write access to SDRAM locations beyond the first 4K words, however the write/read/verify test across the entire 32 MByte SDRAM memory space resulted in multiple instances of single bit errors on read-back.

The test code running to perform the write part of the test:

2018-02-26_17-02-40.png

The test code running to perform the read/verify part of the test:

2018-02-26_17-03-47.png

Various runs thru this test code produce varied readback failures. A sample run output log is attached. 

I am guessing that these bit errors are due to the current SDRAM timing configuration:

2018-02-26_17-12-27.png

Although this is an interesting learning experience, it feels like I am re-inventing the wheel for a process that is surely documented by an NXP/MCUXpresso app note written for the MIMXRT1050-EVK. 

0 Kudos

2,426 Views
edw8
Contributor III

I would like to add some additional information regarding a different configuration where I tried to validate SDRAM access and failed.

I imported a new freertos_queue demo project from the MCUXpresso SDK 2.3 and customized it to run from hyperflash (XiP) -- similar steps as above.

The memory configuration for this project is:

2018-02-23_16-32-08.png

I retained the original threads created by the demo example, but I gutted out the second write task:

2018-02-23_16-33-50.png

and modified the first write task to perform an SDRAM write/read/verify. Since the project ran from flash and used SRAM_DTC for stack/heap, I expected full access to the entire SDRAM space. 

2018-02-23_16-39-07.png

where this is declared as a global:

2018-02-23_16-40-08.png

My first intent was to cycle thru various write patterns with frequent bit rotate operations performed periodically at odd times and run across the entire SDRAM memory space (32 MB), however I encountered readback issues with most tests that span SDRAM space in excess of 4KB.

The first write/read/verify of the first 4KB starting from 0x80000000 completed as expected.

The second test attempted to write 8KB (2 * 1024 uint32_t) starting from 0x80000000. It seems that the first 4KB were overwritten by the second 4KB write patterns.

The third test attempted to write 12KB (3 * 1024 uint32_t) starting from 0x80000000. Similar to the second attempt, it seems that only the first 4KB of SDRAM were accessed in the write phase.

The fourth test attempted to write 12KB starting from 0x80000800. Similar to the second attempt, only the first 4KB of SDRAM were accessed in the write phase.

I attached the output of the fourth test that reflects the test code snips included above.

If anyone has any suggestions regarding either project configuration or additional settings needed to successfully address and use the entire SDRAM space I would appreciate it.

0 Kudos