New member & question

Building your first 6502-based project? We'll help you get started here.
Post Reply
adrocha
Posts: 2
Joined: 10 May 2016

New member & question

Post by adrocha »

As a new member let me present myself.
My native language is not English so you have to be tolerant with my writing.
I work on IT as a business analyst - ERP implementations.
I have a good background on programming (c/c++). I never had the need to study assembler. Hardware and assembler is a complete new field to me.
About year ago I found a new hobby. I began to be interested on microcontrollers and made some projects on robotics with atmel chips.
One day found this site (6502.org) and I assume. I got the bug. I also want to build a single board computer. I also want to create my operating system, my basic and who knows what else.
So I decided to build a 6502 computer. And here I am with my first question.
While I am working on the schematics I am also testing my ROM (AT28C256). Using an Atmega16 I created two routines one to write and another to read from the eeprom. I only use the low address. High address is wired to ground.
Both routines work well. I can write and I can read. If my program just calls the write routine it writes. If my program just calls the read routine it reads. But if I use both routines (write and then read) the values that it reads aren’t real.

Can anybody help me with this?
I know this is not a microcontroller forum, but the objective is to use the microcontroller to study the timing and help to define the wiring.

This is my code:

Code: Select all

#include <avr/io.h>
#include <util/delay.h>


#define LedDDR			DDRC
#define LedPort			PORTC
#define ControlPort		PORTD
#define ControlDDR		DDRD	
#define DataPort		PORTB
#define DataDDR		DDRB
#define DataPIN			PINB
#define AddressPort		PORTA
#define AddressDDR		DDRA

#define MemRW			3
#define MemOE			2
#define MemCE			1

void writeEPROM(unsigned char address, unsigned char c);
unsigned char readEPROM(unsigned char address);

void writeEPROM(unsigned char address, unsigned char c) 
{
	DataDDR |= 0xFF;

	ControlPort |= (1 << MemRW | 1 << MemCE | 1 << MemOE);
	ControlPort &= ~(1 << MemRW);
	AddressPort = address;	
	//asm volatile ("nop");
	ControlPort &= ~(1 << MemCE);	
	DataPort = c;	
	_delay_ms(20);	
	ControlPort |= (1 << MemCE);
}

unsigned char readEPROM(unsigned char address)
{
	unsigned char c;
	
	DataDDR |= 0x00;
	ControlPort |= (1 << MemOE | 1 << MemCE | 1 << MemRW);
	//ControlPort |= (1 << MemRW);	
	AddressPort = address;
	ControlPort &= ~(1 << MemOE | 1 << MemCE);
	_delay_ms(1);
	c = DataPIN;
	ControlPort |= (1 << MemOE | 1 << MemCE);
	
	return c;
}

void write(void) {
	writeEPROM(0b00000000, 0b10000000);
	writeEPROM(0b00000001, 0b10000001);
	writeEPROM(0b00000010, 0b10000010);
	writeEPROM(0b00000011, 0b10000011);
	writeEPROM(0b00000100, 0b10000100);
	writeEPROM(0b00000101, 0b10000101);
	writeEPROM(0b00000110, 0b10000110);	
	writeEPROM(0b00000111, 0b10000111);
	writeEPROM(0b00001000, 0b10001000);
	writeEPROM(0b00001001, 0b10001001);
	writeEPROM(0b00001010, 0b10001010);	
	
	LedPort = 0xFF;
}

void read(void) {
	LedPort = readEPROM(0b00000000); _delay_ms(1000);
	LedPort = readEPROM(0b00000001); _delay_ms(1000);
	LedPort = readEPROM(0b00000010); _delay_ms(1000);
	LedPort = readEPROM(0b00000011); _delay_ms(1000);
	LedPort = readEPROM(0b00000100); _delay_ms(1000);
	LedPort = readEPROM(0b00000101); _delay_ms(1000);
	LedPort = readEPROM(0b00000110); _delay_ms(1000);
	LedPort = readEPROM(0b00000111); _delay_ms(1000);
	LedPort = readEPROM(0b00001000); _delay_ms(1000);
	LedPort = readEPROM(0b00001001); _delay_ms(1000);	
	LedPort = readEPROM(0b00001010); _delay_ms(1000);	
	LedPort = readEPROM(0b00001011); _delay_ms(1000);		
	LedPort = 0xFF;	
}



int main(void) {
	LedDDR = 0xFF;
	ControlDDR |= 0xFF;
	AddressDDR |= 0xFF;
	
	//write();
	read();

	while(1) {
	}
	return 0;
}
Last edited by adrocha on Wed May 11, 2016 10:45 pm, edited 1 time in total.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: New member & question

Post by GARTHWILSON »

Welcome! I'm sorry I myself don't have an answer about your AVR code, but I will comment that you can get your code formatting to show correctly if you put [code] and [/code] around it. Then the forum software won't slam everything up against the left margin. Be sure to check out the 6502 primer, about building your own 6502 computer.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
hoglet
Posts: 367
Joined: 29 Jun 2014

Re: New member & question

Post by hoglet »

Welcome adrocha!
adrocha wrote:
But if I use both routines (write and then read) the values that it reads aren’t real.
Have you tried putting a big delay (e.g. 1 second) between write and read?

Dave
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: New member & question

Post by BigEd »

Hi Adrocha, and welcome.

When you're dealing with chips, the datasheets are your friends - there's a lot in them but it's worth getting the knack of reading them (because sometimes you have to put the pieces together like a puzzle.)

In the case of your ROM (or in fact EEPROM) there's a datasheet here:
http://www.atmel.com/images/doc0006.pdf
and in the feature list we see
Quote:
• Fast Write Cycle Times
– Page Write Cycle Time: 3 ms or 10 ms Maximum
– 1 to 64-byte Page Write Operation
So, you will have to wait for a while before the writes you make are committed. There's usually a protocol to let you know when the write is done, or you can just wait for 10ms. Note that you can't write more than 64 bytes in one batch, and there will be a time window in which to get those 64 bytes to the chip.

Long story short: when using an EEPROM, it's nice and simple as a ROM but writing to it needs a little finesse.
Last edited by BigEd on Fri May 13, 2016 9:15 am, edited 1 time in total.
Klaus2m5
Posts: 442
Joined: 28 Jul 2012
Location: Wiesbaden, Germany

Re: New member & question

Post by Klaus2m5 »

I see you have _delay_ms(20); in writeEPROM. The delay must be after CE & WE are high again!
6502 sources on GitHub: https://github.com/Klaus2m5
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: New member & question

Post by BigEd »

(... and I didn't even read the code! Oops.)
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: New member & question

Post by floobydust »

Referring to the Atmel datasheet, you should look at using the toggle bit mode to confirm completion of the write cycle. I have a short section of (65C02) code that does the write, uses the bit toggle mode to confirm, then compares the data.

Code: Select all

BYTE_WRS	SEI	;Disable interrupts
				LDA	(SRCL)	;Get source byte
				STA	(TGTL)	;Write to target byte
				LDA	(TGTL)	;Read target byte (EEPROM)
				AND	#%01000000	;Mask off bit 6 - toggle bit
BYTE_WLP	STA	TEMP3	;Store in Temp location
				LDA	(TGTL)	;Read target byte again (EEPROM)
				AND	#%01000000	;Mask off bit 6 - toggle bit
				CMP	TEMP3	;Compare to last read (toggles if still in write mode)
				BNE	BYTE_WLP	;Branch back if not done
				CLI	;Re-enable interrupts
BYTE_WRE	RTS	;Return to caller
adrocha
Posts: 2
Joined: 10 May 2016

Re: New member & question

Post by adrocha »

At last I made it work.
At the begging I just move de delay as Klaus2m5 suggested. It worked I could write and read but that irritating problem continue. I couldn't read after the write. I could write after read but not the opposite. Something was wrong on the state of the system after the write function.
After some more tests I found the solution.

This is my new code for the function:

Code: Select all

void writeEPROM(unsigned char address, unsigned char c) 
{
	DataDDR |= 0xFF;

	ControlPort |= (1 << MemRW | 1 << MemCE | 1 << MemOE);
	ControlPort &= ~(1 << MemRW);
	AddressPort = address;	
	ControlPort &= ~(1 << MemCE);	
	DataPort = c;	
	ControlPort |= (1 << MemCE | 1 << MemRW);
	_delay_ms(10);	
	DataDDR = 0x00;	
}
The main difference is the last line "DataDDR = 0x00;". I don´t know why this fix the problem because at the beggining of the read function I have the same instruction. It's some stange request of the microcontroller. I thing the basic process of writing and reading is correct. The problem was the microcontroller.

My next step will be the implementation of the toggle bit as sugested by floobydust. And then I will finish the scematics for my computer.

I want to thank you all of you that helped me to solve this problem. It's nice to find a place where we can ask some questions and receive positive and constructive feedback.
Aslak3
Posts: 258
Joined: 05 Aug 2013
Location: Southampton, UK
Contact:

Re: New member & question

Post by Aslak3 »

Just FWIW, I've built an AVR based AT28C256 programmer. The address bus is presented on a pair of 8 bit counters, clocked and reset by IO pins on the controller.

Overview here: http://aslak3.blogspot.co.uk/2013/04/ee ... d-and.html
Schematic here: http://aslak3.blogspot.co.uk/2013/03/ee ... rcuit.html

The programmer is hooked up to the PC via a serial port. The "client" software is written in C and uses Linux/POSIX serial port calls.

Source code for the programmer, including the client program, is available on github: https://github.com/aslak3/eepromprogrammer

I just reminded myself how the programmer dealt with writes. A 10 ms delay is inserted after each 64 byte page is written. There are no doubt cleverer ways to deal with the page writes, but the delay method is also very reliable, and simple. 10uS delays were used on the transition of the EEPROM control pins.
8 bit fun and games: https://www.aslak.net/
Post Reply