Forums

AT91RM9200 and 16-bit SDRAM not working

Started by Stef October 18, 2005
Hello All,

I am trying to get a 16-bit SDRAM (MT48LC16M16A2-75) to work with the
AT91RM9200 and no matter what I try, it fails to work properly:

Hardware connections:
AT91RM9200  MT48LC16M16A2
----------  -------------
D0-15       DQ0-15
A2-A11      A0-A9
SDA10       A10
A13-A14     A11-A12
BA0/1       BA0/1
SDCKE       CKE
SDCK        CLK
\BS0/1      DQML/H
\RAS        \RAS
\CAS        \CAS
\SDWE       \WE
\SDCS       \CS

Init code:
	volatile int *pRegister;

	pRegister = (int *)0xFFFFFF98;	// SDRAMC_CR
	*pRegister = 0x2188C159;

	pRegister = (int *)0xFFFFFF90;	// SDRAMC_MR
	*pRegister = 0x00000012;	// 16-bit, precharge all on access
	pRegister = (int *)0x20000000;
	*pRegister = 0; 
	pRegister = (int *)0xFFFFFF90;	// SDRAMC_MR
	*pRegister = 0x00000014;	// 16-bit, refresh on access 
	pRegister = (int *)0x20000000;	// MT48LC16M16A2TG-75 requires 2 refreshes
	*pRegister = 0;                 // But do 8 like all examples 
	*pRegister = 0; 
	*pRegister = 0; 
	*pRegister = 0; 
	*pRegister = 0; 
	*pRegister = 0; 
	*pRegister = 0; 
	*pRegister = 0; 
	pRegister = (int *)0xFFFFFF90;	// SDRAMC_MR
	*pRegister = 0x00000013;	// 16-bit, Load mode register on access 
	pRegister = (int *)0x20000040;  // Address will go in mode reg. mode must be 0x020
	*pRegister = 0; 

  
	pRegister = (int *)0xFFFFFF90;	// SDRAMC_MR
	*pRegister = 0x00000010;	// 16-bit, normal mode on access  
	pRegister = (int *)0x20000000;
	*pRegister = 0;  


	pRegister = (int *)0xFFFFFF94;	// SDRAMC_TR
	*pRegister = 0x000002E0; 
	pRegister = (int *)0x20000000;
	*pRegister = 0; 


I've played around with the value of SDRAM_CR, the number of refreshes and 
the addres vor the mode register set, but no change. After this init
procedure, I see refresh cycles every 15 us.

When I write the entire SDRAM with 0x0001 and then read back, all I get is
0xFFFF. When I write and immediately read the same location, I mostly
get the right value back, but in about 1 out of 2000 (seems random) I get
0xFFFF instead of the right value (0x0001). And the wrong value is always
0xFFFF, nothing else.


Any ideas what to try next?

-- 
Stef    (remove caps, dashes and .invalid from e-mail address to reply by mail)

You're definitely on their list.  The question to ask next is what list it is.
Stef wrote:
> Hello All, > > I am trying to get a 16-bit SDRAM (MT48LC16M16A2-75) to work with the > AT91RM9200 and no matter what I try, it fails to work properly: >... > When I write the entire SDRAM with 0x0001 and then read back, all I get is > 0xFFFF. When I write and immediately read the same location, I mostly > get the right value back, but in about 1 out of 2000 (seems random) I get > 0xFFFF instead of the right value (0x0001). And the wrong value is always > 0xFFFF, nothing else.
Sound like noise or unmatched impedance on the signal/data lines. SDRAM layouts are very tricky. If you don't have enough shielding and impedance matching, you are looking for troubles.
> > Any ideas what to try next?
Get someone to review your layouts.
> > -- > Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) > > You're definitely on their list. The question to ask next is what list it is.
For this part you should generate an auto refresh every 7.81us on
average. You could also try setting the cas latency to 3 or 4. Another
trick is to slow down the SDRAM interface to a much slower clock rate.
Finally, SDRAM designs need a good understanding of the memory
controller settings as well as the hardware and layout.

Ken
www.claymore-electronic.co.uk

In comp.arch.embedded,
linnix <me@linnix.info-for.us> wrote:
> >Stef wrote: >> Hello All, >> >> I am trying to get a 16-bit SDRAM (MT48LC16M16A2-75) to work with the >> AT91RM9200 and no matter what I try, it fails to work properly: >>... >> When I write the entire SDRAM with 0x0001 and then read back, all I get is >> 0xFFFF. When I write and immediately read the same location, I mostly >> get the right value back, but in about 1 out of 2000 (seems random) I get >> 0xFFFF instead of the right value (0x0001). And the wrong value is always >> 0xFFFF, nothing else. > >Sound like noise or unmatched impedance on the signal/data lines. >SDRAM layouts are very tricky. If you don't have enough shielding and >impedance matching, you are looking for troubles. >
I have solid power planes (ground and 3V3) on the entire board and every power pin of the SDRAM is bypassed with a 100nF capacitor. So I'm OK on the shielding part. The SDRAM is very close to the CPU and the data/address bus to the rest of the board is separated by means of buffers. Total trace length between CPU, SDRAM and buffer is small, but no special care is taken to match the lines. The problem remains the same if I reduce the clock rate to 36MHz. If the problem is with the signal matching, I would expect more random values and not correct OR 0xFFFF, wouldn't you? -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) I never met a man I didn't want to fight. -- Lyle Alzado, professional football lineman
In comp.arch.embedded,
KenHopkins <k.hopkins@btinternet.com> wrote:
>For this part you should generate an auto refresh every 7.81us on >average. You could also try setting the cas latency to 3 or 4. Another >trick is to slow down the SDRAM interface to a much slower clock rate. >Finally, SDRAM designs need a good understanding of the memory >controller settings as well as the hardware and layout. >
You are right on the refresh, but unfortunately reducing the time between auto refreshes to 7us does not change the behaviour. The AT91RM9200 SDRAM controller only allows a CAS latency setting of 2. I have reduced the clock from 72MHz to 36MHz, no effect. Should I try to go down even further? I did find an error in my initialization: I was doing 32-bit accesses in the init phase instead of 16-bit. But aparently the SDRAM controller already ignored this during init as there is no visible change on the generated waveforms. Although the layout may not be optimal (lines are short but not matched, full power planes, all power pins bypassed with 100nF), I think it is my understanding of the settings that is the problem. Any pointers? I just discovered that the SDRAM's data outputs remain Hi-Z during a read cycle and all I'm reading back is the pulled up bus. Pulling a line down with a resistor changes the read-out value. What may cause this behaviour and how should a read cycle normally look? -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) "You're just the sort of person I imagined marrying, when I was little... except, y'know, not green... and without all the patches of fungus." -- Swamp Thing
In news:81548$4354fbb0$54f63171$17603@publishnet.news-service.com,
Stef <stef33d@yahooI-N-V-A-L-I-D.com.invalid> typed:
> Hello All, > > I am trying to get a 16-bit SDRAM (MT48LC16M16A2-75) to work with the > AT91RM9200 and no matter what I try, it fails to work properly: > > Hardware connections: > AT91RM9200 MT48LC16M16A2 > ---------- ------------- > D0-15 DQ0-15 > A2-A11 A0-A9 > SDA10 A10 > A13-A14 A11-A12 > BA0/1 BA0/1 > SDCKE CKE > SDCK CLK > \BS0/1 DQML/H > \RAS \RAS > \CAS \CAS > \SDWE \WE > \SDCS \CS > > Init code: > volatile int *pRegister; > > pRegister = (int *)0xFFFFFF98; // SDRAMC_CR > *pRegister = 0x2188C159; > > pRegister = (int *)0xFFFFFF90; // SDRAMC_MR > *pRegister = 0x00000012; // 16-bit, precharge all on access > pRegister = (int *)0x20000000; > *pRegister = 0; > pRegister = (int *)0xFFFFFF90; // SDRAMC_MR > *pRegister = 0x00000014; // 16-bit, refresh on access > pRegister = (int *)0x20000000; // MT48LC16M16A2TG-75 requires 2 > refreshes > *pRegister = 0; // But do 8 like all examples > *pRegister = 0; > *pRegister = 0; > *pRegister = 0; > *pRegister = 0; > *pRegister = 0; > *pRegister = 0; > *pRegister = 0; > pRegister = (int *)0xFFFFFF90; // SDRAMC_MR > *pRegister = 0x00000013; // 16-bit, Load mode register on access > pRegister = (int *)0x20000040; // Address will go in mode reg. mode > must be 0x020 *pRegister = 0; > > > pRegister = (int *)0xFFFFFF90; // SDRAMC_MR > *pRegister = 0x00000010; // 16-bit, normal mode on access > pRegister = (int *)0x20000000; > *pRegister = 0; > > > pRegister = (int *)0xFFFFFF94; // SDRAMC_TR > *pRegister = 0x000002E0; > pRegister = (int *)0x20000000; > *pRegister = 0; > > > I've played around with the value of SDRAM_CR, the number of > refreshes and > the addres vor the mode register set, but no change. After this init > procedure, I see refresh cycles every 15 us. > > When I write the entire SDRAM with 0x0001 and then read back, all I > get is 0xFFFF. When I write and immediately read the same location, I > mostly > get the right value back, but in about 1 out of 2000 (seems random) I > get 0xFFFF instead of the right value (0x0001). And the wrong value > is always 0xFFFF, nothing else. > > > Any ideas what to try next?
Are you sure you load the mode register correctly? In my AT91RM9200 with 32-bit SDRAM, I want to load the SDRAM mode register with 0x0020, and since CPU A2-11 --> SDRAM A0-9, I use address 0x0080 on the CPU pins. It works. And are you sure you shouldn't use CPU A1-10 --> SDRAM A0-9 with your 16-bit SDRAM? The datasheet isn't clear -- figure 13-2 suggests A0-9 --> A0-9 for 32-bit SDRAM which is definitely wrong. Karl Olsen
At 36Mhz I would think that cas latency of 2 should be OK. If you have
a scope or logic analyzer it may be time to use them. Are you
generating chip select, RAS, CAS and Address synchronous to the clock.
If the data lines are tri-state during a read then are you generating
the read cycle correctly ? What about series terminations ? Are the
DRAM and chip on the same power rail ? Have you tried more than one
board ?

If you check the Micron datasheet for your part you should be able to
see what read cycles look like. All signal are valid on the rising edge
of the clock

Ken
www.claymore-electronic.co.uk

Stef wrote:
> I have solid power planes (ground and 3V3) on the entire board and every > power pin of the SDRAM is bypassed with a 100nF capacitor. So I'm OK on
Actually you might be better off with smaller capacitors. Check the impedance over frequency characteristics of the capacitors you are using. Greetings, Frieder
In comp.arch.embedded,
KenHopkins <k.hopkins@btinternet.com> wrote:
>At 36Mhz I would think that cas latency of 2 should be OK. If you have >a scope or logic analyzer it may be time to use them. Are you >generating chip select, RAS, CAS and Address synchronous to the clock. >If the data lines are tri-state during a read then are you generating >the read cycle correctly ? What about series terminations ? Are the >DRAM and chip on the same power rail ? Have you tried more than one >board ? >
I have a 2+16 HP scope, it's already connected to some lines, I will connect the others. CPU and SDRAM are on the same power rail. No series termination. The schematics are somewhat based on the AT91RM9200's eval board which has no termination either. I have tested only 1 board up to now but have tested on another board in the past. This board is of simular design and had the SDRAM stuck on as a "bonus". Unfortunately we where not allowed to get to the root of the problem there before designing this board. But as the problems look very simular I am still betting on software probles rather than hardware problems for now.
>If you check the Micron datasheet for your part you should be able to >see what read cycles look like. All signal are valid on the rising edge >of the clock >
Yes they are in there, but which one? I find these SDRAM datasheets a bit difficult to read as I have only used SRAM in the past, but I'll get used to it I suppose. -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) "Success covers a multitude of blunders." -- George Bernard Shaw
In comp.arch.embedded,
Karl Olsen <kro@nospam.post3.tele.dk> wrote:
>In news:81548$4354fbb0$54f63171$17603@publishnet.news-service.com, >Stef <stef33d@yahooI-N-V-A-L-I-D.com.invalid> typed:
>> pRegister = (int *)0xFFFFFF90; // SDRAMC_MR >> *pRegister = 0x00000013; // 16-bit, Load mode register on access >> pRegister = (int *)0x20000040; // Address will go in mode reg. mode >> must be 0x020 *pRegister = 0; >> >Are you sure you load the mode register correctly? In my AT91RM9200 with >32-bit SDRAM, I want to load the SDRAM mode register with 0x0020, and since >CPU A2-11 --> SDRAM A0-9, I use address 0x0080 on the CPU pins. It works. >
Reasonably sure, I verified with a scope that A5 is high during the load mode register command. But I will check this again. In 16-bit mode, the Column/Row lines of the SDRAM controller are connected differently to the CPU core address lines than when in 32-bit mode. So I had to shift 0x80 one bit to the right.
>And are you sure you shouldn't use CPU A1-10 --> SDRAM A0-9 with your 16-bit >SDRAM? The datasheet isn't clear -- figure 13-2 suggests A0-9 --> A0-9 for >32-bit SDRAM which is definitely wrong. >
It indeed is confusing, here's how I read the datasheet: The chapter on the EBI shows the SDRAM controller lines A0-A9 are mapped to EBI (is external) pins A2-A11, not depending on the buswidth. The chapter on the SDRAM controller says how the cpu core lines are mapped to row/column, depending on buswidth. The SDRAM controller will output the row or column on _it's_ lines A0-A9 (and the rest of them), which are the external pins A2-A12. In my opinion your figure 13-2 (in doc1768.pdf they are called figure 87 and 88) is not wrong, but you have to remember it shows SDRAM controller A0-A9, not EBI pins. -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail) Secretary's Revenge: Filing almost everything under "the".