6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Mar 28, 2024 11:11 am

All times are UTC




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: New member & question
PostPosted: Wed May 11, 2016 9:30 pm 
Offline

Joined: Tue May 10, 2016 8:18 pm
Posts: 2
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:
#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.

Top
 Profile  
Reply with quote  
PostPosted: Wed May 11, 2016 10:18 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8412
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2016 6:58 am 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 330
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


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2016 7:03 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10760
Location: England
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.

Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2016 8:03 am 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
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


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2016 9:03 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10760
Location: England
(... and I didn't even read the code! Oops.)


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2016 3:36 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
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:
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

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Fri May 13, 2016 8:51 am 
Offline

Joined: Tue May 10, 2016 8:18 pm
Posts: 2
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:
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.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 13, 2016 12:20 pm 
Offline

Joined: Mon Aug 05, 2013 10:43 pm
Posts: 258
Location: Southampton, UK
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/


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: