Hey guys! First off, let me start off by saying that I really appreciate these forums because up until now I've been able to debug any Arduino related issues with a simple search on these forums.
I'm posting here today regarding an issue with using the Arduino UNO as a NOR Flash chip programmer for an Atmel AT49F040 chip (Datasheet here). The goal with this project is to build a programmable Gameboy Cartridge but I won't get into to much detail about that.
To tackle the problem of not enough I/O I decided to use 3 TI SN54HC595 Shift Registers and below is a block diagram of my current hardware setup. The Arduino is connected to the address pins of the AT49F040 via the 3 shift registers, which share a Clock and Over-Riding Clear pins. IO0-IO7, OE,CE, and WE are connected directly to the Arduino. The shift registers and the AT49F040 are powered by an external 5V supply.
Also the pinout if anybody's interested:
const int sDta = 10;
const int sClk = 11;
const int sLtch = 12;
const int oE = A0;
const int wE = A1;
const int cE = A2;
const int io0 = 2;
const int io1 = 3;
const int io2 = 4;
const int io3 = 5;
const int io4 = 6;
const int io5 = 7;
const int io6 = 8;
const int io7 = 9;
This is a strong assumption but I believe that I'm able to read an arbitrary address since (according to the datasheet) the read sequence is just:
- Load the desired address on A0-A18
- Set CE low
- Set OE low
- Read IO0-IO7
This leads to believe that the following code snippet should achieve just that. (Where sDta is the Serial Data pin, sLtch is Over Ride Clear pin, sClk is the clock pin, and setInput() and setOutput() change pins IO0-IO7 to be inputs or outputs respectively.)
byte readChip(byte addrLsb, byte addrMsb)
{
byte data = 0;
setInput();
digitalWrite(sLtch, LOW);
shiftOut(sDta, sClk, MSBFIRST, 0);
shiftOut(sDta, sClk, MSBFIRST, addrMsb);
shiftOut(sDta, sClk, MSBFIRST, addrLsb);
digitalWrite(sLtch, HIGH);
digitalWrite(cE, LOW);
digitalWrite(oE, LOW);
bitWrite(data, 0, digitalRead(io0));
bitWrite(data, 1, digitalRead(io1));
bitWrite(data, 2, digitalRead(io2));
bitWrite(data, 3, digitalRead(io3));
bitWrite(data, 4, digitalRead(io4));
bitWrite(data, 5, digitalRead(io5));
bitWrite(data, 6, digitalRead(io6));
bitWrite(data, 7, digitalRead(io7));
digitalWrite(cE, HIGH);
digitalWrite(oE, HIGH);
setOutput();
return data;
}
The results I receive seem promising since I receive 0xFF and that is the default value for every address. However, since I'm having trouble with writing to the device this might not mean anything. I've changed the timing of the read to wait one clock cycle after dropping OE but that also returned 0xFF along with reading just before dropping OE which gave 0. This leads me to further believe that reading isn't a problem.
The write is a bit trickier but from what I've gathered writing a byte can be done like so:
- Load the address
- Set CE and WE to LOW in either order
- Wait a min of 50ns
- Load the Data
- Set CE and WE to HIGH in whichever order you chose
But to actually write to the device you need to do the 4 bus cycle operation which consists of:
- 5555 on the Address Bus, Load AA on the Data
- 2AAA on the Address Bus,Load 55 on the Data
- 5555 on the Address Bus,Load A0 on the Data
- Your desired Address, Load the Data to write in
For loading a single byte I've tried the following snippet:
void loadByte(byte hiByte, byte midByte, byte lowByte, byte data){
digitalWrite(sLtch, LOW);
shiftOut(sDta, sClk, MSBFIRST, hiByte);
shiftOut(sDta, sClk, MSBFIRST, midByte);
shiftOut(sDta, sClk, MSBFIRST, lowByte);
digitalWrite(sLtch, HIGH);
digitalWrite(wE, LOW);
digitalWrite(cE, LOW);
__asm__("nop\n\t");
digitalWrite(io0, bitRead(data, 7));
digitalWrite(io1, bitRead(data, 6));
digitalWrite(io2, bitRead(data, 5));
digitalWrite(io3, bitRead(data, 4));
digitalWrite(io4, bitRead(data, 3));
digitalWrite(io5, bitRead(data, 2));
digitalWrite(io6, bitRead(data, 1));
digitalWrite(io7, bitRead(data, 0));
digitalWrite(wE, HIGH);
digitalWrite(cE, HIGH);
}
I tried using the above snippet for the four bus cycle write operation but upon reading an address to verify I still get 0xFF. I've also wondered if it's possible that the Arduino takes too long to load the data so I also attempted this next snippet with the same result:
void loadByte(byte hiByte, byte midByte, byte lowByte, byte data){
digitalWrite(sLtch, LOW);
shiftOut(sDta, sClk, MSBFIRST, hiByte);
shiftOut(sDta, sClk, MSBFIRST, midByte);
shiftOut(sDta, sClk, MSBFIRST, lowByte);
digitalWrite(sLtch, HIGH);
digitalWrite(io0, bitRead(data, 7));
digitalWrite(io1, bitRead(data, 6));
digitalWrite(io2, bitRead(data, 5));
digitalWrite(io3, bitRead(data, 4));
digitalWrite(io4, bitRead(data, 3));
digitalWrite(io5, bitRead(data, 2));
digitalWrite(io6, bitRead(data, 1));
digitalWrite(io7, bitRead(data, 0));
digitalWrite(wE, LOW);
digitalWrite(cE, LOW);
__asm__("nop\n\t");
digitalWrite(wE, HIGH);
digitalWrite(cE, HIGH);
}
So what I'm wondering if it's possible that I'm either reading the timing sheet for the AT49F040 incorrectly or if the Arduino UNO is too slow to use as a programmer for this chip?
If anybody has any possible insight towards this issue I'd very much appreciate it. Also, if you feel I'm missing any information please let me know as well.
Thanks,
Josh