Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

DRAM + dsPIC30F Help!

Status
Not open for further replies.
In my DIG class we're working on interfacing a DRAM chip, specifically the **broken link removed** chip, to the dsPIC30F4011.

We quickly went over some sample code in class but not much info was given, so please forgive me if Ive overlooked something obvious.

According to the datasheet, I need to refresh 256 times every 4mS. I have set up timer1 as such and verified the timer1 interrupt occurs every 4mS.

My code tries to do the following:
- write 0xA0 to 0x1234
- read the data back
- turn on an LED if the data was read back correctly.

Right now, I read back 0x20 no matter what I try. Im sure there's a problem, I just need another set of eyes to see it.

Also, the way Ive decided to do addressing is as follows:
- 16bit address which is divided into a row and column
(this part is assumed - my teacher wouldnt give me a straight answer. I dont know if you can actually do this or not - I dont understand how many rows and columns there are)

In the attached code, Ive commented out the read/write code I tried to write from the timing diagrams in the datasheet. I also tried more logical code, which is what returns 0x20. Any advice is greatly appreciated!

Code:
#include <p30f4011.h>

void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void);
void timerInit(void);
void portInit(void);
void delayCycles(int);
unsigned char read(unsigned short);
void write(unsigned short, unsigned char);

int i; // refresh counter
unsigned char row, col;

#define CAS PORTFbits.RF0
#define RAS PORTFbits.RF1
#define OE PORTFbits.RF4
#define W PORTFbits.RF5
#define SUCCESS PORTFbits.RF6

// pin setup:
// portb - a0-a7
// porte - d0-d3
// f0 - /cas
// f1 - /ras
// f4 - /oe
// f5 - /we
// f6 - success led

int main(void)
{
	portInit();
	timerInit();

	unsigned char data = 0xA0;
	unsigned short address = 0x1234;
	
	write(address, data);
	delayCycles(2000);
	TRISE = 0xFF;
	unsigned char temp = read(address);

	if (temp == data)
		SUCCESS = 1;

	while(1);

	return 0;
}								

void portInit()
{
	// pin setup:
	// portb - a0-a7
	// porte - d0-d3
	// f0 - /cas
	// f1 - /ras
	// f4 - /oe
	// f5 - /we
	
	ADPCFG = 0xFF;
	TRISB = 0x00;
	TRISE = 0x00;
	TRISF = 0x00;

	CAS = 1;
	RAS = 1;
	OE = 1;
	W = 1;
}

void timerInit()
{
	PR1 = 500; // 8uS per tick = 500 ticks
	T1CON = 0; // clear t1con
	T1CONbits.TCKPS = 1; // prescale 8
 	IFS0bits.T1IF = 0; // clear flag
	IPC0bits.T1IP = 7; // high prio
 	IEC0bits.T1IE = 1; // enable interrupt
	T1CONbits.TON = 1; // start counting
}

void _T1Interrupt(void)
{
	// i should happen every ~4ms

	for (i = 0; i < 256; i++)
	{
		CAS = 0;
		//delayCycles(50);
		RAS = 0;
		//delayCycles(50);
		CAS = 1;
		//delayCycles(50);
		RAS = 1;
		//delayCycles(50);
	}

 	IFS0bits.T1IF = 0;
}

void delayCycles(int cycles)
{
	while (cycles-- > 0);
}


unsigned char read(unsigned short address)
{
	unsigned char row = address / 8;
	unsigned char col = address % 8;
	unsigned char temp;

	__asm__ volatile("disi #0x3FFF"); /* disable interrupts */
/*
	PORTB = row;
	delayCycles(50);
	RAS = 0;
	delayCycles(50);
	W = 1;
	delayCycles(50);
	PORTB = col;
	delayCycles(50);
	CAS = 0;
	delayCycles(50);
	OE = 0;
	delayCycles(50);
	temp = PORTE;
	delayCycles(50);
	CAS = 1;
	delayCycles(50);
	OE = 1;
	delayCycles(50);
	RAS = 1;
	delayCycles(50);
*/

	PORTB = row;
	delayCycles(10);
	RAS = 0;
	delayCycles(10);
	PORTB = col;
	delayCycles(10);
	CAS = 0;
	delayCycles(10);
	TRISE = 0xFF;
	delayCycles(10);
	OE = 0;
	delayCycles(10);
	temp = PORTE;
	delayCycles(10);
	OE = 1;
	delayCycles(10);
	RAS = 1;
	delayCycles(10);
	CAS = 1;
	delayCycles(10);

	TRISE = 0x00;	

	__asm__ volatile("disi #0x0000"); /* enable interrupts */

	return temp;
}

void write(unsigned short address, unsigned char data)
{
	unsigned char row = address / 8;
	unsigned char col = address % 8;

	__asm__ volatile("disi #0x3FFF"); /* disable interrupts */
	/*
	PORTB = row;
	delayCycles(50);
	RAS = 0;
	delayCycles(50);
	W = 0;
	delayCycles(50);
	PORTE = data;
	delayCycles(50);
	PORTB = col;
	delayCycles(50);
	CAS = 0;
	delayCycles(50);
	W = 1;
	delayCycles(50);
	CAS = 1;
	delayCycles(50);
	RAS = 1;
	delayCycles(50);
*/

	PORTB = row;
	delayCycles(10);
	RAS = 0;
	delayCycles(10);
	PORTB = col;
	delayCycles(10);
	CAS = 0;
	delayCycles(10);
	PORTE = data;
	delayCycles(10);
	W = 0;
	delayCycles(10);
	W = 1;
	delayCycles(10);
	CAS = 1;
	delayCycles(10);
	RAS = 1;
	delayCycles(10);

	__asm__ volatile("disi #0x0000"); /* enable interrupts */
}
 
Ive seen that document before, and theres another floating around aswell. What I dont understand about theirs is that there is a low and high address bus, on ports b and c respectively. My address bus is only 8 bits wide... Theirs has 8 lsbs and 2 msbs for each column and row address. Other than that our code is the same, in operation anyway
 
Well, one of the problems was that I was trying to write 0xA0 to a 4-bit data line... Address was also way too high (max is 0x7FF with my code)

Still not working correctly though :( Anyone?
 
Last edited:
Well, after breaking out the logic analyzer, it finally works!

**broken link removed**

Code:
	// - a write to 0x800 addresses took 1.46s (scope)
	// 2048 nibbles = 1024 bytes = 1kbyte
	// 1kbyte / 1.46s = 701.4 bytes per second!
	//
	// - dram is finnicky until you understand it
	// then it becomes easy
	// 
	// - in the above test, k[] always came back with
	// six specific addresses:
	// 0x0062
	// 0x01C9
	// 0x0330
	// 0x0497
	// 0x05FE
	// 0x0765
	// 
	// (ive attached a spreadsheet of row vs column)
	// but all those addresses failed by returning 0x0F
	// all 1's... hmm. only a bit more code and id have
	// a functioning dram controller	
	//
	// - the dspic's speed surprised me aswell; whether i
	// record the addy and data or not made no difference
	// in the length of the for loop


Code:
#include <p30f4011.h>

void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void);
void timerInit(void);
void portInit(void);
void delayCycles(int);
unsigned char read(unsigned short);
void write(unsigned short, unsigned char);

int i; // refresh counter
unsigned char row, col;

#define FOSC 8000000
#define PLL 8
#define PS 64
#define calcPeriod (FOSC*PLL*0.004)/(2*PS)

#define CAS LATFbits.LATF0
#define RAS LATFbits.LATF1
#define OE LATFbits.LATF4
#define W LATFbits.LATF5
#define SUCCESS LATFbits.LATF6

// pin setup:
// portb - a0-a7
// porte - d0-d3
// f0 - /cas
// f1 - /ras
// f4 - /oe
// f5 - /we
// f6 - success led

int main(void)
{
	portInit();
	timerInit();

	unsigned char data = 0x08;
	unsigned short address = 0x123; // 0-7FF
	
	write(address, data); // write a nibble

	delayCycles(32000); // wait a long time to show refresh works
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);

	unsigned char temp = read(address); // read the nibble back

	if (temp == data) // see if it's correct
		SUCCESS = 1;

	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);
	delayCycles(32000);

	SUCCESS = 0;

	unsigned int i, j = 0;
	int k[20] = { 0 };
	int l[20] = { 0 };

	for (i = 0; i < 0x800; i++)
	{
		write(i, 0x0A);
		temp = read(i);

		if (temp != 0x0A)
		{	
			k[j] = i; // hold addy to examine
			l[j++] = temp; // hold data to examine
		}
	}

	SUCCESS = 1;
	Nop();

	// notes:
	//
	// - a write to 0x800 addresses took 1.46s (scope)
	// 2048 nibbles = 1024 bytes = 1kbyte
	// 1kbyte / 1.46s = 701.4 bytes per second!
	//
	// - dram is finnicky until you understand it
	// then it becomes easy
	// 
	// - in the above test, k[] always came back with
	// six specific addresses:
	// 0x0062
	// 0x01C9
	// 0x0330
	// 0x0497
	// 0x05FE
	// 0x0765
	// 
	// (ive attached a spreadsheet of row vs column)
	// but all those addresses failed by returning 0x0F
	// all 1's... hmm. only a bit more code and id have
	// a functioning dram controller	
	//
	// - the dspic's speed surprised me aswell; whether i
	// record the addy and data or not made no difference
	// in the length of the for loop

	while(1);

	return 0;
}								

void portInit()
{	
	ADPCFG = 0xFF;
	TRISB = 0x00;
	TRISE = 0x00;
	TRISF = 0x00;

	CAS = 1;
	RAS = 1;
	OE = 1;
	W = 1;
}

void timerInit()
{
	PR1 = calcPeriod;
	T1CON = 0; // clear t1con
	T1CONbits.TCKPS = 2; // prescale 64
 	IFS0bits.T1IF = 0; // clear flag
	IPC0bits.T1IP = 7; // high prio
 	IEC0bits.T1IE = 1; // enable interrupt
	T1CONbits.TON = 1; // start counting
}

void _T1Interrupt(void)
{
	// i should happen every ~4ms

	for (i = 0; i < 256; i++)
	{
		CAS = 0;
		Nop();
		RAS = 0;
		Nop();		
		CAS = 1;
		Nop();	
		RAS = 1;
		Nop();	
	}

 	IFS0bits.T1IF = 0;
}

void delayCycles(int cycles)
{
	while (cycles-- > 0);
}


unsigned char read(unsigned short address)
{
	unsigned char row = address / 8;
	unsigned char col = address % 8;
	unsigned char temp;

	// pin config
	RAS = 1;
	CAS = 1;
	OE = 1;
	W = 1;
	TRISE = 0x0F; // port e input

	delayCycles(10); // pause

	__asm__ volatile("disi #0x3FFF"); // disable interrupts 

	LATB = row; // move row address onto latb

	delayCycles(3);

	RAS = 0; // latch row

	delayCycles(3);

	LATB = col; // move col address onto latb

	delayCycles(6);

	CAS = 0; // latch column

	delayCycles(3);

	OE = 0; // enable output drivers

	delayCycles(3);

	temp = PORTE & 0x0F; // read nibble of data

	delayCycles(3);

	OE = 1; // disable output drivers

	delayCycles(3);

	CAS = 1;
	RAS = 1;

	delayCycles(6);

	RAS = 0;

	delayCycles(3);

	CAS = 0;
		
	__asm__ volatile("disi #0x0000"); // enable interrupts 

	return temp;
}

void write(unsigned short address, unsigned char data)
{
	unsigned char row = address / 8; // 0x24
	unsigned char col = address % 8; // 0x03

	RAS = 1;
	CAS = 1;
	OE = 1;
	W = 1;
	TRISE = 0x00; // port e output

	delayCycles(10); // pause

	__asm__ volatile("disi #0x3FFF"); // disable interrupts 

	LATB = row; // 0x24
	LATE = data; // 0x08

	delayCycles(3);

	RAS = 0;

	delayCycles(3);

	W = 0;

	delayCycles(3);

	LATB = col; // 0x03

	delayCycles(6);

	CAS = 0;

	delayCycles(6);	

	W = 1;

	delayCycles(3);

	CAS = 1;
	RAS = 1;

	delayCycles(6);

	RAS = 0;

	delayCycles(3);

	CAS = 0;

	__asm__ volatile("disi #0x0000"); // enable interrupts 
}

I love and hate assignments like this at the same time, theyre very frustrating to work thorough, but very rewarding in the end!
 

Attachments

  • dram spreadsheet.zip
    8.6 KB · Views: 190
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top