LPC4337 external SDRAM options?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC4337 external SDRAM options?

2,100 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ZZZMQP on Wed May 18 05:56:02 MST 2016
Hi,

I'm working with the LPC4337 and need to add a significant amount of fast RAM (16+MByte) to buffer a data stream. What are my options?

EMC is the obvious choice, however, I need all SGPIO pins and USB0/1, maybe SD/MMC, and there doesn't seem to be a way to make EMC happen from a pin mux point of view (regardless of the package).

SPIFI would be the perfect interface, but I need RAM, not FLASH. Read [u]and[/u] write speed must be at least 25mByte/s, without write cycle limitations (continuously buffering). I found one Quad SPI SRAM chip (http://www.cypress.com/products/1-mb-quad-spi-nvsram), but it's only 128kB.

Any comments/ideas?

Thanks!

标签 (1)
0 项奖励
回复
6 回复数

1,843 次查看
lpcware
NXP Employee
NXP Employee
bump
0 项奖励
回复

1,842 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ZZZMQP on Sun Jun 05 12:53:15 MST 2016
I was able to configure a BGA256 device with all pins I need (attached).

I obtained a dev board with an LPC4357 and 32Mbyte external SRAM. (I will eventually move back to the 4337 chip as I don't need LCD, but otherwise it really doesn't matter I think).

I was able to migrate all hardware functions to the new board (SGPIO, USB, SDMMC etc). With the SDRAM itself, however, I haven't had success yet.

The board has a MT48LC8M32B2 SDRAM chip on it. The MCU (and peripheral clock) runs at 204 MHz. This is my SDRAM initialization function, based on code that came with the board (had to do a little updating and porting, but the settings remained unchanged):

/**********************************************************************
* $Id$SDRAM_Init.c2011-06-02
*//**
* @fileSDRAM_Init.c
* @briefThis file contains SCU_MODE_FUNCtions used to initialize SDRAM
* @version1.0
* @date02. June. 2011
* @authorNXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
**********************************************************************/
#include "chip.h"

/************************** PRIVATE DEFINITIONS *************************/
/* SDRAM Address Base for DYCS0*/
#define SDRAM_ADDR_BASE0x28000000

#define MS 8350  // for() loop count to delay 1 ms

/* SDRAM refresh time to 16 clock num */
#define EMC_SDRAM_REFRESH(freq,time)  \
  (((uint64_t)((uint64_t)time * freq)/16000000000ull)+1)

/*-------------------------PRIVATE SCU_MODE_FUNCTIONS------------------------------*/
/*********************************************************************
 * @briefCalculate EMC Clock from nano second
 * @param[in]freq - frequency of EMC Clk
 * @param[in]time - nano second
 * @return None
 **********************************************************************/
uint32_t NS2CLK(uint32_t freq,uint32_t time){
 return (((uint64_t)time*freq/1000000000));
}

/*********************************************************************
 * @briefInit the EMC Controller to connect ex SDRAM
 * @param[in]None
 * @return None
 **********************************************************************/
 void SDRAM_Init () {
uint32_t pclk, temp;
uint64_t tmpclk;
uint32_t i = 0;

Chip_SCU_PinMuxSet(2,9,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A0
Chip_SCU_PinMuxSet(2,10,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A1
Chip_SCU_PinMuxSet(2,11,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A2
Chip_SCU_PinMuxSet(2,12,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A3
Chip_SCU_PinMuxSet(2,13,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A4

Chip_SCU_PinMuxSet(1,0,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A5
Chip_SCU_PinMuxSet(1,1,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A6
Chip_SCU_PinMuxSet(1,2,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A7

Chip_SCU_PinMuxSet(2,8,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A8
Chip_SCU_PinMuxSet(2,7,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//A9
Chip_SCU_PinMuxSet(2,6,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A10
Chip_SCU_PinMuxSet(2,2,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A11
Chip_SCU_PinMuxSet(2,1,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A12
Chip_SCU_PinMuxSet(2,0,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//A13
Chip_SCU_PinMuxSet(6,8,(SCU_PINIO_FAST | SCU_MODE_FUNC1));//A14


Chip_SCU_PinMuxSet(1,7,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D0
Chip_SCU_PinMuxSet(1,8,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D1
Chip_SCU_PinMuxSet(1,9,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D2
Chip_SCU_PinMuxSet(1,10,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D3
Chip_SCU_PinMuxSet(1,11,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D4
Chip_SCU_PinMuxSet(1,12,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D5
Chip_SCU_PinMuxSet(1,13,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D6
Chip_SCU_PinMuxSet(1,14,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D7

Chip_SCU_PinMuxSet(5,4,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D8
Chip_SCU_PinMuxSet(5,5,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D9
Chip_SCU_PinMuxSet(5,6,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D10
Chip_SCU_PinMuxSet(5,7,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D11

Chip_SCU_PinMuxSet(5,0,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D12
Chip_SCU_PinMuxSet(5,1,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D13
Chip_SCU_PinMuxSet(5,2,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D14
Chip_SCU_PinMuxSet(5,3,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D15

Chip_SCU_PinMuxSet(0X0D,2,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D16
Chip_SCU_PinMuxSet(0X0D,3,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D17
Chip_SCU_PinMuxSet(0X0D,4,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D18
Chip_SCU_PinMuxSet(0X0D,5,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D19
Chip_SCU_PinMuxSet(0X0D,6,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D20
Chip_SCU_PinMuxSet(0X0D,7,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D21
Chip_SCU_PinMuxSet(0X0D,8,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D22
Chip_SCU_PinMuxSet(0X0D,9,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//D23

Chip_SCU_PinMuxSet(0X0E,5,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D24
Chip_SCU_PinMuxSet(0X0E,6,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D25
Chip_SCU_PinMuxSet(0X0E,7,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D26
Chip_SCU_PinMuxSet(0X0E,8,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D27
Chip_SCU_PinMuxSet(0X0E,9,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D28
Chip_SCU_PinMuxSet(0X0E,10,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D29
Chip_SCU_PinMuxSet(0X0E,11,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D30
Chip_SCU_PinMuxSet(0X0E,12,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//D31


Chip_SCU_PinMuxSet(6,11,(SCU_PINIO_FAST | SCU_MODE_FUNC3));// CKEOUT0
Chip_SCU_ClockPinMuxSet(0, (SCU_PINIO_FAST | SCU_MODE_FUNC0));// CLK0 connected to EMC_CLK0
Chip_SCU_ClockPinMuxSet(1, (SCU_PINIO_FAST | SCU_MODE_FUNC0));// CLK1 connected to EMC_CLK1
Chip_SCU_ClockPinMuxSet(2, (SCU_PINIO_FAST | SCU_MODE_FUNC0));// CLK2 connected to EMC_CLK3
Chip_SCU_ClockPinMuxSet(3, (SCU_PINIO_FAST | SCU_MODE_FUNC0));// CLK3 connected to EMC_CLK2

Chip_SCU_PinMuxSet(6,12,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//DQMOUT0
Chip_SCU_PinMuxSet(6,10,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//DQMOUT1
Chip_SCU_PinMuxSet(0X0D,0,(SCU_PINIO_FAST | SCU_MODE_FUNC2));//DQMOUT2
Chip_SCU_PinMuxSet(0X0E,13,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//DQMOUT3

Chip_SCU_PinMuxSet(6,4,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//CAS
Chip_SCU_PinMuxSet(6,5,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//RAS

Chip_SCU_PinMuxSet(1,6,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//WE
Chip_SCU_PinMuxSet(6,9,(SCU_PINIO_FAST | SCU_MODE_FUNC3));//DYCS0


/* Select EMC clock-out */
LPC_SCU->SFSCLK[0] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[1] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[2] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[3] = SCU_PINIO_FAST;

LPC_EMC->CONTROL = 0x00000001;
LPC_EMC->CONFIG  = 0x00000000;
LPC_EMC->DYNAMICCONFIG0    = 1<<14 | 2<<9 | 1<<7 | 0 << 12; /* 256Mb, 8Mx32, 4 banks, row=12, column=9 */

pclk = Chip_Clock_GetRate(CLK_MX_EMC);

LPC_EMC->DYNAMICRASCAS0    = 0x00000303; /* 1 RAS, 3 CAS latency */
LPC_EMC->DYNAMICREADCONFIG = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */

LPC_EMC->DYNAMICRP         = NS2CLK(pclk, 20);
LPC_EMC->DYNAMICRAS        = NS2CLK(pclk, 42);
LPC_EMC->DYNAMICSREX       = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICAPR        = 0x00000005;
LPC_EMC->DYNAMICDAL        = 0x00000005;
LPC_EMC->DYNAMICWR         = 2;
LPC_EMC->DYNAMICRC         = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICRFC        = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICXSR        = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICRRD        = NS2CLK(pclk, 14);
LPC_EMC->DYNAMICMRD        = 0x00000002;

for(i = 0; i < 100*MS; i++);/* wait 100ms */
LPC_EMC->DYNAMICCONTROL    = 0x00000183; /* Issue NOP command */

for(i = 0; i < 200*MS; i++);/* wait 200ms */
LPC_EMC->DYNAMICCONTROL    = 0x00000103; /* Issue PALL command */

LPC_EMC->DYNAMICREFRESH    = EMC_SDRAM_REFRESH(pclk,70); /* ( n * 16 ) -> 32 clock cycles */

for(i = 0; i < 200*MS; i++);/* wait 200ms */ /* wait 128 AHB clock cycles */

tmpclk = (uint64_t)15625*(uint64_t)pclk/1000000000/16;
LPC_EMC->DYNAMICREFRESH    = tmpclk; /* ( n * 16 ) -> 736 clock cycles -> 15.330uS at 48MHz <= 15.625uS ( 64ms / 4096 row ) */

LPC_EMC->DYNAMICCONTROL    = 0x00000083; /* Issue MODE command */

//Timing for 48/60/72MHZ Bus
 temp = *((volatile uint32_t *)(SDRAM_ADDR_BASE | (((3<<4)| 2UL)<<13))); /* 4 burst, 3 CAS latency 12 = (8+2+2) RBC */
 temp = temp;

LPC_EMC->DYNAMICCONTROL    = 0x00000000; /* Issue NORMAL command */

//[re]enable buffers
LPC_EMC->DYNAMICCONFIG0    |= 1<<19;
}



I added the RAM to the memory configuration (see attached).

My test code:
#define SDRAM_ADDR_BASE0x28000000
uint32_t *ramdata;

int main(void) {

board_SystemInit();
SystemCoreClockUpdate();
...

SDRAM_Init();

ramdata = (uint32_t *)SDRAM_ADDR_BASE;

*ramdata = 0x11223344;
...
}

For completeness reasons:
/* Set up and initialize hardware prior to call to main */
void board_SystemInit(void)
{
/* Setup system clocking and memory. This is done early to allow the
   application and tools to clear memory and use scatter loading to
   external memory. */

int i;

/* Enable Flash acceleration and setup wait states */
Chip_CREG_SetFlashAcceleration(MAX_CLOCK_FREQ);

/* Setup System core frequency to MAX_CLOCK_FREQ */
Chip_SetupCoreClock(CLKIN_CRYSTAL, MAX_CLOCK_FREQ, true);

/* Setup system base clocks and initial states. This won't enable and
   disable individual clocks, but sets up the base clock sources for
   each individual peripheral clock. */
for (i = 0; i < (sizeof(InitClkStates) / sizeof(InitClkStates[0])); i++) {
Chip_Clock_SetBaseClock(InitClkStates.clk, InitClkStates.clkin,
InitClkStates.autoblock_enab, InitClkStates.powerdn);
}

/* Reset and enable 32Khz oscillator */
LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2));
LPC_CREG->CREG0 |= (1 << 1) | (1 << 0);
}


When executing '*ramdata = 0x11223344;', I end up with "[color=#f00]No source available for "0xfffffe"[/color]".

Does anybody see off hand what's wrong or missing?

Thank you.
0 项奖励
回复

1,842 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ZZZMQP on Mon May 23 13:26:09 MST 2016
Thank you, bavarian.

I will take another look. I may have used more EMC interface pins than absolutely required.
0 项奖励
回复

1,842 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Mon May 23 02:07:00 MST 2016
With a 256BGA package it should be possible to use EMC and SGPIO and some other stuff in parallel.

I configured in the pinmux tool the following interfaces: 
[list]
  [*]  SGPIO with all 16 pins
  [*]  EMC for 16-bit SDRAM
  [*]  SD-Card with 4-bit interface (no control pins like VOLT0 etc)
  [*]  USB0 with all pins except USB0_PPWR (this is the only conflict with EMC D0)
  [*]  USB1 without ULPI pins
[/list]

Maybe you play a little bit around with the Java pinmux tool, the jar file and my pre-configuration is attached. If you don't have Java on your computer you can run it with a converter:

http://www.ikvm.net/download.html

Go into the bin folder of this tool and you can run the pinmux tool with:  ikvm -jar PinMux.jar

Regards,
NXP Support Team
0 项奖励
回复

1,842 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ZZZMQP on Thu May 19 16:46:36 MST 2016
Hi lpcmunich,

thank you very much for your answer. I was afraid that's the case.

SGPIO is our workhorse and actually acquires the incoming stream(s). Two separate 4bit wide inputs with DV and 25MHz CLK and DMA transfers use up all but two SGPIO pins. Works like a charm - so not much I can change here.

I'm just curious why they make cheap Quad SPI FLASH chips of almost any size and Quad SPI RAM is only available in the low kB range and super expensive...?

Anyway, the reason for the buffering is that the incoming data stream is sent out on USB using usbd_rom_libusb (512kB BULK endpoint), which generally works fine. However, the PC side (using libusb/libusbk) has gaps in the bulk EP polling once other things happen on the PC and the data stream reaches about 20% of the 200Mbit/s (even running as a high priority task). The gap can be anything from 5 to 30++ms (depending on the PC and load), which translates into several hundred of kB or even a couple of MB of data (depending on the packet sizes etc). So the PC seems to be the bottleneck, but we have to tolerate different systems and not all will have optimal performance (and not even an i7 with lots of RAM and SSD runs without gaps). Means, even doubling the on-chip RAM by using flashless parts would not nearly close the gap...

So, what can we do...  maybe we need to look into adding another MCU (potentially another LPC4337) that has all pins available for a standard EMC interface and uses SPI(FI) to receive the data stream from the first MCU into external SRAM and and passes it right on to the USB stack. That would double the MCU cost and PCB real estate (and complexity), so less than optimal, but I don't see a lot of other options here...

That being said..
1. Do you see any other options in this scenario?
2. Is there a large SRAM chip with EMC interface (16+MB) which you can recommend and have an example ready to run out of the box (HW and SW side) to save some development time?

Thanks again for your help!
0 项奖励
回复

1,842 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lpcmunich on Thu May 19 05:41:34 MST 2016
Hi ZZZMQP,
The LPC4337 and other flash parts in the family have quite limited internal RAM.
If you look at the flashless parts in the family, you might get in excess of 264kByte.
But if you really need 16+MByte, the only option is to use EMC and that means sacrifice some of the SGPIO pins.

0 项奖励
回复