LPC4357: using external SDRAM as data/program-memory

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

LPC4357: using external SDRAM as data/program-memory

5,398 Views
hartmutmeyer
Contributor II

I have available the EVB LPC4357 with external 256 Mb SDRAM MT48LC16M16A2 and using Keils uVision-IDE.

My final application requires several MB of RAM, therefore execution from SRAM is not possible because

of the limited size.

 

The board and LCD is working with examples, the timing-setup for the SDRAM seems to be ok so far.

( At least the LCD is working using the framepointer... ).

But if I enable the external SDRAM starting at 0x2800.0000 or later  in the uVision-setup as external RAM1

there will be an error.

Basicaly, the whole application should start from SDRAM, internal SRAM may be disabled.

I read about moving all required data from ROM to SDRAM after booting and mapping addresses,

but I couldn' find an illustrative example so far.

It is known that execution-speed will be much lower using external SDRAM, but this is not so important for me.

 

Is there an example available somewhere showing the technics

or some usefull hints how to proceed ?

Labels (1)
Tags (1)
0 Kudos
Reply
6 Replies

3,378 Views
bernhardfink
NXP Employee
NXP Employee

I don't have a convenient example available yet, but I keep looking for it.

What you need to consider:

  • Keil µVision can do the relocation of a complete object file for you, either by using the UI way or by using a scatter file. So this is easy going.
  • But you need to have the SDRAM interface set up before the code gets relocated.
  • The relocation and the zero-initialization is done in __main. This function is called from the startup.s file. Before there is SystemInit(), where you need to set up the PLL and the dynamic EMC interface. After that you can jump to __main.
  • As alternative you could of course do things manually, examples for such copy routines can be found on the net for various ARM controllers and compiler types.

Regards,

NXP Support Team

0 Kudos
Reply

3,378 Views
bernhardfink
NXP Employee
NXP Employee

Thanks for the example project. That's always the best way to get help ;-)

Unfortunately I didn't have the right hardware in place to test it, but I loaded it on another board and saw a problem with the clock setup. When you do a SystemCoreClockUpdate (), I don't think that you get back an updated clock value. After this function there should be the PLL frequency in SystemCoreClock (102MHz), but there is still the CLK_IRC with 12MHz. And with these 12MHz you jump into the SDRAM setup. Maybe hardcode it to 102MHz before you go into the SDRAM setup.

void SystemCoreClockUpdate (void)

{

  /* Check BASE_M4_CLK connection */

  uint32_t base_src = (LPC_CGU->BASE_M4_CLK >> 24) & 0x1F;

  /* Update core clock frequency */

  SystemCoreClock = GetClockFreq (base_src);    //  THIS MIGHT NOT RETURN THE CORRECT FREQUENCY !!!

}

Regards,

NXP Support Team

0 Kudos
Reply

3,378 Views
bernhardfink
NXP Employee
NXP Employee

Hello Hartmut,
I can't see a generic mistake in your software setup. I can't test it with a display because I don't have this standard display for the element14 LPC4357-EVB available. However, I see that the software runs fine from internal flash and also if I map it to internal SRAM.

To execute from SDRAM you need to do the following:

  • Click with a right mouse click on main.c and go to Options.
  • Assign the SDRAM as RO and RW memory as shown in the attached picture.
  • DO NOT "enable the SDRAM" in the target options of Keil µVision ! (see attached picture). This would mean that the linker uses this memory right from the beginning, at a time where the physical interface is not set up.
  • startup.s and SystemInit will still need to run from flash, the SDRAM interface is set up in there, the compiler will implement code to relocate main.o to SDRAM and the executes this object from there.
  • Any other object and also constant data like BMP data can be positioned in SDRAM the same way
  • Sharing the SDRAM bus for executable code, constant data and the framebuffer is sub-optimal, I would recommend to use the internal flash for executable code and use the SDRAM for heap and for the display framebuffer.

P.S. How can you be happy when your chess program runs with an STM32 :smileywink:

The LPC4357 provides much more bandwidth if you use it the right way.

Regards,

NXP Support Team

0 Kudos
Reply

3,378 Views
hartmutmeyer
Contributor II

Hello Bernhard,

I have thought a bit about the heap-topic,

as a result it looks like that assigning to much heap already in startup.s

fails

because the external SDRAM is still not ready before the jump to main

occures.

Therefore the max heap is limited by the value of  IRAM1.

How can I assign heap the best way in this case ?

0 Kudos
Reply

3,378 Views
bernhardfink
NXP Employee
NXP Employee

Hello Hardy,

there is no limitation for the heap. It can be as large as the external memory. You only need to make sure that it's declared in the right way and that the SDRAM interface is set up when the embedded libraries initialize and use the heap.

There is absolutely no rule that the heap size must be defined in startup.s.there is even no rule that the startup file must be in assembler, it can be in C-code as well.

What memory you declare to be there is important. Think thoroughly about the way the linker works. You declared the internal memory to be available for the linker (0x10000 bytes at address 0x10000000), that's the limit for the linker.

You did not declare the SDRAM at 0x28000000 to be available for the linker. For a good reason, because otherwise the linker might use it before it is set up. A viscious circle :smileywink:

Anyway, you can declare the heap position and size in a different way, then you only need to make sure that you don't use the heap before the SDRAM interface has been enabled.

Look in the Keil forum for more info:      http://www.keil.com/support/man/docs/armlib/armlib_chr1358938929242.htm

Regards,

NXP Support Team

0 Kudos
Reply

3,378 Views
hartmutmeyer
Contributor II

Hello Bernhard,

I have found now a working configuration for my application using the LPC4357 with the mentioned external 32 MB-SDRAM ( 256 Mbits ).

I am using a scatter-loading description-file, this is recommended in case the application is more complex.

( The scatter-file will be found under "Options for Target -> Linker" in uVision, using this feature requires a full-version ).

For my application this file actualy looks like this:

( The decimal-point is only for better readability )

LR_IROM1  0x1A00.0000  0x0008.0000  {

  ER_IROM1  0x1A00.0000  0x0008.0000   {

     *.o (RESET, +FIRST)

     *(InRoot$$Sections)

     .ANY (+RO)

}

RW_IRAM1  0x1000.0000  0x0000.8000 {

   system_lpc43xx.o  (+RW )

}

RW_IRAM2  0x2000.0000  0x0001.0000 {

   startup_lpc43xx.o  (+RW +ZI)

}

RW_RAM1  0x2800.0000  0x01F0.0000 {

   .ANY  (+RW +ZI)

}

}

The Framepointer required for LCD-output ( if used ) is located at 0x29F0.0000 using the last 1 MB of the available SDRAM.

( working well for my aplication, however the demand on RAM is not clarified ).

In general, the problem using the LPC4357 is that the SDRAM needs to be initialized before it can be used for the application.

The initialisation is done in startup_lpc43xx.s together with system_lpc43xx.c and execution must be done in internal RAM.

For applications with large demands on heap-space the internal RAM is usualy not big enough, external RAM must be used.

It is possible to assign system_lpc43xx.o and startup_lpc43xx.o to 2 different internal RAM-regions like shown in the example.

This has the advantage of having nearly 64 K of stack-space available within IRAM2 in case this is required ( like in my application ).

In most cases it should be sufficient to place both files only in 1 IRAM-region and leave the other empty.

Inside startup_lpc43xx.s I have assigned now for heap and stack:

Stack_Size    EQU   0x0000.F000

Heap_Size    EQU   0x0000.0400

The stack is defined here with 60 K, nearly the limit of what is possible.

The critical point now is, that all this is still not working until there will be placed a command for initialising the heap.

This command I have added to the end of system_LPC43xx.c, after the external memory-Controller will be configured:

...

/*  Configure External memory Controller */

    SystemInit_ExtMemCtl ();

/* Configure external heap */

   _init_alloc(0x2880.1000, 0x29F0.0000);        // allocation of heap inside region RW_RAM1 ( base, top ).

This range spans nearly 24 MB heap in my application but all may need to be adjusted according to the requirements.

The first 8 MB inside RW_RAM1 is reserved for program-data ( this is the range from 0x2800.0000 to 0x2880.0000 ).

It is important not to start with heap-allocation directly at the boundary ( 0x2880.0000 ), this fails for my application.

Therefore the heap starts at 0x2880.1000 ( as an example ).

Of course to make all this working it is required to have working files for system_lpc43xx.c and startup_lpc43xx.s available,

Esspecialy the timing-setup for the SDRAM in use must be in order of course.

For the 32 MB-SDRAM in use I made 1 additional change inside the configuration:

LPC_EMC->DYNAMICCONFIG0  =  (0x05)<<7;

My application ( a modern chess-engine ) using nearly the 32 MB RAM available ( mainly for hash-tables ) has proved to be working very well now.

However, the recommended way to define stack and heap is using the region-model and not using "_init_alloc()".

0 Kudos
Reply